/* ============================================================
   MODALS & CONTEXT MENU
   ============================================================ */


.context-menu {
    position: absolute;
    background: white;
    border: 1px solid var(--dc-n-150);
    border-radius: 4px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.15);
    padding: 4px 0;
    z-index: 1000;
    display: none;
    min-width: 150px;
}

.context-menu-header {
    padding: 6px 16px 4px;
    font-size: var(--dc-text-xs);
    font-weight: 600;
    color: var(--dc-n-600);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    border-bottom: 1px solid var(--dc-n-150);
    margin-bottom: 2px;
    cursor: default;
}

.context-menu-item {
    padding: 8px 16px;
    cursor: pointer;
    font-size: var(--dc-text-md);
    color: var(--dc-n-950);
}

.context-menu-item:hover {
    background: var(--dc-n-50);
}

.context-menu-item.danger {
    color: var(--dc-c-error);
}

.context-menu-separator {
    height: 1px;
    background: var(--dc-n-150);
    margin: 4px 0;
}

.context-menu-item.has-submenu {
    position: relative;
}

.context-submenu {
    display: none;
    position: absolute;
    left: 100%;
    top: -4px;
    background: white;
    border: 1px solid var(--dc-n-150);
    border-radius: 4px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.15);
    padding: 4px 0;
    min-width: 120px;
    white-space: nowrap;
    z-index: 1001;
    max-height: 80vh;
    overflow-y: auto;
}

.context-menu-item.has-submenu:hover .context-submenu {
    display: block;
}

.context-menu-item.current-type {
    color: var(--dc-n-500);
    cursor: default;
}

.context-menu-item.current-type:hover {
    background: none;
}

/* --- Modal base --- */

.modal {
    display: none;
    position: fixed;
    z-index: var(--dc-z-modal);
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background: var(--dc-overlay-backdrop);
    backdrop-filter: blur(var(--dc-overlay-blur));
    align-items: center;
    justify-content: center;
}

.modal.active {
    display: flex;
    animation: dcModalBackdropIn 0.2s ease both;
}

.modal.active > .modal-content {
    animation: dcModalPopIn var(--dc-anim-in) var(--dc-ease-pop) both;
}

@media (prefers-reduced-motion: reduce) {
    .modal.active,
    .modal.active > .modal-content {
        animation: none;
    }
}

/* A regular dialog opened from another regular dialog (the name prompt from the projects
   list) — the same z-index otherwise, and DOM order would put it behind the one that
   asked for it */
.modal.modal-stacked {
    z-index: var(--dc-z-modal-stack);
}

/* Link params modal sits above panel visualization modal */
#linkParamsModal {
    z-index: var(--dc-z-modal-stack);
    align-items: flex-start;
    overflow-y: auto;
    padding: 24px 0;
    justify-content: center;
}

/* ODF placement picker modal */
#odfPreviewModal {
    z-index: var(--dc-z-modal-top);
}

.odf-picker-content {
    max-width: 860px;
    width: 94%;
    position: relative;
    padding: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    max-height: 88vh;
}

.odf-picker-body {
    display: grid;
    grid-template-columns: 240px 1fr;
    flex: 1;
    min-height: 0;
    overflow: hidden;
}

.odf-picker-left {
    border-right: 1px solid var(--dc-n-100);
    padding: 16px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.odf-picker-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 8px;
}

.odf-preset-item {
    padding: 9px 12px;
    border-radius: 7px;
    cursor: pointer;
    border: 1.5px solid transparent;
    background: var(--dc-n-25);
    transition: background 0.12s, border-color 0.12s;
}

.odf-preset-item:hover {
    background: #eef6f3;
}

.odf-preset-item.selected {
    background: #e6f4f0;
    border-color: var(--dc-c-accent);
}

.odf-preset-item-name {
    font-size: var(--dc-text-sm);
    font-weight: 600;
    color: var(--dc-c-dark);
    line-height: 1.3;
}

.odf-preset-item-desc {
    font-size: var(--dc-text-xs);
    color: var(--dc-n-600);
    margin-top: 2px;
    line-height: 1.3;
}

.odf-preset-item-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 3px;
    margin-top: 5px;
}

/* .odf-preset-tag is a plain .badge now — see js/racks.js. */

.odf-picker-right {
    display: flex;
    flex-direction: column;
    padding: 16px;
    gap: 10px;
    min-height: 0;
}

.odf-viewer-wrap {
    flex: 1;
    position: relative;
    border-radius: 8px;
    overflow: hidden;
    background: var(--dc-n-25);
    min-height: 320px;
}

.odf-model-status {
    position: absolute;
    bottom: 8px;
    left: 50%;
    transform: translateX(-50%);
    font-size: var(--dc-text-xs);
    color: var(--dc-n-500);
    background: rgba(255,255,255,0.85);
    padding: 3px 10px;
    border-radius: 10px;
    pointer-events: none;
    white-space: nowrap;
}

.odf-picker-info {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-height: 48px;
}

.odf-picker-info-name {
    font-size: var(--dc-text-md);
    font-weight: 700;
    color: var(--dc-c-dark);
}

.odf-picker-info-desc {
    font-size: var(--dc-text-sm);
    color: var(--dc-c-muted);
}

.odf-picker-info-code {
    font-size: var(--dc-text-xs);
    color: var(--dc-n-400);
    font-family: monospace;
    margin-top: 2px;
}

/* Favorite overwrite modal sits above link params modal */
#favOverwriteModal {
    z-index: calc(var(--dc-z-modal-stack) + 100);
}

/* Zoom-tier and admin overlays (z-index moved here from inline HTML) */
#topologyModal {
    z-index: calc(var(--dc-z-modal-top) + 200);
}
#imageModal {
    z-index: var(--dc-z-modal-zoom);
}
#panelEnlargedModal {
    z-index: calc(var(--dc-z-modal-zoom) + 1);
}
#panelCabinetZoomModal {
    z-index: calc(var(--dc-z-modal-zoom) + 2);
}
#equipmentCatalogModal {
    z-index: calc(var(--dc-z-modal-zoom) + 10);
}
/* A regular dialog opened from a zoom-tier view (e.g. rack height from the rack view) —
   without this it would open behind the view that asked for it */
.modal.modal-above-zoom {
    z-index: calc(var(--dc-z-modal-zoom) + 20);
}
#equipmentCatalogEditModal {
    z-index: calc(var(--dc-z-modal-zoom) + 11);
}

.modal-content {
    background: var(--dc-modal-surface);
    padding: 30px;
    border-radius: var(--dc-radius-lg);
    box-shadow: var(--dc-elev-modal);
    max-width: 800px;
    width: 90%;
}

.modal-header {
    font-size: var(--dc-text-xl);
    font-weight: 700;
    margin-bottom: 20px;
    color: var(--dc-c-dark);
}

.modal-body {
    margin-bottom: 20px;
    max-height: 60vh;
    overflow-y: auto;
}

.modal-footer {
    display: flex;
    gap: 10px;
    justify-content: flex-end;
    padding-top: 14px;
    border-top: 1px solid var(--dc-modal-divider);
}

/* --- Universal modal close button --- */

.modal-close-btn {
    background: var(--dc-n-0);
    border: 1px solid #dde;
    border-radius: 50%;
    width: 28px;
    height: 28px;
    min-width: 28px;
    font-size: 18px;
    font-weight: 700;
    cursor: pointer;
    color: var(--dc-n-800);
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    padding: 0;
    box-shadow: 0 2px 6px rgba(0,0,0,0.15);
    flex-shrink: 0;
    transition: background var(--dc-transition-fast), color var(--dc-transition-fast);
}

/* Floats over the panel's own content - a product photograph, say - instead of
   sitting in a header row. This is the only thing the two hand-made copies in
   css/productSelector.css had that this class did not, and it is why they existed. */
.modal-close-btn--float {
    position: absolute;
    top: 12px;
    right: 14px;
}

.modal-close-btn:hover {
    background: var(--dc-n-50);
    color: var(--dc-n-1000);
}

/* ── Auth (login/register) modal ───────────────────────────────────────────
   Was fully inline-styled in index.html with a transparent backdrop and
   z-index 99999; now uses the shared tokens and the common dim/blur look. */

.auth-modal {
    display: none;
    position: fixed;
    inset: 0;
    background: var(--dc-overlay-backdrop);
    backdrop-filter: blur(var(--dc-overlay-blur));
    z-index: var(--dc-z-modal-auth);
    align-items: center;
    justify-content: center;
}

.auth-modal.active {
    display: flex;
    animation: dcModalBackdropIn 0.2s ease both;
}

.auth-modal.active > .auth-card {
    animation: dcModalPopIn var(--dc-anim-in) var(--dc-ease-pop) both;
}

@media (prefers-reduced-motion: reduce) {
    .auth-modal.active,
    .auth-modal.active > .auth-card {
        animation: none;
    }
}

.auth-card {
    background: var(--dc-modal-surface);
    border-radius: var(--dc-radius-lg);
    padding: 36px 36px 32px;
    width: 360px;
    box-shadow: var(--dc-elev-modal);
    display: flex;
    flex-direction: column;
    gap: 18px;
}

/* ── Cabling topology modal ────────────────────────────────────────────── */
/* The drawing is one <svg> that fills the body; zoom and pan move its viewBox
   (js/topology.js). The legend is part of the drawing, not an overlay. */
/* The generic body caps itself at 60vh; this one is the whole modal. */
#topologyModal .modal-body { max-height: none; margin-bottom: 0; }
#topologyContainer svg {
    display: block;
    width: 100%;
    height: 100%;
    cursor: grab;
    touch-action: none;
    /* A drag pans the view; without this it also sweeps a text selection across the labels. */
    user-select: none;
    -webkit-user-select: none;
}
#topologyContainer svg:active { cursor: grabbing; }
#topologyContainer .topo-tile[data-cluster],
#topologyContainer .topo-tile[data-expanded-in] { cursor: pointer; }
#topologyContainer .topo-tile[data-cluster]:hover rect,
#topologyContainer .topo-tile[data-expanded-in]:hover rect { stroke-width: 2.5; }
.topo-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    color: var(--dc-c-muted);
    font-size: var(--dc-text-md);
}

/* ── Link Types Admin Modal ────────────────────────────────────────────────── */

.lt-admin-content {
    max-width: 1100px;
    width: 95%;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    position: relative;
}

.lt-admin-body {
    flex: 1;
    overflow-y: auto;
    padding: 16px 20px 20px;
}

.lt-admin-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(480px, 1fr));
    gap: 14px;
}

.lt-card {
    border: 1px solid var(--dc-n-150);
    border-radius: 8px;
    padding: 14px 16px 12px;
    background: var(--dc-n-0);
    box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}

.lt-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 3px;
}

.lt-card-name {
    font-size: var(--dc-text-lg);
    font-weight: 600;
    color: #1a1a2e;
}

.lt-card-id {
    font-size: var(--dc-text-xs);
    color: var(--dc-n-600);
    font-family: monospace;
    margin-bottom: 6px;
}

.lt-card-badges {
    display: flex;
    gap: 5px;
}

/* The link-type badges are .badge now (js/links.js): --info, --warning, --success
   and plain neutral. The uppercase went with them - it was the one family in the
   product that shouted, and FIBER read no better than Fiber. */

.lt-card-stats {
    font-size: var(--dc-text-xs);
    color: var(--dc-n-800);
    margin-bottom: 10px;
}

.lt-struct {
    display: flex;
    align-items: stretch;
    gap: 4px;
    flex-wrap: wrap;
}

.lt-struct-cell {
    flex: 1;
    min-width: 100px;
    background: var(--dc-n-25);
    border: 1px solid var(--dc-n-100);
    border-radius: 6px;
    padding: 7px 10px;
}

.lt-struct-cable {
    flex: 1.4;
    background: #f0f4ff;
    border-color: #c8d8f8;
}

.lt-struct-role {
    font-size: var(--dc-text-2xs);
    font-weight: 700;
    color: var(--dc-n-600);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 3px;
}

.lt-struct-name {
    font-size: var(--dc-text-xs);
    color: var(--dc-n-950);
    line-height: 1.3;
}

.lt-struct-qty {
    font-size: var(--dc-text-2xs);
    color: var(--dc-n-500);
    margin-top: 2px;
}

.lt-struct-arrow {
    display: flex;
    align-items: center;
    color: var(--dc-n-300);
    font-size: 14px;
    flex-shrink: 0;
    padding: 0 2px;
}

.lt-odf-row {
    margin-top: 8px;
    padding: 6px 10px;
    background: #fffbf0;
    border: 1px solid #f0e6c0;
    border-radius: 5px;
    font-size: var(--dc-text-xs);
    color: #7a6000;
    line-height: 1.5;
}

.lt-block {
    margin-top: 8px;
}

.lt-block + .lt-block {
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px dashed var(--dc-n-100);
}

.lt-block-label {
    font-size: var(--dc-text-2xs);
    font-weight: 700;
    color: var(--dc-n-600);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 5px;
}

/* ODF configurator overlay — preset name badge */
#odfPresetBadge {
    transition: background 0.2s, border-color 0.2s;
}

#odfPresetBadge.odf-preset-badge--dirty {
    border-color: #f39c12 !important;
    color: #f9c74f !important;
}

.table-edit-btn {
    font-size: var(--dc-text-xs);
    padding: 3px 8px;
    border: 1px solid var(--dc-n-200);
    border-radius: var(--dc-radius-xs);
    background: var(--dc-n-0);
    cursor: pointer;
    color: var(--dc-n-900);
    transition: background var(--dc-transition-fast), border-color var(--dc-transition-fast);
}
.table-edit-btn:hover {
    background: var(--dc-n-50);
    border-color: var(--dc-n-400);
}
.table-edit-btn:focus-visible {
    outline: none;
    box-shadow: var(--dc-focus-ring);
}

/* ── BOM card grid (Bill of Materials tab in Equipment List modal) ────────── */

.bom-section-title {
    font-weight: 700;
    font-size: var(--dc-text-xs);
    color: var(--dc-c-dark);
    margin: 22px 0 10px;
    text-transform: uppercase;
    letter-spacing: .6px;
}

.bom-section-title:first-child {
    margin-top: 6px;
}

.bom-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(155px, 1fr));
    gap: 12px;
}

.bom-card {
    background: var(--dc-n-0);
    border-radius: 8px;
    border: 1px solid var(--dc-n-100);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    position: relative;
}

.bom-card-img {
    width: 100%;
    aspect-ratio: 4/3;
    object-fit: contain;
    background: var(--dc-n-0);
    padding: 10px;
    box-sizing: border-box;
    display: block;
}

.bom-card-img-placeholder {
    width: 100%;
    aspect-ratio: 4/3;
    background: linear-gradient(135deg, var(--dc-c-accent-light) 0%, #d4ede8 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--dc-c-accent);
    font-size: 24px;
}

.bom-card-body {
    padding: 8px 10px 10px;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.bom-card-name {
    font-size: var(--dc-text-xs);
    font-weight: 600;
    color: var(--dc-c-dark);
    line-height: 1.35;
}

.bom-card-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 3px;
    margin-top: 4px;
}

.bom-qty-badge {
    position: absolute;
    top: 7px;
    right: 7px;
    background: var(--dc-c-success);
    color: var(--dc-n-0);
    font-size: var(--dc-text-2xs);
    font-weight: 700;
    padding: 2px 8px;
    border-radius: 20px;
    line-height: 1.4;
    white-space: nowrap;
    box-shadow: 0 1px 4px rgba(39,174,96,.35);
}
/* ── Links overview (Equipment List tab) ──────────────────────────────────────
   Mirrors the PDF section in js/export.js: links grouped by source rack + spec,
   everything constant for the group hoisted into the header as chips. Colours are
   kept in sync with _LINK_CHIP / _LINK_KIND there — change both together.
   The flat all-columns view stays available through Export to Excel. */
/* Sections: external first, then backbone, then zonal. Collapsible here, always
   expanded in the PDF. */
.lo-section {
    margin-bottom: 22px;
}

.lo-section-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0 5px;
    margin-bottom: 10px;
    border-bottom: 1.5px solid currentColor;
    font-size: var(--dc-text-lg);
    font-weight: 700;
    cursor: pointer;
    list-style: none;
    user-select: none;
}

.lo-section-head::-webkit-details-marker { display: none; }

.lo-section--zonal    .lo-section-head { color: var(--dc-n-700); }
.lo-section--backbone .lo-section-head { color: #2980b9; }
.lo-section--external .lo-section-head { color: #c0622a; }

.lo-section-caret {
    width: 0;
    height: 0;
    border-left: 5px solid currentColor;
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
    transition: transform .15s ease;
    transform-origin: 30% 50%;
}

.lo-section[open] > .lo-section-head .lo-section-caret { transform: rotate(90deg); }

.lo-section-count {
    margin-left: auto;
    font-size: var(--dc-text-xs);
    font-weight: 500;
    color: var(--dc-n-700);
}

.lo-group {
    margin-bottom: 18px;
}

.lo-group-head {
    background: #f4efec;
    border-radius: 6px;
    padding: 8px 12px;
    margin-bottom: 6px;
    overflow: hidden;
}

.lo-group-title {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 6px;
}

.lo-group-count {
    margin-left: auto;
    font-size: var(--dc-text-xs);
    font-weight: 700;
    color: #a79189;
    white-space: nowrap;
}

.lo-group-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 5px;
}

.lo-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--dc-text-xs);
    table-layout: fixed;
}

.lo-table th {
    text-align: left;
    padding: 3px 6px;
    color: var(--dc-n-700);
    font-weight: 700;
    white-space: nowrap;
}

/* Block row (Panel A / Panel B / Cable) — thin, it repeats for every group. */
.lo-table .lo-block th {
    font-size: var(--dc-text-2xs);
    padding: 1px 6px;
    background: #f4efec;
    color: #a79189;
}

.lo-table .lo-block th:first-child { background: none; }

.lo-table .lo-cols th {
    border-bottom: 2px solid #dcd6d2;
    font-size: var(--dc-text-2xs);
}

.lo-table td {
    padding: 3px 6px;
    border-bottom: 1px solid #f0eeec;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.lo-table tbody tr:nth-child(even) { background: #faf9f8; }

.lo-num  { text-align: right; font-variant-numeric: tabular-nums; }
.lo-bold { font-weight: 700; }
/* Cells whose title spells the length calculation out (see linkLengthTooltip in panellinks.js) */
.lo-help { cursor: help; }

/* Link colour stripe, same rule as .link-color-stripe on the Created Links cards. */
.lo-id {
    position: relative;
    text-align: right;
    color: var(--dc-n-700);
    padding-left: 10px;
}

.lo-id::before {
    content: '';
    position: absolute;
    left: 2px;
    top: 2px;
    bottom: 2px;
    width: 3px;
    border-radius: 1px;
    background: var(--lo-link-color, #9b59b6);
}

/* Row markers are pinned left, clear of the right-aligned id, so the ids of a group line
   up whether or not a row carries one. _linkColsFor widens the column to suit. */
.lo-id-marks {
    position: absolute;
    left: 9px;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    gap: 3px;
}

/* The id cell carries the no-route and waypoint marks, which are chips. */
.lo-id .badge { margin: 0; }

/* The weight this rule used to force on a chip is gone with the rule: a chip carries its
   weight inline now, from its tone, and an inline value beats a stylesheet — a rule that
   cannot take effect reads as a promise the file does not keep. There is no chip in this
   cell anyway; it holds a cabinet label. */
.lo-to-rack { font-weight: 700; color: #2c3e50; }
.lo-to-rack .badge { margin-right: 4px; }

.lo-spans-n {
    font-size: var(--dc-text-2xs);
    color: var(--dc-n-700);
    margin-right: 2px;
    vertical-align: super;
}

.lo-notes {
    font-size: var(--dc-text-2xs);
    color: var(--dc-n-700);
    margin-top: 10px;
}

.lo-notes div {
    display: flex;
    align-items: center;
    gap: 5px;
    margin-top: 4px;
}

/* ── Panels overview (Equipment List tab) ─────────────────────────────────────
   Mirrors the PDF section in js/export.js: panel sides grouped by what actually gets
   installed, and each type drawn once as a schematic over the same chassis and module
   images the panel view uses. The chips both reports draw come from UITpl.chip, whose
   palette js/export.js also reads for the PDF — change the table and all three move
   together. .lo-section-caret above is shared with this section too.
   The flat one-row-per-shelf table stays available through Export to Excel. */
.po-summary {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 10px;
}

.po-stat {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 92px;
    padding: 8px 12px;
    background: #f4efec;
    border-radius: 6px;
}

.po-stat--warn { background: #fff3cd; }

.po-stat-v {
    font-size: var(--dc-text-lg);
    font-weight: 700;
    color: #2c3e50;
    line-height: 1.2;
}

.po-stat--warn .po-stat-v { color: #856404; }

.po-stat-k {
    font-size: var(--dc-text-2xs);
    color: var(--dc-n-700);
    text-transform: uppercase;
    letter-spacing: .3px;
}

/* Index of the type cards below: same badge, same name, plus the quantity. */
.po-types {
    /* Sized to its content, not to the modal: a full-width table would strand the
       quantity a hand's width away from the name it belongs to. */
    width: max-content;
    max-width: 100%;
    border-collapse: collapse;
    font-size: var(--dc-text-xs);
    margin-bottom: 20px;
}

.po-types th {
    text-align: left;
    padding: 3px 8px;
    border-bottom: 1px solid #e2dad6;
    font-weight: 700;
    color: var(--dc-n-700);
}

.po-types td {
    padding: 3px 8px;
    color: var(--dc-n-800);
}

.po-types tbody tr:nth-child(even) td { background: #faf9f8; }

.po-types .po-num {
    text-align: right;
    font-weight: 700;
    color: #2c3e50;
    font-variant-numeric: tabular-nums;
}

.po-types-badge { width: 1%; white-space: nowrap; }

/* The name stays on one line — it is a label, not a description. */
.po-types td:nth-child(2),
.po-types th:nth-child(2) { padding-right: 40px; white-space: nowrap; }

.po-types-mount { color: var(--dc-n-700); white-space: nowrap; }

/* Same chips as the type cards below — both reports build them with UITpl.chip. */
.po-types-ports { white-space: nowrap; }
.po-types-ports .badge { margin-right: 3px; }

.po-section { margin-bottom: 22px; }

.po-section-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0 5px;
    margin-bottom: 12px;
    border-bottom: 1.5px solid currentColor;
    font-size: var(--dc-text-lg);
    font-weight: 700;
    color: #a79189;
    cursor: pointer;
    list-style: none;
    user-select: none;
}

.po-section-head::-webkit-details-marker { display: none; }
.po-section[open] > .po-section-head .lo-section-caret { transform: rotate(90deg); }

.po-section-count {
    margin-left: auto;
    font-size: var(--dc-text-xs);
    font-weight: 500;
    color: var(--dc-n-700);
}

.po-group {
    border: 1px solid #ece5e2;
    border-radius: 8px;
    margin-bottom: 16px;
    overflow: hidden;
}

.po-group-head {
    display: flex;
    align-items: center;
    gap: 10px;
    background: #f4efec;
    padding: 8px 12px;
}

.po-type {
    background: #2c3e50;
    color: var(--dc-n-0);
    font-size: var(--dc-text-2xs);
    font-weight: 700;
    letter-spacing: .4px;
    padding: 2px 8px;
    border-radius: 4px;
}

.po-group-title {
    font-size: var(--dc-text-md);
    font-weight: 700;
    color: #2c3e50;
}

.po-group-count {
    margin-left: auto;
    font-size: var(--dc-text-xs);
    font-weight: 700;
    color: #a79189;
}

/* Computed fill: how much of the shelves' slot capacity the modules take. */
.po-fill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: var(--dc-text-2xs);
    font-weight: 600;
    color: var(--dc-n-700);
}

.po-fill-bar {
    display: block;
    width: 44px;
    height: 5px;
    border-radius: 3px;
    background: #e2dad6;
    overflow: hidden;
}

.po-fill-bar i {
    display: block;
    height: 100%;
    background: #1a9e7c;
}

/* The schematic: only the panels themselves — no rack sprite, no other equipment.
   .panel-unit / .panel-base-image / .panel-module come from panel-links.css, so the
   report and the panel view draw from one set of rules. column-reverse puts PP-01 on
   top, matching renderPanelHardware(). */
.po-schematic {
    padding: 14px 56px 14px 16px;
    background: var(--dc-n-0);
}

.po-stack {
    display: flex;
    flex-direction: column-reverse;
    align-items: flex-start;
    width: 300px;
}

.po-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 5px;
    padding: 0 12px 10px;
}

.po-facts {
    font-size: var(--dc-text-xs);
    color: var(--dc-n-800);
    padding: 0 12px 10px;
}

.po-facts div { margin-top: 3px; }
.po-facts b   { color: var(--dc-n-700); font-weight: 600; margin-right: 6px; }

.po-racks {
    border-top: 1px solid #ece5e2;
    padding: 8px 12px;
    background: #fbfaf9;
    font-size: var(--dc-text-xs);
}

.po-rack-zone {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px;
    margin-top: 4px;
}

.po-rack-zone-name {
    font-weight: 700;
    color: var(--dc-n-700);
    margin-right: 4px;
}

.po-rack-list {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}

/* Frame around one cabinet entry. What is inside it is the shared cabinet label
   (.cl, css/ui-templates.css) — this rule only draws the pill around it. */
.po-rack {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    background: var(--dc-n-0);
    border: 1px solid #e2dad6;
    border-radius: 4px;
    padding: 1px 6px;
    color: #2c3e50;
    white-space: nowrap;
}

.po-rack-side {
    font-style: normal;
    font-weight: 700;
    font-size: var(--dc-text-2xs);
}

.po-rack-side--front { color: #2980b9; }
.po-rack-side--rear  { color: #c0392b; }
/* The rail could not be named - same grey and the same reason as
   .lp-ep-panel-badge--unknown: which of the two sides this is, is what is not known. */
.po-rack-side--unknown { color: var(--dc-n-700); }

.po-rack--over {
    background: #fff3cd;
    border-color: #ffc107;
    color: #856404;
}

/* An ODF card is the cabinet itself: its own render with the cassettes of this
   rail marked on it and the other rails washed over, put there by
   _poFillOdfSchematics() (js/export.js) once it arrives over the network. It
   used to be a grid of little slot squares beside the picture; the picture says
   the same thing and says it about the real cabinet, so the grid went.

   Both the size of the box and the scale of the picture inside it are set in JS
   from _PO_ODF_FRONT_H — the render is laid out at its own pixel size and then
   scaled as a whole, exactly as the panel modal does it, so the hairline round
   each cassette stays a hairline instead of swallowing the cassette. Empty until
   the picture lands — and for good, if the preset has no render — so it takes no
   room at all until there is something in it. */
.po-schematic--odf { display: flex; }

.po-odf-front {
    position: relative;
    flex: none;
    overflow: hidden;
}
.po-odf-front:empty { display: none; }

/* ── Account modal ─────────────────────────────────────────────────────────
   Own profile + permissions. Laid out as independent sections so future
   account actions (change password, …) drop in as one more .acc-section. */

#accountModal {
    z-index: var(--dc-z-modal-account);
}

.acc-modal-content {
    position: relative;
    max-width: 520px;
    padding: 26px 28px;
}

.acc-state {
    padding: 20px 0;
    font-size: var(--dc-text-md);
    color: var(--dc-c-muted);
    display: flex;
    align-items: center;
    gap: var(--dc-space-3);
}

.acc-state--error { color: var(--dc-c-error); }

.acc-section { margin-bottom: 22px; }

.acc-section-title {
    font-size: var(--dc-text-xs);
    font-weight: 700;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    color: var(--dc-c-muted);
    padding-bottom: var(--dc-space-2);
    margin-bottom: var(--dc-space-3);
    border-bottom: 1px solid var(--dc-modal-divider);
}

.acc-row {
    display: flex;
    align-items: center;
    gap: var(--dc-space-4);
    padding: 5px 0;
    font-size: var(--dc-text-md);
}

.acc-row-label {
    flex: 0 0 108px;
    color: var(--dc-c-muted);
}

.acc-row-value {
    color: var(--dc-c-dark);
    font-weight: 500;
    word-break: break-word;
}

/* Role badge: .badge .badge--outline .badge--md plus one of these (js/account.js).
   Each is a tone in the primitive's sense — it sets the two properties --outline
   paints from and paints nothing itself. The ::before icon below reads the same
   colour through currentColor, which --outline sets from --badge-ink. */
.acc-role-badge--admin        { --badge-ink: var(--dc-c-role-admin);        --badge-line: var(--dc-c-role-admin); }
.acc-role-badge--expert       { --badge-ink: var(--dc-c-role-expert);       --badge-line: var(--dc-c-role-expert); }
.acc-role-badge--professional { --badge-ink: var(--dc-c-role-professional); --badge-line: var(--dc-c-role-professional); }
.acc-role-badge--user         { --badge-ink: var(--dc-c-role-user);         --badge-line: var(--dc-c-role-user); }

/* Role icon. Painted as a mask rather than an <img> so the glyph picks up the
   role colour from currentColor — the icon files carry a fixed brown fill that
   would fight the badge. Admin has no icon of its own, so only the three roles
   that do get a ::before. */
.acc-role-badge--expert::before,
.acc-role-badge--professional::before,
.acc-role-badge--user::before {
    content: '';
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    background-color: currentColor;
    -webkit-mask: var(--acc-role-icon) center / contain no-repeat;
            mask: var(--acc-role-icon) center / contain no-repeat;
}

.acc-role-badge--expert       { --acc-role-icon: url('../images/icon_Expert.svg'); }
.acc-role-badge--professional { --acc-role-icon: url('../images/icon_Professional.svg'); }
.acc-role-badge--user         { --acc-role-icon: url('../images/icon_Engineer.svg'); }

.acc-perm {
    display: flex;
    align-items: flex-start;
    gap: var(--dc-space-3);
    padding: 7px 0;
}

.acc-perm-mark {
    flex: 0 0 18px;
    text-align: center;
    font-size: 13px;
    font-weight: 700;
    line-height: 18px;
    color: var(--dc-c-success);
}

.acc-perm--off .acc-perm-mark { color: var(--dc-c-error); }

.acc-perm-mark--num {
    color: var(--dc-c-dark);
    font-size: 12px;
}

.acc-perm-text {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.acc-perm-label {
    font-size: var(--dc-text-md);
    font-weight: 600;
    color: var(--dc-c-dark);
    line-height: 18px;
}

.acc-perm-desc {
    font-size: var(--dc-text-xs);
    color: var(--dc-c-muted);
    line-height: 1.4;
}

.acc-perm-status {
    flex: 0 0 auto;
    font-size: var(--dc-text-xs);
    font-weight: 600;
    color: var(--dc-c-success);
    line-height: 18px;
    white-space: nowrap;
}

.acc-perm--off .acc-perm-status { color: var(--dc-c-muted); }

/* ── Password dialogs ─────────────────────────────────────────────────────── */
/* Both reuse .auth-modal / .auth-card; only the stacking differs. */
#changePasswordModal,
#tempPasswordModal { z-index: var(--dc-z-modal-password); }

/* Reveal toggle inside a password field. The button sits over the input's right
   edge, so the input reserves room for it instead of running text underneath. */
.pw-input-wrap {
    position: relative;
    display: flex;
    align-items: center;
}

.pw-input-wrap > .field {
    width: 100%;
    padding-right: 36px;
}

.pw-toggle {
    position: absolute;
    right: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    border: none;
    border-radius: var(--dc-radius-sm);
    background: none;
    color: var(--dc-c-muted);
    cursor: pointer;
    transition: color var(--dc-transition);
}

.pw-toggle:hover { color: var(--dc-c-dark); }
.pw-toggle:focus-visible { outline: none; box-shadow: var(--dc-focus-ring); }
.pw-toggle svg { width: 17px; height: 17px; display: block; }

/* Account modal: the password section is an action row, not a fact row. */
.acc-pw-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--dc-space-4);
}

.acc-pw-hint {
    font-size: var(--dc-text-xs);
    color: var(--dc-c-muted);
    line-height: 1.4;
}

.acc-note {
    font-size: var(--dc-text-xs);
    color: var(--dc-c-muted);
    padding-top: var(--dc-space-3);
    border-top: 1px solid var(--dc-modal-divider);
}

/* ── Solution Illustration: which sections to include ─────────────────────── */
/* One row per chapter of the PDF, asked before the export starts. The rows are
   built by showPdfSectionsModal() from PDF_REPORT_SECTIONS in js/export.js. */

.pdf-sections-intro {
    font-size: var(--dc-text-sm);
    color: var(--dc-c-muted);
    line-height: 1.4;
    margin: 0 0 var(--dc-space-4);
}

.pdf-sections-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.pdf-section-row {
    display: flex;
    align-items: flex-start;
    gap: var(--dc-space-4);
    padding: var(--dc-space-2) var(--dc-space-3);
    border-radius: var(--dc-radius-sm);
    cursor: pointer;
    transition: background var(--dc-transition-fast);
}

.pdf-section-row:hover { background: var(--dc-c-accent-light); }

.pdf-section-row input[type="checkbox"] {
    width: 15px;
    height: 15px;
    margin: 2px 0 0;
    accent-color: var(--dc-c-accent);
    cursor: pointer;
    flex-shrink: 0;
}

.pdf-section-text {
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.pdf-section-label {
    font-size: var(--dc-text-md);
    font-weight: 600;
    color: var(--dc-c-dark);
}

.pdf-section-hint {
    font-size: var(--dc-text-xs);
    color: var(--dc-c-muted);
    line-height: 1.35;
}

/* A sub-section is indented under the chapter it belongs to and goes flat with it:
   unchecking the parent leaves it nothing to illustrate. */
.pdf-section-row--sub { margin-left: 24px; }

.pdf-section-row.is-disabled {
    opacity: 0.45;
    cursor: default;
}

.pdf-section-row.is-disabled:hover { background: none; }
.pdf-section-row.is-disabled input[type="checkbox"] { cursor: default; }
