html, body {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

/* Beta/test environment: an amber "BETA" chip in the top bar + a thin amber strip along the top, so this
   instance is never mistaken for production. Driven by the beta.<domain> host (see MainLayout). */
/* Language switch at the bottom of the left nav (global NL/EN toggle). */
.nav-lang-switch {
    margin-top: auto; padding: 12px 1.5rem; display: flex; align-items: center; justify-content: space-between;
    gap: 8px; border-top: 1px solid rgba(255,255,255,.08);
}
.nav-lang-label { font-size: .8rem; color: #b7bec9; white-space: nowrap; }
.nav-lang-opts { display: inline-flex; border: 1px solid rgba(255,255,255,.2); border-radius: 6px; overflow: hidden; }
.nav-lang-opt {
    border: 0; background: transparent; color: #cdd3db; font-size: .74rem; font-weight: 600;
    padding: 3px 9px; cursor: pointer; line-height: 1.4;
}
.nav-lang-opt:hover { background: rgba(255,255,255,.08); }
.nav-lang-opt.active { background: #1b6ec2; color: #fff; }
/* The nav column is a full-height flex column (NavMenu.razor.css); `margin-top:auto` on the switch
   (above) pins it to the bottom. Keep the nav list from stretching so the auto-margin gets the slack. */
.nav-scrollable > .nav { flex: 0 0 auto; }

/* Empty-floor prompt: a new floor has no maps until the user adds one. */
.map-empty-hint {
    position: absolute; inset: 0; z-index: 6; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 8px; text-align: center; pointer-events: none;
}
.map-empty-hint > * { pointer-events: auto; }
.map-empty-title { font-size: 1rem; font-weight: 600; color: #8b93a7; }
.map-empty-sub { font-size: .82rem; color: #6b7280; max-width: 340px; }

.beta-badge {
    display: inline-flex; align-items: center; font-size: .68rem; font-weight: 700; letter-spacing: .06em;
    color: #241a05; background: #f0ad4e; border-radius: 5px; padding: 1px 7px; margin-right: 4px;
    box-shadow: 0 1px 3px rgba(0,0,0,.3);
}
.page.beta-env { box-shadow: inset 0 3px 0 #f0ad4e; }

/* Consistent scaling across resolutions: keep the current size on normal screens (~≤1900px stays 16px)
   and grow the rem-based UI on large / high-res monitors so it doesn't look tiny. The editor's map has
   its own zoom and uses px, so it's unaffected. */
html { font-size: clamp(16px, 0.42vw + 8px, 21px); }

h1:focus {
    outline: none;
}

a, .btn-link {
    color: var(--bs-link-color, #2dd4bf);
}

.btn-primary {
    color: #06251f;
    background-color: #19c3b1;
    border-color: #19c3b1;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
  box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

.content {
    padding-top: 1.1rem;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid red;
}

.validation-message {
    color: red;
}

#blazor-error-ui {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.loading-progress {
    position: absolute;
    display: block;
    width: 8rem;
    height: 8rem;
    inset: 20vh 0 auto 0;
    margin: 0 auto 0 auto;
}

    .loading-progress circle {
        fill: none;
        stroke: #e0e0e0;
        stroke-width: 0.6rem;
        transform-origin: 50% 50%;
        transform: rotate(-90deg);
    }

        .loading-progress circle:last-child {
            stroke: #1b6ec2;
            stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
            transition: stroke-dasharray 0.05s ease-in-out;
        }

.loading-progress-text {
    position: absolute;
    text-align: center;
    font-weight: bold;
    inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
}

    .loading-progress-text:after {
        content: var(--blazor-load-percentage-text, "Loading");
    }

code {
    color: #c02d76;
}

/* Rendered assistant markdown (Assistant.razor) */
.assistant-md > :first-child { margin-top: 0; }
.assistant-md > :last-child { margin-bottom: 0; }

.assistant-md h1, .assistant-md h2, .assistant-md h3,
.assistant-md h4, .assistant-md h5, .assistant-md h6 {
    margin: 0.8rem 0 0.4rem;
    font-weight: 600;
    line-height: 1.25;
}
.assistant-md h1 { font-size: 1.5rem; }
.assistant-md h2 { font-size: 1.3rem; }
.assistant-md h3 { font-size: 1.15rem; }

.assistant-md p { margin: 0 0 0.6rem; }
.assistant-md ul, .assistant-md ol { margin: 0 0 0.6rem 1.4rem; }
.assistant-md li { margin: 0.15rem 0; }

.assistant-md pre {
    background: #11151d;
    border: 1px solid #2a3242;
    border-radius: 6px;
    padding: 0.75rem 1rem;
    overflow-x: auto;
    margin: 0 0 0.6rem;
}
.assistant-md pre code {
    color: #cdd3df;          /* reset inline-code colour inside fenced blocks */
    background: none;
    padding: 0;
    white-space: pre;
}
.assistant-md :not(pre) > code {
    background: #232b3a;
    color: #e1b3d0;
    padding: 0.1rem 0.3rem;
    border-radius: 4px;
}

.assistant-md blockquote {
    margin: 0 0 0.6rem;
    padding: 0.1rem 0 0.1rem 0.9rem;
    border-left: 3px solid #39435a;
    color: #8b93a7;
}

.assistant-md table {
    border-collapse: collapse;
    margin: 0 0 0.6rem;
}
.assistant-md th, .assistant-md td {
    border: 1px solid #2c3546;
    padding: 0.3rem 0.6rem;
}
.assistant-md th { background: #1b212e; }

.assistant-md a { color: #2dd4bf; }

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}
/* ---- Floor-plan editor ---- */
.editor-canvas {
    width: 100%;
    height: 100%;
    /* Transparent + stacked above the zone-fill layer, so component nodes paint on top of the zones while the
       floor plan + zone fills (lower z-index layers) show through. The grid moves to the wrapper (below). */
    background: transparent;
    position: relative;
    z-index: 3;
}

.floor-background {
    pointer-events: none;
    display: block;
    user-select: none;
}

.component-node {
    position: relative;
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 110px;
    padding: 8px 12px;
    background: #fff;
    border: 2px solid var(--node-color, #0d6efd);
    border-radius: 6px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .15);
    font-size: 14px;
    user-select: none;
    cursor: move;
    /* User-adjustable display size (Settings ▸ Map component size) plus per-node rotation; centred so nodes don't drift. */
    transform: scale(var(--cs, 1)) rotate(var(--rot, 0deg));
    transform-origin: 50% 50%;
}
.component-node.selected {
    box-shadow: 0 0 0 2px #6e9fd4, 0 1px 6px rgba(0, 0, 0, .25);
}
.component-node-icon { font-size: 18px; line-height: 1; }
/* Indicative direction triangle attached to the top/bottom of the label — subtle, icon-sized, points outward
   to mark the device's real position. Sits inside the node so it rotates with the label. */
.component-node-pointer {
    position: absolute; left: 50%; transform: translateX(-50%);
    width: 0; height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent;
    opacity: .6; pointer-events: none;
}
.component-node-pointer.top { bottom: 100%; margin-bottom: 2px; border-bottom: 7px solid var(--node-color, #0d6efd); }
.component-node-pointer.bottom { top: 100%; margin-top: 2px; border-top: 7px solid var(--node-color, #0d6efd); }
.component-node-text { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
.component-node-label { white-space: nowrap; color: #212529; }
.component-node-code {
    font-size: 10px; font-weight: 600; color: #6b7280;
    white-space: nowrap; letter-spacing: .2px;
}
/* Fixtures render small: just icon + label, tighter padding. The whole chip is filled with the
   component's colour (bus-derived for devices on a bus), with contrasting text for readability. */
.component-node.compact {
    min-width: 0;
    gap: 5px;
    padding: 3px 7px;
    border-width: 1px;
    border-radius: 5px;
    font-size: 11px;
    background: var(--node-color, #0d6efd);
    border-color: var(--node-color, #0d6efd);
}
.component-node.compact .component-node-icon { font-size: 13px; }
.component-node.compact .component-node-label { font-weight: 600; color: #212529; }   /* always dark ink, regardless of chip colour */
/* Room-position marker: 4 side handles (shown on hover) to drag out a physical marker; dotted leader line. */
.cn-handle {
    position: absolute; border-radius: 50%;
    /* Size in inverse of the diagram zoom (--dz) so handles stay a constant on-screen size at any zoom. */
    width: calc(9px / var(--dz, 1)); height: calc(9px / var(--dz, 1));
    background: #19c3b1; border: calc(1.5px / var(--dz, 1)) solid #06231f; box-shadow: 0 1px 2px rgba(0,0,0,.4);
    opacity: 0; pointer-events: none; cursor: crosshair; z-index: 5;
}
.component-node:hover .cn-handle { opacity: 1; pointer-events: auto; }
.cn-handle.top { top: 0; left: 50%; transform: translate(-50%, -50%); }
.cn-handle.bottom { top: 100%; left: 50%; transform: translate(-50%, -50%); }
.cn-handle.left { left: 0; top: 50%; transform: translate(-50%, -50%); }
.cn-handle.right { left: 100%; top: 50%; transform: translate(-50%, -50%); }

.marker-layer { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; z-index: 6; }
.marker-line { stroke: #19c3b1; stroke-width: 1.5; stroke-dasharray: 2.5 3; }
.marker-dot { fill: #19c3b1; stroke: #06231f; stroke-width: 1.5; }

/* Highlight mode: unrelated nodes fade right back so only the selected/related ones light up. */
.component-node.dimmed { border-color: #d3d8e0; opacity: .28; filter: grayscale(0.6); }
.component-node.dimmed.selected { border-color: #19c3b1; opacity: 1; filter: none; }   /* selection ring still wins */

/* DALI-group assign popup */
.group-picker .gp-current { font-size: .82rem; color: #aeb4c2; margin-bottom: 8px; }
.gp-scroll { max-height: 52vh; overflow: auto; display: flex; flex-direction: column; gap: 12px; padding-right: 2px; }
.gp-bus { border: 1px solid #2c3546; border-radius: 9px; padding: 9px 11px; background: #161c27; }
.gp-bus.ctx { border-color: #19c3b1; box-shadow: 0 0 0 1px #19c3b155 inset; }
.gp-bus-head { font-size: .76rem; color: #8b93a7; margin-bottom: 8px; }
.gp-bus-head .gp-bus-name { color: #e6e9ef; font-weight: 600; margin-left: 4px; }
.gp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(86px, 1fr)); gap: 6px; }
.gp-cell {
    display: flex; align-items: center; justify-content: space-between; gap: 6px;
    background: #1b212e; border: 1px solid #2c3546; border-radius: 7px; padding: 6px 8px;
    font-size: .78rem; color: #c7ccd6; cursor: pointer;
}
.gp-cell:hover { border-color: #19c3b1; color: #e6e9ef; }
.gp-cell.empty { color: #6b7280; }
.gp-cell.active { border-color: #f0ad4e; background: #2a2113; color: #ffd98a; }
.gp-cell-count {
    flex: 0 0 auto; font-size: .68rem; font-weight: 700; color: #06231f;
    background: #19c3b1; border-radius: 999px; padding: 0 6px; min-width: 18px; text-align: center;
}
.gp-cell.active .gp-cell-count { background: #f0ad4e; }
.gp-cell-type {
    flex: 0 0 auto; font-size: .66rem; color: #ffd98a;
    background: #2a2113; border: 1px solid #4a3a1a; border-radius: 4px; padding: 0 5px;
}
.gp-type { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.gp-type label { font-size: .78rem; color: #aeb4c2; margin: 0; }
.gp-type select { max-width: 220px; }
.gp-type-hint { font-size: .72rem; color: #6b7280; }

/* Ports (replicated from the library's default-node styling, scoped to our node) */
.component-node .diagram-port {
    position: absolute;
    width: 12px;
    height: 12px;
    margin: -6px;
    background: var(--node-color, #0d6efd);
    border: 2px solid #fff;
    border-radius: 50%;
    opacity: 0;
    transition: opacity .15s ease;
    cursor: crosshair;
}
.component-node:hover .diagram-port,
.component-node .diagram-port.has-links { opacity: 1; }
.component-node .diagram-port.top { top: 0; left: 50%; }
.component-node .diagram-port.bottom { bottom: 0; left: 50%; }
.component-node .diagram-port.left { left: 0; top: 50%; }
.component-node .diagram-port.right { right: 0; top: 50%; }

/* Drag-to-pan over the floor plan: the background is a locked node whose wrapper would
   otherwise swallow the pointer, so make it pointer-transparent. Panning then works
   anywhere on the canvas (empty space or over the plan). */
.diagram-node:has(> .floor-background) {
    pointer-events: none;
}

/* ---- Tree view (dark) ---- */
.tv {
    color: #c7ccd6;
    font-size: 0.82rem;   /* rem so the sidebar tree scales up on large screens too (was 13px) */
    padding: 6px 4px 12px;
}
.tv-title-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 8px 4px 10px;
}
.tv-title {
    font-size: 11px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #8b93a7;
    font-weight: 600;
}
.tv-actions { display: inline-flex; gap: 2px; }
.tv-act-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    border: 0;
    background: transparent;
    color: #6b7488;
    border-radius: 5px;
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
}
.tv-act-btn:hover:not(:disabled) { color: #19c3b1; background: rgba(255,255,255,.06); }
.tv-act-btn:disabled { opacity: .35; cursor: default; }
.tv-act-btn.on { color: #ffd98a; background: #2a2113; }   /* viewing another floor's tree */

/* Floor picker (Components tree → show another floor) */
.floor-picker { max-width: 340px; }
.floor-picker-list { display: flex; flex-direction: column; gap: 4px; margin: 4px 0 2px; }
.floor-picker-item {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    background: #1b212e; border: 1px solid #2c3546; border-radius: 7px; padding: 8px 12px;
    color: #c7ccd6; font-size: .85rem; cursor: pointer; text-align: left;
}
.floor-picker-item:hover { border-color: #19c3b1; color: #e6e9ef; }
.floor-picker-item.active { border-color: #19c3b1; background: #12241f; color: #d7fff8; font-weight: 600; }
.floor-picker-tag {
    font-size: .66rem; color: #8b93a7; background: #232b3a; border: 1px solid #2c3546;
    border-radius: 4px; padding: 0 5px;
}
.tv-search {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 4px 8px 8px;
    padding: 6px 9px;
    background: #11151d;
    border: 1px solid #2a3242;
    border-radius: 8px;
}
.tv-search-icon { color: #6b7488; flex: 0 0 auto; }
.tv-search-input {
    border: 0; outline: 0; background: transparent; color: #cdd3df;
    width: 100%; font-size: 13px;
}
.tv-search-input::placeholder { color: #5b6477; }

.tv-row {
    position: relative;
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 4px 6px;
    padding: 7px 9px;
    color: #c7ccd6;
    background: linear-gradient(180deg, #283143 0%, #222a39 100%);
    border: 1px solid #2c3546;
    border-radius: 7px;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.04), 0 1px 2px rgba(0,0,0,.35);
    cursor: pointer;
    user-select: none;
}
.tv-row:hover { filter: brightness(1.12); }
.tv-row.selected { border-color: #19c3b1; box-shadow: 0 0 0 1px #19c3b1, 0 1px 2px rgba(0,0,0,.35); }
/* Unplaced item: keep it readable, but mark it with a diagonal hatch overlay. */
.tv-row.muted { font-style: italic; color: #aeb6c5; }
.tv-row.muted::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 7px;
    pointer-events: none;
    background: repeating-linear-gradient(
        45deg,
        transparent 0, transparent 7px,
        rgba(139, 147, 167, .22) 7px, rgba(139, 147, 167, .22) 9px);
}

.tv-accent { width: 3px; height: 16px; border-radius: 2px; flex: 0 0 auto; }

.tv-eye {
    flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; padding: 0; border: 0; background: transparent; cursor: pointer;
    color: #7f8aa3; border-radius: 50%;
}
.tv-eye.on { color: #cdd3df; }
.tv-eye.off { color: #4b5468; }
.tv-eye:hover { color: #19c3b1; }

.tv-caret {
    flex: 0 0 auto; width: 14px; height: 14px; padding: 0; border: 0; background: transparent;
    color: #8b93a7; font-size: 9px; line-height: 14px; cursor: pointer;
    transition: transform .12s ease;
}
.tv-caret.open { transform: rotate(90deg); }
.tv-caret-spacer { flex: 0 0 auto; width: 14px; }

.tv-icon { flex: 0 0 auto; font-size: 14px; line-height: 1; }
/* Row body: icon + name on top, full-width labelcode underneath (wraps, never clipped). */
.tv-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.tv-main-top { display: flex; align-items: center; gap: 6px; min-width: 0; }
.tv-label { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tv-sublabel {
    font-size: .66rem; color: #8b93a7; line-height: 1.2; letter-spacing: .2px;
    white-space: normal; overflow-wrap: anywhere; word-break: break-all;   /* fit the whole code */
    font-family: ui-monospace, Menlo, Consolas, monospace;
}

/* Compact member row under a DALI group: tiny, code-only, dim. */
.tv-row-compact {
    display: flex; align-items: center; gap: 6px; cursor: pointer;
    margin: 1px 6px 1px 0; padding: 1px 0;
}
.tv-compact-code {
    font-family: ui-monospace, Menlo, Consolas, monospace; font-size: .66rem;  /* match the parent's code (.tv-sublabel) */
    color: #7c8597; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tv-row-compact:hover .tv-compact-code { color: #c1c7d3; }

.tv-children {
    margin-left: 16px;
    border-left: 1px solid rgba(255,255,255,.08);
    padding-left: 4px;
    /* Animate open/closed by transitioning the grid row from 0fr→1fr (collapses to auto height). */
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows .18s ease;
}
.tv-children.open { grid-template-rows: 1fr; }
.tv-children-inner { overflow: hidden; min-height: 0; }
@media (prefers-reduced-motion: reduce) { .tv-children { transition: none; } }

/* ---- Editor shell (side panels + canvas) ---- */
.editor-shell {
    display: flex;
    /* Fill the viewport below the top bar (3.5rem) + content padding (1.1rem), leaving a small gap. */
    height: calc(100vh - 6rem);
    border: 1px solid #ced4da;
    border-radius: 6px;
    overflow: hidden;
}
.editor-side {
    position: relative;
    flex: 0 0 290px;
    width: 290px;
    background: #1b212e;
    overflow: hidden;
    border-right: 1px solid #0d1117;
    display: flex;
    flex-direction: column;
}
/* The two trees (Zones + Components) scroll INDEPENDENTLY, so collapsing a floor in one never
   reflows/scrolls the other (previously the shared scroll jumped up to the Zones tree). */
.editor-side-body { flex: 1; min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
.editor-side-body > .tv { display: flex; flex-direction: column; min-height: 0; }
.editor-side-body > .tv:first-child { flex: 0 1 auto; max-height: 45%; }   /* Zones */
.editor-side-body > .tv:last-child { flex: 1 1 0; }                        /* Components */
.editor-side-body > .tv > .tv-body { flex: 1; min-height: 0; overflow-y: auto; }

/* Docked: drag the right edge to change the sidebar width. */
.dock-resize {
    position: absolute; top: 0; right: 0; width: 6px; height: 100%;
    cursor: ew-resize; z-index: 3;
}
.dock-resize:hover { background: linear-gradient(to right, transparent, #19c3b155); }

/* Detached: a floating, movable, resizable panel (still in the same DOM, so drag & drop keeps working). */
.editor-side.floating {
    position: fixed;
    z-index: 40;
    flex: none;
    border: 1px solid #2c3546;
    border-right: 1px solid #2c3546;
    border-radius: 10px;
    box-shadow: 0 14px 46px rgba(0, 0, 0, .55);
}
.panel-titlebar {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 8px 6px 12px; cursor: move; user-select: none;
    background: #232b3a; border-bottom: 1px solid #2c3546; border-radius: 10px 10px 0 0;
}
.panel-titlebar-label { font-size: .8rem; font-weight: 600; color: #c7ccd6; }
.panel-titlebar .panel-btn {
    margin-left: auto; background: transparent; border: 1px solid #3a4558; color: #c7ccd6;
    border-radius: 6px; font-size: .74rem; padding: 2px 8px; cursor: pointer;
}
.panel-titlebar .panel-btn:hover { border-color: #19c3b1; color: #fff; }
.panel-resize {
    position: absolute; right: 0; bottom: 0; width: 18px; height: 18px; cursor: nwse-resize; z-index: 2;
}
.panel-resize::after {
    content: ""; position: absolute; right: 3px; bottom: 3px; width: 8px; height: 8px;
    border-right: 2px solid #5a6473; border-bottom: 2px solid #5a6473;
}
.panel-drag-capture { position: fixed; inset: 0; z-index: 100; }
.panel-drag-capture.move { cursor: move; }
.panel-drag-capture.resize { cursor: nwse-resize; }
.panel-drag-capture.hresize { cursor: ew-resize; }
.editor-side .project-pick {
    margin: 8px;
}
/* Own stacking context (z-index:0) so the canvas layers (zones/guides) stay below the app chrome
   (top bar z-1, sidebar, dropdowns), and clip so nothing spills onto the sidebar. */
.editor-canvas-wrap {
    flex: 1; position: relative; min-width: 0; overflow: hidden; z-index: 0;
    /* The grid backdrop lives here (behind the floor plan + zone + component layers, which are transparent). */
    background: #e9ecef;
    background-image: radial-gradient(#dee2e6 1px, transparent 1px);
    background-size: 24px 24px;
}

/* Empty state when a project has no floor yet. */
.editor-empty {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; z-index: 4;
}
.editor-empty-card {
    background: #1b212e; border: 1px solid #2c3546; border-radius: 10px;
    padding: 20px 26px; text-align: center; color: #c7ccd6; box-shadow: 0 6px 20px rgba(0,0,0,.4);
}

/* ===================== Projects page ===================== */
.project-grid {
    display: grid; gap: 14px;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
.project-card {
    background: #1b212e; border: 1px solid #2c3546; border-radius: 10px;
    padding: 14px 16px; cursor: pointer; transition: border-color .15s ease, transform .05s ease;
    display: flex; flex-direction: column; gap: 6px;
}
.project-card:hover { border-color: #19c3b1; }
.project-card:active { transform: translateY(1px); }
.project-card-top { display: flex; align-items: center; gap: 8px; }
.project-name { font-weight: 600; color: #e6e9ef; font-size: 1.02rem; }
.project-meta { color: #8b93a7; font-size: .82rem; }
.project-notes {
    color: #aeb4c2; font-size: .8rem; margin-top: 2px;
    overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.project-card-actions { display: flex; gap: 6px; margin-top: 10px; align-items: center; flex-wrap: wrap; }
/* Keep each action button on one line and let it size to its label, so a longer word (e.g. NL "Publiceren")
   can't shrink a button and wrap its icon onto a second line — which made that button taller than its row. */
.project-card-actions .btn { white-space: nowrap; flex: 0 0 auto; }
/* Projects cards have four actions that don't fit one row once translated (NL labels are wider), so lay them
   out as a tidy 2×2 grid that stays aligned in any language. Components/Typicals cards carry .comp-card and
   have fewer actions, so they keep the plain wrapping row above. */
.project-card:not(.comp-card) .project-card-actions { display: grid; grid-template-columns: 1fr 1fr; }
.project-card:not(.comp-card) .project-card-actions .btn { width: 100%; margin: 0; }

.status-badge {
    margin-left: auto; font-size: .7rem; font-weight: 600; padding: 2px 8px; border-radius: 999px;
    white-space: nowrap;
}
.status-active { background: #0f766e; color: #eafffb; }
.status-hold   { background: #7c5e10; color: #fff5da; }
.status-done   { background: #334155; color: #cbd5e1; }

.projects-empty {
    background: #1b212e; border: 1px dashed #39435a; border-radius: 10px;
    padding: 28px; text-align: center; color: #c7ccd6; max-width: 420px;
}

/* Publish dialog */
.publish-group { border: 1px solid #2c3546; border-radius: 9px; padding: 10px 12px; background: #161c27; }
.publish-group-title { font-size: .72rem; text-transform: uppercase; letter-spacing: .03em; color: #8b93a7; margin-bottom: 6px; }
.publish-opt { display: flex; align-items: center; gap: 8px; margin: 0; padding: 3px 0; cursor: pointer; color: #c7ccd6; font-size: .88rem; }
.publish-opt .form-check-input { margin: 0; }

/* Project create/edit form (in the styled modal) */
.modal-card.modal-card-wide { width: min(460px, 92vw); }
.proj-form { display: flex; flex-direction: column; gap: 2px; }
.proj-form label { font-size: .78rem; color: #8b93a7; margin: 8px 0 2px; }
.proj-form label:first-child { margin-top: 0; }

/* ---- Components catalog page ---- */
.comp-card { gap: 8px; }
.comp-card-top { display: flex; align-items: flex-start; gap: 10px; }
.comp-icon {
    flex: 0 0 auto; width: 38px; height: 38px; border-radius: 9px;
    display: grid; place-items: center; font-size: 1.2rem; line-height: 1;
}
.comp-title { display: flex; flex-direction: column; min-width: 0; }
/* Truncate a long component / typical name to one line with an ellipsis instead of overflowing the card. */
.comp-title .project-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.comp-key { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: .72rem; color: #7c8597; }
.comp-code {
    margin-left: auto; font-family: ui-monospace, Menlo, Consolas, monospace; font-weight: 700;
    font-size: .72rem; padding: 2px 7px; border-radius: 6px;
    color: var(--c, #19c3b1); border: 1px solid color-mix(in srgb, var(--c, #19c3b1) 45%, transparent);
}
.comp-flags { display: flex; flex-wrap: wrap; gap: 6px; }
.comp-flag { font-size: .72rem; color: #8b93a7; }
.comp-flag.on { color: #5ec8bb; }
.comp-rel { display: flex; gap: 6px; font-size: .78rem; align-items: baseline; }
.comp-rel-label { flex: 0 0 58px; color: #7c8597; font-size: .72rem; text-transform: uppercase; letter-spacing: .03em; }
.comp-chips { color: #c1c7d3; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }

.comp-search { max-width: 260px; }

.bus-table {
    width: 100%; max-width: 560px; border-collapse: collapse;
    background: #1b212e; border: 1px solid #2c3546; border-radius: 10px; overflow: hidden;
}
.bus-table th, .bus-table td {
    text-align: left; padding: 8px 14px; font-size: .84rem; border-bottom: 1px solid #242c3b;
}
.bus-table thead th {
    color: #7c8597; font-size: .72rem; text-transform: uppercase; letter-spacing: .03em; font-weight: 600;
}
.bus-table tbody tr:last-child td { border-bottom: 0; }
.bus-table .num { text-align: right; font-variant-numeric: tabular-nums; color: #c1c7d3; }
.bus-name { color: #e6e9ef; }
.bus-code {
    font-family: ui-monospace, Menlo, Consolas, monospace; font-weight: 700; font-size: .74rem;
    color: #19c3b1; border: 1px solid #19c3b155; padding: 1px 6px; border-radius: 5px;
}

.modal-card.comp-modal { width: min(620px, 94vw); }
.comp-form { display: flex; flex-direction: column; gap: 12px; }
.comp-form-row { display: flex; gap: 12px; flex-wrap: wrap; }
.comp-field { display: flex; flex-direction: column; gap: 3px; flex: 1 1 160px; }
.comp-field-narrow { flex: 0 0 auto; width: 130px; }
.comp-form label, .comp-pick > label { font-size: .76rem; color: #8b93a7; }
.comp-icon-input { text-align: center; font-size: 1.1rem; width: 64px; }
.comp-fov { display: flex; align-items: center; gap: 4px; }
.comp-fov input { width: 56px; }
.comp-fov-x { color: #8b93a7; }
.comp-color-input { padding: 2px; height: 31px; width: 56px; }
.comp-key-ro { font-family: ui-monospace, Menlo, Consolas, monospace; opacity: .8; }
.comp-pick { display: flex; flex-direction: column; gap: 6px; }
.comp-pick-grid { display: grid; gap: 6px; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
.comp-pick-item {
    display: flex; align-items: center; gap: 7px; cursor: pointer; user-select: none;
    background: #161c27; border: 1px solid #2c3546; border-radius: 7px; padding: 6px 9px;
    font-size: .82rem; color: #c7ccd6; margin: 0;
}
.comp-pick-item:hover { border-color: #3a4558; }
.comp-pick-item.sel { border-color: #19c3b1; background: #122a28; color: #e6e9ef; }
.comp-pick-item input { accent-color: #19c3b1; }

/* Typical requirement rows (component + min count) */
.typ-req {
    display: flex; align-items: center; gap: 7px;
    background: #161c27; border: 1px solid #2c3546; border-radius: 7px; padding: 5px 9px;
    font-size: .82rem; color: #c7ccd6;
}
.typ-req.sel { border-color: #19c3b1; background: #122a28; color: #e6e9ef; }
.typ-req-check { display: flex; align-items: center; gap: 7px; margin: 0; cursor: pointer; flex: 1; }
.typ-req-check input { accent-color: #19c3b1; }
.typ-req-count { width: 62px; padding: 2px 6px; text-align: center; }

/* Data-label chips + add row (Components form) */
.comp-datalabels { display: flex; flex-wrap: wrap; gap: 6px; }
.comp-datalabel {
    display: inline-flex; align-items: center; gap: 6px;
    background: #122a28; border: 1px solid #1f5e57; border-radius: 12px;
    padding: 3px 6px 3px 10px; font-size: .8rem; color: #e6e9ef;
}
.comp-datalabel-x {
    border: none; background: transparent; color: #8b93a7; cursor: pointer;
    font-size: 1rem; line-height: 1; padding: 0 2px;
}
.comp-datalabel-x:hover { color: #ff6b6b; }
.comp-datalabel-add { display: flex; gap: 8px; }
.comp-datalabel-add input { flex: 1; }

/* Restore-data panel (Projects → Edit) */
.restore-panel { margin-top: 14px; border-top: 1px solid #232b39; padding-top: 10px; }
.restore-toggle {
    display: flex; align-items: center; justify-content: space-between; width: 100%;
    background: none; border: none; color: #e6e9ef; font-weight: 600; font-size: .9rem;
    padding: 2px 0; cursor: pointer;
}
.restore-caret { color: #8b93a7; }
.restore-row { display: flex; gap: 8px; align-items: center; }
.restore-row select { max-width: 240px; }
.restore-list { margin-top: 10px; max-height: 240px; overflow-y: auto; display: flex; flex-direction: column; gap: 5px; }
.restore-item {
    display: flex; align-items: center; gap: 9px;
    background: #12161f; border: 1px solid #232b39; border-radius: 7px; padding: 6px 9px; font-size: .82rem;
}
.restore-when { font-variant-numeric: tabular-nums; color: #e6e9ef; }
.restore-badge {
    font-size: .68rem; text-transform: uppercase; letter-spacing: .4px;
    background: #22303a; color: #9fb3c8; border-radius: 8px; padding: 1px 6px;
}
.restore-badge.manual { background: #3a2f12; color: #f0c674; }
.restore-meta { color: #8b93a7; font-size: .76rem; }

/* Per-project component derivation panel (Components page) */
.derive-panel {
    background: #12161f; border: 1px solid #232b39; border-radius: 10px;
    padding: 14px 16px; margin-bottom: 20px;
}
.derive-head { display: flex; align-items: center; gap: 12px; }
.derive-title { font-weight: 600; color: #e6e9ef; }
.derive-proj { max-width: 280px; }
.derive-grid {
    display: grid; gap: 7px; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
}
.derive-item {
    display: flex; align-items: center; gap: 7px; cursor: pointer; user-select: none; margin: 0;
    background: #161c27; border: 1px solid #2c3546; border-radius: 7px; padding: 6px 9px;
    font-size: .84rem; color: #c7ccd6;
}
.derive-item:hover { border-color: #3a4558; }
.derive-item.on { border-color: #19c3b1; background: #122a28; color: #e6e9ef; }
.derive-item input { accent-color: #19c3b1; }
.derive-ico { font-size: 1rem; }
.derive-name { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.derive-count {
    background: #1f5e57; color: #d7fff8; border-radius: 10px; padding: 0 7px;
    font-size: .72rem; font-weight: 600; font-variant-numeric: tabular-nums;
}
/* Per-project component manager rows */
.proj-comp-grid {
    display: grid; gap: 7px; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
}
.proj-comp-item {
    display: flex; align-items: center; gap: 8px;
    background: #161c27; border: 1px solid #2c3546; border-radius: 7px; padding: 6px 9px;
    font-size: .84rem; color: #c7ccd6;
}
.proj-comp-item .derive-name { flex: 1; }
.proj-comp-item .btn { padding: 1px 8px; }

/* Typicals page: compact overview of which typicals are selected on rooms in a project */
.typ-overview { display: flex; flex-direction: column; gap: 4px; margin-top: 10px; }
.typ-overview-row { display: flex; align-items: baseline; gap: 8px; font-size: .82rem; min-width: 0; }
.typ-overview-name { font-weight: 600; color: #e6e9ef; white-space: nowrap; flex-shrink: 0; max-width: 40%;
    overflow: hidden; text-overflow: ellipsis; }
.typ-overview-count {
    background: #1f5e57; color: #d7fff8; border-radius: 10px; padding: 0 7px;
    font-size: .72rem; font-weight: 700; font-variant-numeric: tabular-nums; flex-shrink: 0;
}
.typ-overview-rooms { color: #9aa3b2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }

/* Live-collaboration badges in the editor toolbar */
.collab-badge { display: inline-flex; align-items: center; gap: 4px; font-size: .78rem; font-weight: 600;
    border-radius: 12px; padding: 1px 8px; white-space: nowrap; }
.collab-conflict { background: #7a1f1f; color: #ffe0e0; }
.collab-lock { background: #23405c; color: #cfe6ff; }
.collab-presence { background: #1f5e57; color: #d7fff8; }

/* Reorder-tree dialog */
.reorder-card { max-width: 460px; }
.reorder-list { display: flex; flex-direction: column; gap: 5px; max-height: 52vh; overflow-y: auto; margin-bottom: 4px; }
.reorder-row {
    display: flex; align-items: center; gap: 10px; padding: 6px 9px;
    background: #161c27; border: 1px solid #2c3546; border-radius: 7px;
}
.reorder-pos { width: 20px; text-align: right; color: #7c8597; font-variant-numeric: tabular-nums; font-size: .8rem; }
.reorder-info { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.reorder-name { color: #e6e9ef; font-size: .86rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.reorder-code { color: #7c8597; font-size: .72rem; font-family: ui-monospace, Menlo, Consolas, monospace; }
.reorder-btns { display: flex; gap: 4px; flex-shrink: 0; }
.reorder-btns .btn { padding: 1px 8px; line-height: 1.3; }

/* Manual page */
.manual { max-width: 820px; color: #c7ccd6; line-height: 1.5; }
.manual-intro { color: #9aa3b2; font-size: .95rem; margin-bottom: 4px; }
.manual-part {
    margin-top: 30px; padding: 10px 14px; border-radius: 8px;
    background: linear-gradient(90deg, #122a28, #0f141d); border: 1px solid #1f5e57;
}
.manual-part-title { font-size: 1.3rem; font-weight: 800; color: #37d39b; margin: 0; }
.manual-part-blurb { color: #9aa3b2; font-size: .9rem; margin: 4px 0 0; }
.manual-section { margin-top: 22px; }
.manual-h2 {
    font-size: 1.12rem; font-weight: 700; color: #19c3b1; margin: 0 0 6px;
    border-bottom: 1px solid #232b39; padding-bottom: 5px;
}
.manual-h3 { font-size: .96rem; font-weight: 600; color: #e6e9ef; margin: 12px 0 4px; }
.manual-p { margin: 6px 0; }
.manual-ul, .manual-ol { margin: 6px 0 6px 4px; padding-left: 22px; }
.manual-ul li, .manual-ol li { margin: 3px 0; }
.manual-ul li::marker { color: #19c3b1; }
.manual-ol li::marker { color: #19c3b1; font-weight: 700; }
.manual-tip {
    margin: 8px 0; padding: 8px 12px; background: #122a28; border-left: 3px solid #19c3b1;
    border-radius: 6px; font-size: .9rem;
}
.manual-tip-label { font-weight: 700; color: #37d39b; margin-right: 6px; }

/* Data editor page */
.data-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.data-proj { max-width: 180px; }
.data-scope { max-width: 260px; }
.data-search { max-width: 220px; }
.data-dirty { color: #f0ad4e; font-size: .8rem; font-weight: 600; }
.data-hint { margin-bottom: 8px; }
.data-section-title { font-size: 1rem; font-weight: 600; color: #e6e9ef; margin: 18px 0 4px; }
.data-hint kbd { background: #222a39; border: 1px solid #2c3546; border-radius: 4px; padding: 0 5px; font-size: .72rem; }
.data-empty { background: #12161f; border: 1px solid #232b39; border-radius: 10px; padding: 20px; }

.data-grid-wrap { overflow: auto; max-height: calc(100dvh - 200px); border: 1px solid #232b39; border-radius: 10px; }
.data-grid { border-collapse: separate; border-spacing: 0; width: 100%; font-size: .82rem; }
.data-grid th, .data-grid td { border-bottom: 1px solid #202836; border-right: 1px solid #202836; padding: 5px 8px; text-align: left; }
.data-grid thead th {
    position: sticky; top: 0; z-index: 2; background: #161c27; color: #e6e9ef; vertical-align: top;
}
.data-grid th.data-check, .data-grid td.data-check { width: 34px; text-align: center; }
.data-grid th.data-comp, .data-grid td.data-comp {
    position: sticky; left: 0; z-index: 1; background: #12161f; min-width: 190px; max-width: 260px;
}
.data-grid thead th.data-comp { z-index: 3; background: #161c27; }
.data-comp-name { color: #e6e9ef; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.data-comp-code { color: #8b93a7; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: .7rem; }
.data-fixed-labels { display: flex; flex-wrap: wrap; gap: 3px; margin-top: 3px; }
.data-fixed-label {
    background: #232b3a; border: 1px solid #2c3546; color: #b9c0cc;
    border-radius: 4px; padding: 0 5px; font-size: .68rem; white-space: nowrap;
}
.data-col { min-width: 130px; }
.data-col-name { font-weight: 600; margin-bottom: 3px; white-space: nowrap; }
.data-fill {
    width: 100%; font-size: .72rem; padding: 2px 5px;
    background: #0f141d; color: #cdd3dd; border: 1px dashed #3a4558; border-radius: 5px;
}
.data-fill::placeholder { color: #5a6472; }
.data-input {
    width: 100%; font-size: .8rem; padding: 3px 6px;
    background: #0f141d; color: #e6e9ef; border: 1px solid #2c3546; border-radius: 5px;
}
.data-input:focus { border-color: #19c3b1; outline: none; }
.data-na { color: #4a5164; }
.data-grid tbody tr:hover td { background: #161d29; }
.data-grid tbody tr.sel td { background: #122a28; }
.data-grid tbody tr.sel td.data-comp { background: #123028; }
.data-grid tbody tr:hover td.data-comp { background: #161d29; }

/* Hover data bar: fades in at the bottom-centre when hovering a map component. */
.hover-databar {
    position: absolute; bottom: 14px; left: 50%; transform: translateX(-50%);
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: center;
    max-width: 56%; padding: 6px 12px;
    background: rgba(16, 21, 31, .95); border: 1px solid #2f6f66; border-radius: 10px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, .45);
    font-size: .8rem; color: #cdd3dd;
    opacity: 0; pointer-events: none; transition: opacity .18s ease; z-index: 7;
}
.hover-databar.show { opacity: 1; }
/* When components are selected the bar is interactive (editable), not just a hover preview. */
.hover-databar.editing { pointer-events: auto; border-color: #19c3b1; }
.hover-databar-code { font-weight: 700; color: #19c3b1; font-variant-numeric: tabular-nums; }
.hover-databar-chip {
    display: inline-flex; align-items: baseline; gap: 5px;
    background: #22303a; border-radius: 8px; padding: 1px 9px; font-size: .74rem;
}
.hover-databar-key { color: #8b93a7; }
.hover-databar-val { color: #d7fff8; font-weight: 600; }
.hover-databar-empty { color: #6b7280; font-style: italic; }
.hover-databar-input {
    width: 84px; background: #10151f; color: #d7fff8; font-weight: 600;
    border: 1px solid #35505a; border-radius: 5px; padding: 1px 6px; font-size: .74rem;
}
.hover-databar-input:focus { outline: none; border-color: #19c3b1; box-shadow: 0 0 0 2px rgba(25,195,177,.25); }
.hover-databar-input:disabled { opacity: .55; }
/* Alignment (rotate) + stacking (front/back) controls, shown when a component is selected. */
.hover-databar-tools { display: inline-flex; align-items: center; gap: 3px; }
.hover-databar-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; border: 1px solid #35505a; border-radius: 5px;
    background: #22303a; color: #d7fff8; font-size: .85rem; line-height: 1; cursor: pointer; padding: 0;
}
.hover-databar-btn:hover { background: #2d3f4b; border-color: #19c3b1; }
.hover-databar-btn.on { background: #19c3b1; border-color: #19c3b1; color: #06231f; }
.hover-databar-btn-wide { width: auto; padding: 0 8px; gap: 4px; font-size: .72rem; font-weight: 600; }
.hover-databar-rotinput {
    width: 44px; background: #10151f; color: #d7fff8; font-weight: 600; text-align: right;
    border: 1px solid #35505a; border-radius: 5px; padding: 1px 4px; font-size: .74rem;
    font-variant-numeric: tabular-nums;
}
.hover-databar-rotinput:focus { outline: none; border-color: #19c3b1; box-shadow: 0 0 0 2px rgba(25,195,177,.25); }
.hover-databar-deg { color: #8b93a7; margin-right: 2px; }
.hover-databar-toolsep { width: 1px; height: 16px; background: #35505a; margin: 0 3px; }

/* Typicals view overlay: per-room component lists anchored on the plan */
.typical-layer { position: absolute; inset: 0; pointer-events: none; z-index: 6; }
.typical-room {
    position: absolute; transform: translate(-50%, -50%);
    min-width: 96px; max-width: 220px;
    background: rgba(16, 21, 31, .94); border: 1px solid #2f6f66; border-radius: 8px;
    padding: 6px 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, .4);
    font-size: .72rem; color: #cdd3dd; pointer-events: auto;
}
.typical-room-head {
    display: flex; align-items: center; gap: 6px;
    border-bottom: 1px solid #24303a; padding-bottom: 2px; margin-bottom: 4px;
}
.typical-room-name { font-weight: 700; color: #19c3b1; font-size: .8rem; flex: 1; }
.typical-room-flag { font-weight: 700; font-size: .82rem; }
.typical-room-flag.ok { color: #37d39b; }
.typical-room-flag.bad { color: #ff6b6b; }
.typical-room-select {
    /* Extra right padding reserves room for the dropdown arrow, so a long typical name ellipsizes with a
       clean gap before it instead of running right up under the arrow. */
    width: 100%; max-width: 100%; margin-bottom: 5px; font-size: .72rem; padding: 2px 26px 2px 6px;
    background: #0f141d; color: #cdd3dd; border: 1px solid #2c3546; border-radius: 5px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.typical-room-code { font-variant-numeric: tabular-nums; letter-spacing: .2px; white-space: nowrap; }
.typical-room-empty { color: #6b7280; font-style: italic; }

/* Address tick-grid (add device to a bus) */
.addr-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(42px, 1fr));
    gap: 5px; max-height: 220px; overflow-y: auto; padding: 2px;
    border: 1px solid #2c3546; border-radius: 8px; background: #10151f;
}
.addr-cell {
    border: 1px solid #2c3546; background: #161c27; color: #c7ccd6;
    border-radius: 6px; padding: 5px 0; font-size: .8rem; font-variant-numeric: tabular-nums;
    cursor: pointer; user-select: none; text-align: center;
}
.addr-cell:hover:not(:disabled) { border-color: #3a4558; }
.addr-cell.sel { border-color: #19c3b1; background: #122a28; color: #e6e9ef; font-weight: 600; }
.addr-cell.taken, .addr-cell:disabled {
    background: #0d1017; color: #4a5164; cursor: not-allowed;
    text-decoration: line-through; border-color: #20262f;
}

/* Tape-ruler / calibrate overlay: sits above the canvas and captures the drag. user-select:none so dragging
   (e.g. the compass) never highlights the bearing/measurement label text under the cursor. */
.measure-overlay { position: absolute; inset: 0; z-index: 5; cursor: crosshair; user-select: none; -webkit-user-select: none; }
.measure-overlay.calibrate { cursor: cell; }
.measure-svg { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; }
.measure-line { stroke: #19c3b1; stroke-width: 2; stroke-dasharray: 6 4; }
.measure-dot { fill: #19c3b1; stroke: #06231f; stroke-width: 1; }
.measure-label {
    position: absolute; transform: translate(-50%, -150%);
    background: #19c3b1; color: #06231f; font-weight: 600; font-size: .78rem;
    padding: 2px 7px; border-radius: 5px; white-space: nowrap; pointer-events: none;
    box-shadow: 0 2px 6px rgba(0,0,0,.35);
}
/* Compass bearing tags: centered on each side of the wall, in an amber compass colour. */
.measure-label.compass-label { transform: translate(-50%, -50%); background: #f0ad4e; color: #241a05; }
.measure-hint {
    position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%);
    background: rgba(20,26,36,.92); color: #c7ccd6; font-size: .76rem;
    padding: 4px 10px; border-radius: 6px; pointer-events: none; border: 1px solid #2c3546;
}
.measure-seg {
    transform: translate(-50%, -50%);
    background: #11332f; color: #7fe9dc; font-weight: 500; font-size: .72rem;
}
.measure-total {
    transform: translate(10px, -50%);
    background: #0f766e; color: #eafffb;
}
.measure-hint kbd {
    background: #2a3242; color: #e6e9ef; border-radius: 4px; padding: 0 5px;
    font-size: .7rem; border: 1px solid #39435a;
}

/* Hidden-but-in-layout file input: stays interactive so a <label for> reliably opens the OS picker
   (display:none can suppress the dialog in some browsers). */
.visually-hidden-file { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); border: 0; opacity: 0; }

/* CAD import: per-drawing-layer selection rows. */
.cad-layer-row { display: flex; align-items: center; gap: 8px; padding: 3px 2px; cursor: pointer; }
.cad-layer-row .cad-layer-name { font-size: .82rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cad-layer-row .cad-layer-count { margin-left: auto; font-size: .72rem; color: var(--bs-secondary-color, #9aa0aa); background: rgba(255,255,255,.06); border-radius: 10px; padding: 0 8px; }

/* Zone colour-preset editor rows. */
.palette-edit { display: flex; flex-direction: column; gap: 6px; max-height: 46vh; overflow-y: auto; }
.palette-swatch-row { display: flex; align-items: center; gap: 8px; }
.palette-swatch-row .form-control-color { width: 34px; padding: 2px; }
.palette-alpha { width: 84px; accent-color: #19c3b1; cursor: pointer; }
.palette-alpha-val { min-width: 34px; text-align: right; font-size: .72rem; color: var(--bs-secondary-color, #9aa0aa); font-variant-numeric: tabular-nums; }
.palette-hex { font-family: monospace; font-size: .78rem; color: var(--bs-secondary-color, #9aa0aa); text-transform: uppercase; }
.palette-del { margin-left: auto; line-height: 1; padding: 0 .4rem; }

/* Smart-snap alignment guides — a segment from the anchor a point lines up with to the point
   itself, drawn above the drawing/drag overlays so it stays visible while you work. */
.snap-guide-layer { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; z-index: 120; }
.snap-guide { stroke: #ff2d95; stroke-width: 1; stroke-dasharray: 4 3; shape-rendering: crispEdges; }
.snap-guide-dot { fill: #ff2d95; }

/* ---- Zone-area annotations ---- */
/* Zones render in two layers so they sit BELOW the components visually but stay editable: the fills paint
   under the (transparent) component canvas, the grab-outline/vertices/labels paint above it. The floor plan
   is a third layer, below the fills. */
.floor-bg-layer { position: absolute; z-index: 1; pointer-events: none; }
/* Field-of-view rectangles: below the components, dashed + translucent in the component's colour. */
.fov-layer { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 2; pointer-events: none; overflow: visible; }
.fov-rect {
    fill: url(#fov-hatch);
    stroke: #1157a6; stroke-opacity: .85; stroke-width: 1.8; stroke-linejoin: round;
}
.floor-bg-layer img { display: block; width: 100%; height: 100%; user-select: none; }
.zone-fill-layer { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
.zone-hit-layer { position: absolute; inset: 0; z-index: 4; pointer-events: none; }
.zone-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.zone-poly {
    fill: var(--zc, #19c3b1); fill-opacity: .08;
    stroke: var(--zc, #19c3b1); stroke-opacity: .6; stroke-width: 1.5;
    stroke-linejoin: round;
}
.zone-poly.selected { fill-opacity: .14; stroke-width: 2.5; stroke-opacity: .9; }
/* Highlight mode greys the zones too, so only the lit components stand out. */
.zone-fill-layer.dim-zones .zone-poly { fill: #8b93a7; stroke: #8b93a7; fill-opacity: .05; stroke-opacity: .25; }
.zone-hit-layer.dim-zones .zone-label { background: #5a6472; color: #cfd4dc; opacity: .45; box-shadow: none; }
/* Wide transparent border used to grab (select + move) the zone; interior fill stays click-through. */
.zone-outline-hit { fill: none; stroke: transparent; stroke-width: 12; pointer-events: stroke; cursor: move; }
.zone-vertex { fill: #fff; stroke-width: 2.5; pointer-events: all; cursor: grab; }
.zone-vertex:hover { fill: #eafffb; }
.zone-draw-poly { fill: #19c3b1; fill-opacity: .12; stroke: #19c3b1; stroke-width: 2; stroke-dasharray: 6 4; }
.zone-label {
    position: absolute; pointer-events: auto; cursor: move; user-select: none;
    display: inline-flex; align-items: center; gap: 2px;
    background: var(--zc, #19c3b1); color: #06231f; font-weight: 600; font-size: .72rem;
    padding: 2px 3px 2px 8px; border-radius: 5px; white-space: nowrap;
    box-shadow: 0 2px 6px rgba(0,0,0,.35);
}
.zone-label-func {
    font-weight: 500; font-style: italic; opacity: .8;
    padding-left: 5px; margin-left: 3px; border-left: 1px solid #06231f55;
}
.zone-label-del {
    border: 0; background: transparent; color: #06231faa; cursor: pointer;
    font-size: .95rem; line-height: 1; padding: 0 3px; border-radius: 4px;
}
.zone-label.selected { outline: 2px solid #fff; outline-offset: 1px; }
.zone-label-del:hover { color: #7a0000; background: rgba(0,0,0,.12); }

/* Bottom-right floating controls: zoom + live scale. Collapses to its content width. */
.canvas-controls {
    position: absolute; right: 10px; bottom: 10px; z-index: 6;
    display: inline-flex; align-items: center; gap: 8px;
    background: rgba(20,26,36,.92); border: 1px solid #2c3546;
    border-radius: 8px; padding: 4px 8px; box-shadow: 0 2px 8px rgba(0,0,0,.35);
}
.canvas-controls .canvas-scale { font-size: .76rem; color: #c7ccd6; white-space: nowrap; }

/* Multi-select: Ctrl-held overlay + drag-box. */
.marquee-overlay { position: absolute; inset: 0; z-index: 5; cursor: crosshair; }
.marquee-box {
    position: absolute; border: 1.5px dashed #19c3b1;
    background: rgba(25,195,177,.14); pointer-events: none;
}

/* Layer switch (E/W) + notes toggle, bottom-left — same pill style as the zoom controls. */
.canvas-layers {
    position: absolute; left: 10px; bottom: 10px; z-index: 6;
    display: inline-flex; align-items: center; gap: 8px;
    background: rgba(20,26,36,.92); border: 1px solid #2c3546;
    border-radius: 8px; padding: 4px 8px; box-shadow: 0 2px 8px rgba(0,0,0,.35);
}
.canvas-layers-toggle { padding: .1rem .35rem; line-height: 1; opacity: .8; }
.canvas-layers-toggle:hover { opacity: 1; }
/* After a mouse click these toggles kept Bootstrap's focus ring, so an off button looked half-on.
   Drop the ring for mouse focus (keyboard focus still shows it via :focus-visible). */
.canvas-layers .btn:focus:not(:focus-visible) { box-shadow: none; }
/* Smoothly slide/fade the tools in and out when the cluster collapses. */
.canvas-layers-tools {
    display: inline-flex; align-items: center; gap: 8px;
    overflow: hidden; max-width: 340px; opacity: 1;
    transition: max-width .25s ease, opacity .2s ease, margin-left .25s ease;
}
.canvas-layers.collapsed .canvas-layers-tools {
    max-width: 0; opacity: 0; margin-left: -8px; pointer-events: none;
}

/* Discipline badges on tree rows (E/W). */
.tv-badges { display: inline-flex; gap: 3px; margin-left: auto; padding-left: 6px; }
.tv-badge {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 16px; height: 16px; padding: 0 3px; border-radius: 4px;
    font-size: 9.5px; font-weight: 700; color: #06231f; line-height: 1;
    pointer-events: none;   /* informational by default */
}
/* Clickable badges (floor rows) act as shortcuts to that floor + layer. */
.tv-badge-btn { pointer-events: auto; border: 1px solid transparent; cursor: pointer; opacity: .75; }
.tv-badge-btn:hover { opacity: 1; }
.tv-badge-btn.active { opacity: 1; border-color: #fff; box-shadow: 0 0 0 1px rgba(255,255,255,.4); }

/* Tools dropdown (Ruler / Calibrate). */
.tool-dd { position: relative; display: inline-block; }
.tool-dd-backdrop { position: fixed; inset: 0; z-index: 1040; }
.tool-dd-menu {
    position: absolute; top: calc(100% + 4px); left: 0; z-index: 1050; min-width: 170px;
    background: #1b212e; border: 1px solid #2c3546; border-radius: 8px; padding: 4px;
    box-shadow: 0 6px 18px rgba(0,0,0,.45);
}
.tool-dd-item {
    display: block; width: 100%; text-align: left; background: none; border: 0;
    color: #c7ccd6; font-size: .85rem; padding: 6px 10px; border-radius: 6px; cursor: pointer;
}
.tool-dd-item:hover { background: #2a3242; color: #e6e9ef; }
.tool-dd-item.active { background: #19c3b1; color: #06231f; font-weight: 600; }
.tool-dd-color { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.tool-dd-color input[type=color] { width: 30px; height: 22px; padding: 0; border: 1px solid #35505a; border-radius: 5px; background: none; cursor: pointer; }
/* Colour submenu: a "🎨 Colour ▸" row expands the colour controls (recolour, brush, presets, transparency). */
.tool-dd-expand { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.tool-dd-caret { color: #8b93a7; font-size: .7rem; }
.tool-dd-group { margin: 2px 2px 2px 8px; padding-left: 6px; border-left: 2px solid #2c3546; }
/* Recolour brush: the picker is the "recolour" button; preset + transparency sit indented underneath it. */
.tool-dd-sub { padding: 2px 10px 6px 24px; display: flex; flex-direction: column; gap: 7px; }
.tool-dd-subrow { display: flex; align-items: center; justify-content: space-between; gap: 8px; color: #b7bdca; font-size: .78rem; }
.tool-brush-select {
    max-width: 120px; height: 22px; padding: 0 4px; font-size: .78rem; cursor: pointer;
    color: #e6e9ef; background: #1c2330; border: 1px solid #35505a; border-radius: 5px;
}
.tool-brush-select option { color: #fff; }
.tool-dd-subrow input[type=range] { flex: 1; min-width: 70px; accent-color: #19c3b1; cursor: pointer; }
.tool-alpha-val { min-width: 30px; text-align: right; color: #8b93a7; font-size: .72rem; font-variant-numeric: tabular-nums; }
.tool-dd-sep { height: 1px; background: #2c3546; margin: 4px 2px; }
/* Building-orientation compass in Settings: red needle points to true north; the plan's up is screen-up. */
.orient-row { display: flex; align-items: center; gap: 12px; padding: 4px 10px 8px; }
.orient-compass { width: 84px; height: 84px; flex: none; cursor: pointer; }
.orient-compass svg { width: 100%; height: 100%; display: block; pointer-events: none; }
.oc-dial { fill: #1c2330; stroke: #35505a; stroke-width: 2; }
.oc-up { stroke: #6b7280; stroke-width: 2; stroke-linecap: round; }
.oc-north { fill: #e5484d; }
.oc-south { fill: #9aa0aa; }
.oc-hub { fill: #c7ccd6; }
.orient-ctl { display: flex; flex-direction: column; gap: 6px; }
.orient-help { color: #8b93a7; font-size: .72rem; max-width: 140px; line-height: 1.3; }
.orient-input { display: flex; align-items: center; gap: 6px; color: #c7ccd6; font-size: .82rem; }
.orient-input input { width: 56px; background: #1c2330; color: #e6e9ef; border: 1px solid #35505a; border-radius: 5px; padding: 2px 5px; }
.tool-dd-label { color: #8b93a7; font-size: .72rem; padding: 4px 10px 2px; }
.tool-dd-stepper { display: flex; align-items: center; gap: 6px; padding: 4px 10px 6px; }
.tool-dd-stepper .btn { padding: 0 8px; line-height: 1.4; }
.tool-dd-stepval { min-width: 42px; text-align: center; color: #e6e9ef; font-size: .82rem; font-variant-numeric: tabular-nums; }
.tool-dd-reset { color: #8b93a7; text-decoration: none; padding: 0 2px; margin-left: auto; }
.tool-dd-reset:hover:not(:disabled) { color: #e6e9ef; }
.tool-dd-hint { color: #8b93a7; font-size: .72rem; padding: 6px 10px 2px; border-top: 1px solid #2c3546; margin-top: 4px; }
.tool-dd-hint kbd {
    background: #2a3242; color: #e6e9ef; border-radius: 4px; padding: 0 5px;
    font-size: .7rem; border: 1px solid #39435a;
}

/* ===================== App theme (dark + teal, matches the tree styling) ===================== */
[data-bs-theme="dark"] {
    --bs-body-bg: #141a24;
    --bs-body-color: #c7ccd6;
    --bs-emphasis-color: #e6e9ef;
    --bs-heading-color: #e6e9ef;
    --bs-border-color: #2c3546;
    --bs-secondary-bg: #1b212e;
    --bs-tertiary-bg: #232b3a;
    --bs-link-color: #2dd4bf;
    --bs-link-hover-color: #5eead4;
    --bs-primary: #19c3b1;
    --bs-primary-rgb: 25, 195, 177;
}

body { background-color: #141a24; }
h1, h2, h3, h4, h5, h6 { color: var(--bs-emphasis-color); }

/* Teal primary buttons with dark text */
.btn-primary {
    --bs-btn-bg: #19c3b1; --bs-btn-border-color: #19c3b1;
    --bs-btn-hover-bg: #16b3a3; --bs-btn-hover-border-color: #16b3a3;
    --bs-btn-active-bg: #129b8d; --bs-btn-active-border-color: #129b8d;
    --bs-btn-color: #06251f; --bs-btn-hover-color: #06251f; --bs-btn-active-color: #06251f;
    --bs-btn-disabled-bg: #19c3b1; --bs-btn-disabled-border-color: #19c3b1; --bs-btn-disabled-color: #06251f;
}

/* Cards / surfaces: the subtle elevated slate look from the tree rows */
[data-bs-theme="dark"] .card {
    --bs-card-bg: #1b212e;
    --bs-card-border-color: #2c3546;
    --bs-card-cap-bg: #1b212e;
    background-image: linear-gradient(180deg, #222a39 0%, #1c2330 100%);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.03), 0 1px 3px rgba(0,0,0,.35);
}

/* Inputs / selects */
[data-bs-theme="dark"] .form-control,
[data-bs-theme="dark"] .form-select,
[data-bs-theme="dark"] .input-group-text {
    background-color: #11151d;
    border-color: #2a3242;
    color: #cdd3df;
}
[data-bs-theme="dark"] .form-control::placeholder { color: #5b6477; }
[data-bs-theme="dark"] .form-control:focus,
[data-bs-theme="dark"] .form-select:focus {
    border-color: #19c3b1;
    box-shadow: 0 0 0 .2rem rgba(25,195,177,.25);
}

/* Outline-secondary buttons read better on slate */
[data-bs-theme="dark"] .btn-outline-secondary {
    --bs-btn-color: #aab2c2; --bs-btn-border-color: #39435a;
    --bs-btn-hover-bg: #232b3a; --bs-btn-hover-color: #e6e9ef; --bs-btn-hover-border-color: #4a5670;
}

/* ---- Modal dialog ---- */
.modal-dim {
    position: fixed; inset: 0; z-index: 1080;
    background: rgba(8, 11, 17, .6);
}
.modal-card {
    position: fixed; z-index: 1090;
    /* Always centred in the viewport and capped to it, so the dialog is fully visible on any screen. */
    top: 50%; left: 50%; transform: translate(-50%, -50%);
    width: 340px; max-width: calc(100vw - 32px);
    max-height: calc(100dvh - 24px); overflow-y: auto;
    padding: 18px;
    background: linear-gradient(180deg, #222a39 0%, #1b212e 100%);
    border: 1px solid #2c3546;
    border-radius: 10px;
    box-shadow: 0 12px 40px rgba(0,0,0,.5);
    color: #c7ccd6;
}
.modal-card-title { font-size: 15px; font-weight: 600; color: #e6e9ef; margin-bottom: 10px; }
.modal-card-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }

/* Modal "choose type" list */
.modal-choose-list { display: flex; flex-direction: column; gap: 6px; max-height: 320px; overflow-y: auto; }
.modal-choose-item {
    display: flex; align-items: center; text-align: left;
    padding: 8px 10px; border: 1px solid #2c3546; border-radius: 7px;
    background: #1b212e; color: #c7ccd6; cursor: pointer; font-size: 14px;
}
.modal-choose-item:hover { border-color: #19c3b1; background: #222a39; }
