/* ── Admin-broadcast alert ticker (see /admin/alert-dashboard) ── */
.alert-ticker{
  flex-shrink:0;overflow:hidden;white-space:nowrap;padding:6px 0;
  border-bottom:1px solid var(--border);
}
/* Light pastel gradients per severity (explicit request 2026-09-03 — the
   original solid --accent/--amber/--red fills read as too dark/heavy for
   a persistent top-of-page strip). Fixed regardless of the page's own
   light/dark theme toggle, same reasoning the env-stripe banner in
   nits-auth-guard.js already uses a fixed color scheme -- a severity
   banner needs to read the same way for every viewer, not shift with
   their own theme preference. Dark, saturated text (not white) for
   contrast against these light backgrounds. */
.alert-ticker.info{background:linear-gradient(90deg,#e0f2fe,#bae6fd);color:#075985;}
.alert-ticker.warning{background:linear-gradient(90deg,#fef3c7,#fde68a);color:#92400e;}
.alert-ticker.critical{background:linear-gradient(90deg,#fee2e2,#fecaca);color:#991b1b;}
.alert-ticker-track{
  display:inline-block;padding-left:100%;font-weight:600;font-size:13px;
  animation-name:alert-ticker-scroll;animation-timing-function:linear;animation-iteration-count:infinite;
  /* `nowrap` (inherited from .alert-ticker) only stops line-wrapping -- it
     does NOT stop the browser from collapsing runs of plain spaces down to
     one, which silently ate alert-banner.js's wider inter-alert spacing.
     `pre` preserves every space exactly as authored (and still never wraps,
     same as nowrap, since there's nothing here to wrap onto a new line). */
  white-space:pre;
}
@keyframes alert-ticker-scroll{from{transform:translateX(0);}to{transform:translateX(-100%);}}

/* ── Top bar ── */
.topbar{
  background:var(--surface);border-bottom:1px solid var(--border);
  padding:0 16px;height:64px;display:flex;align-items:center;gap:10px;
  flex-shrink:0;
}
.topbar-logo{font-size:15px;font-weight:700;color:var(--accent);letter-spacing:-.3px;display:none;}
.topbar-sep{width:1px;height:24px;background:var(--border);}
.search-form{display:flex;align-items:center;gap:6px;flex:0 1 560px;}
.search-select{
  background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius);
  color:var(--text);padding:5px 10px;font-size:12px;cursor:pointer;outline:none;
}
.search-select:focus{border-color:var(--accent);}
.search-by{color:var(--text2);font-weight:500;font-size:12px;}
.search-input{
  flex:1;min-width:0;background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius);padding:6px 10px;font-size:12px;
  color:var(--text);outline:none;
}
.search-input:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-light);}
.btn{
  padding:6px 14px;border-radius:var(--radius);font-size:12px;font-weight:500;
  cursor:pointer;border:none;transition:all .12s;white-space:nowrap;
}
.btn-primary{background:#0093a5;color:#fff;}
.btn-primary:hover{background:#007a8a;}
.btn-ghost{background:var(--surface2);border:1px solid var(--border);color:var(--text2);}
.btn-ghost:hover{color:var(--text);border-color:#9ca3af;}
/* "+ New X" create buttons — light-blue chip look */
.btn-create{background:#dbeafe;color:#1d4ed8;border:1px solid #93c5fd;}
.btn-create:hover{background:#bfdbfe;border-color:#60a5fa;}
.topbar-actions{margin-left:auto;display:flex;gap:6px;}
.topbar-link{
  font-family:inherit;font-size:12px;color:var(--accent);text-decoration:none;padding:5px 10px;
  border:1px solid var(--accent-border);border-radius:var(--radius);
  background:var(--accent-light);cursor:pointer;
}
.topbar-link:hover{opacity:.85;}

/* ── Generic "Create X" modal (schema-driven — see openCreateModal()) ── */
.modal-overlay{
  position:fixed;inset:0;z-index:2000;background:rgba(0,0,0,.5);
  display:flex;align-items:center;justify-content:center;padding:20px;
}
.modal-card{
  background:var(--surface);border:1px solid var(--border);border-radius:10px;
  max-width:480px;width:100%;max-height:88vh;display:flex;flex-direction:column;
  box-shadow:var(--shadow-lg);overflow:hidden;
}
.modal-card-header{
  display:flex;align-items:center;gap:10px;padding:14px 18px;
  border-bottom:1px solid var(--border);flex-shrink:0;
}
.modal-card-header h3{font-size:15px;font-weight:700;color:var(--text);}
.modal-card-body{padding:16px 18px;overflow:auto;flex:1;display:flex;flex-direction:column;gap:12px;}
.modal-card-footer{
  display:flex;gap:10px;align-items:center;padding:12px 18px;
  border-top:1px solid var(--border);flex-shrink:0;
}
.field-row{display:flex;flex-direction:column;gap:4px;}
.field-label{font-size:12px;font-weight:600;color:var(--text2);}
.field-label .req{color:var(--red);}
.field-input,.field-select{
  background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius);
  color:var(--text);padding:7px 10px;font-size:13px;font-family:inherit;outline:none;
}
.field-input:focus,.field-select:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-light);}
.field-input.invalid,.field-select.invalid{border-color:var(--red);}
/* auto-filled-from-parent + locked (read-only) fields */
.field-input.locked,.field-select.locked{background:var(--border);color:var(--text2);cursor:not-allowed;opacity:.85;}
/* field.disabled (temporary, schema-driven — see openCreateModal) */
.field-disabled{opacity:.5;}
.field-disabled .field-label{cursor:not-allowed;}
.field-error{font-size:11.5px;color:var(--red);}
/* lookup field: input + choose (▾) + create (+) — data wired later */
.field-lookup{display:flex;gap:4px;align-items:stretch;}
.field-lookup .field-input{flex:1;min-width:0;}
.lookup-btn,.lookup-new{
  background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius);
  color:var(--text2);padding:0 10px;font-size:12px;cursor:pointer;flex-shrink:0;
}
.lookup-btn:hover,.lookup-new:hover{background:var(--border);color:var(--text);}
/* lookup typeahead picker (fields with a lookup_endpoint) */
.field-lookup .lookup-search{flex:1;min-width:0;}
.lookup-clear{background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius);
  color:var(--text2);padding:0 10px;font-size:12px;cursor:pointer;flex-shrink:0;}
.lookup-clear:hover{background:var(--border);color:var(--text);}
.lookup-results{position:absolute;top:calc(100% + 2px);left:0;right:0;z-index:60;
  background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius);
  max-height:210px;overflow-y:auto;box-shadow:0 6px 18px rgba(0,0,0,.18);}
.lookup-result{padding:7px 10px;cursor:pointer;font-size:12.5px;border-bottom:1px solid var(--border);}
.lookup-result:last-child{border-bottom:none;}
.lookup-result:hover,.lookup-result.active{background:var(--accent-light);}
.lookup-result .lr-name{font-weight:600;color:var(--text);}
.lookup-result .lr-full{color:var(--text3);margin-left:6px;}
.lookup-empty{padding:8px 10px;color:var(--text3);font-size:12px;}
.field-checkbox{width:16px;height:16px;cursor:pointer;flex-shrink:0;margin:0;}
/* datetime field: text input + T/N/C buttons */
.field-datetime{display:flex;gap:4px;align-items:stretch;}
.field-datetime .dt-input{flex:1;min-width:0;}
.dt-btn{background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius);
  color:var(--text2);padding:0 9px;font-size:12px;font-weight:600;cursor:pointer;flex-shrink:0;}
.dt-btn:hover{background:var(--border);color:var(--text);}
/* checkbox row: box in front of the label, on one line */
.field-cb-row{display:flex;align-items:center;gap:8px;cursor:pointer;
  font-size:12px;font-weight:600;color:var(--text2);}
.field-color{width:60px;height:32px;padding:2px;cursor:pointer;
  background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius);}
/* modal tabs + footer option checkboxes */
.cm-tabs{display:flex;gap:2px;padding:0 18px;border-bottom:1px solid var(--border);flex-shrink:0;}
.cm-tab{padding:8px 14px;font-size:12.5px;font-weight:600;color:var(--text2);cursor:pointer;
  border:1px solid transparent;border-bottom:none;border-radius:6px 6px 0 0;background:transparent;}
.cm-tab.active{background:var(--surface2);color:var(--text);border-color:var(--border);}
.cm-tabpane{display:none;flex-direction:column;gap:12px;}
.cm-tabpane.active{display:flex;}
.cm-footer-opts{display:flex;gap:14px;align-items:center;font-size:12px;color:var(--text2);}
.cm-footer-opts label{display:flex;gap:5px;align-items:center;cursor:pointer;}
.modal-card.wide{max-width:640px;}
/* ── Grid picker (schema field.grid_picker) — a sortable/filterable/paginated
   browse-the-full-table popup, opened via the extra "⊞" button next to a
   lookup field's usual quick typeahead. Reuses the .modal-overlay backdrop
   but its own wider/taller card. ── */
/* height (not max-height): fixed so the popup doesn't resize itself as the
   filtered row count changes while typing — .gp-body's own overflow:auto
   absorbs having more or fewer rows than fit, instead of the whole card
   growing/shrinking and visibly jumping around the screen on every keystroke. */
.gp-card{background:var(--surface);border:1px solid var(--border);border-radius:10px;
  max-width:1040px;width:100%;height:86vh;display:flex;flex-direction:column;
  box-shadow:var(--shadow-lg);overflow:hidden;}
.gp-header{display:flex;align-items:center;gap:10px;padding:14px 18px;
  border-bottom:1px solid var(--border);flex-shrink:0;}
.gp-header h3{font-size:15px;font-weight:700;color:var(--text);}
.gp-body{flex:1;overflow:auto;position:relative;}
/* table-layout:fixed so a width set on a header <th> (see .gp-col-resizer
   drag handler in create-modal.js) pins that column for every row instead
   of the browser recomputing widths from cell content on each reload. */
.gp-table{width:100%;border-collapse:collapse;font-size:12px;table-layout:fixed;}
.gp-table thead th{position:sticky;top:0;background:var(--accent);color:#fff;
  padding:7px 10px;text-align:left;font-size:10.5px;font-weight:700;
  text-transform:uppercase;letter-spacing:.3px;cursor:pointer;user-select:none;
  border-right:1px solid rgba(255,255,255,.15);white-space:nowrap;}
.gp-table thead th:hover{background:var(--accent-dark,var(--accent));opacity:.92;}
.gp-table thead th .gp-sort-arrow{margin-left:4px;opacity:.85;}
.gp-col-resizer{position:absolute;top:0;right:0;width:8px;height:100%;
  cursor:col-resize;user-select:none;}
.gp-col-resizer:hover,.gp-col-resizer.resizing{background:rgba(255,255,255,.35);}
.gp-filter-row th{position:sticky;top:29px;background:var(--surface2);padding:4px 6px;
  border-right:1px solid var(--border);border-bottom:1px solid var(--border);}
.gp-filter-row input{width:100%;box-sizing:border-box;font-size:11.5px;padding:4px 6px;
  border:1px solid var(--border);border-radius:4px;background:var(--surface);color:var(--text);}
.gp-table tbody td{padding:6px 10px;border-bottom:1px solid var(--border);color:var(--text);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:220px;}
.gp-table tbody tr{cursor:pointer;}
.gp-table tbody tr:hover{background:var(--accent-light);}
.gp-table tbody tr:nth-child(even){background:var(--surface2);}
.gp-table tbody tr:nth-child(even):hover{background:var(--accent-light);}
.gp-empty,.gp-loading{padding:30px;text-align:center;color:var(--text3);font-size:12.5px;}
.gp-footer{display:flex;align-items:center;gap:10px;padding:10px 18px;
  border-top:1px solid var(--border);flex-shrink:0;font-size:12px;color:var(--text2);}
.gp-footer .gp-spacer{margin-left:auto;}
.gp-page-input{width:52px;text-align:center;border:1px solid var(--border);border-radius:4px;
  padding:3px 4px;background:var(--surface2);color:var(--text);}
/* Wider still + 2-column field grid, opt-in via schema.two_col (Node's form —
   13 fields in one flex column was an unusable amount of vertical scroll).
   Rule order matters: this must come after .wide above so it wins when both
   classes are present (schema.wide is left on NODE for back-compat). */
.modal-card.twocol{max-width:920px;}
.cm-tabpane.active.twocol-grid{display:grid;grid-template-columns:1fr 1fr;column-gap:22px;row-gap:14px;align-items:start;}
.field-row.full-row{grid-column:1/-1;}

/* ── Relation diagram (schema.relation_diagram) — a small live picture of how
   each picked relation (Order/Customer/Site/etc.) feeds into the record being
   created, sitting above the fields. Purely visual: boxes start empty ("—")
   and light up with the picked label as the corresponding field is filled in
   (wireRelationDiagram() in ui-common.js does the live updating). ── */
.cm-diagram-wrap{margin-bottom:2px;}
.cm-diagram-svg{width:100%;height:auto;display:block;}
.cm-diag-centerbox{fill:var(--accent);stroke:var(--accent);}
.cm-diag-centertext{fill:#fff;font-size:13px;font-weight:700;font-family:inherit;}
.cm-diag-line{stroke:var(--border);stroke-width:1.5;}
.cm-diag-box{fill:var(--surface2);stroke:var(--border);stroke-width:1;transition:fill .15s,stroke .15s;}
.cm-diag-node.filled .cm-diag-box{fill:var(--accent-light);stroke:var(--accent);}
.cm-diag-label{fill:var(--text2);font-size:9.5px;font-weight:600;font-family:inherit;}
.cm-diag-value{fill:var(--text3);font-size:10px;font-family:inherit;}
.cm-diag-node.filled .cm-diag-value{fill:var(--text);font-weight:600;}
/* Endpoint group boxes (Circuit's A_End / B_End Details) — one box listing
   Site/Port/Node instead of six separate spokes. */
.cm-diag-groupbox{fill:var(--surface2);stroke:var(--accent);stroke-width:1.3;}
.cm-diag-grouptitle{fill:var(--accent);font-size:11px;font-weight:700;font-family:inherit;}
.cm-diag-grouplabel{fill:var(--text2);font-size:10.5px;font-weight:600;font-family:inherit;}

/* ── Breadcrumb ── */
.breadcrumb{
  background:var(--surface);border-bottom:1px solid var(--border);
  padding:6px 16px;display:flex;align-items:center;gap:4px;
  flex-shrink:0;min-height:32px;flex-wrap:wrap;
}
.bc-item{
  display:flex;align-items:center;gap:4px;font-size:11px;
  cursor:pointer;padding:2px 6px;border-radius:4px;
}
.bc-item:hover{background:var(--accent-light);}
.bc-sep{color:var(--text3);font-size:10px;}
.bc-tag{
  font-size:10px;font-weight:600;padding:1px 6px;border-radius:10px;
  color:#fff;letter-spacing:.3px;
}
.bc-tag.Customer{background:#16a34a;}
.bc-tag.Circuit{background:#0093a5;}
.bc-tag.Node{background:#7c3aed;}
.bc-tag.Equipment{background:#d97706;}
.bc-tag.Location{background:#0891b2;}
.bc-tag.Order{background:#db2777;}
.bc-tag.Port{background:#0093a5;}
.bc-tag.Rack{background:#475569;}
.bc-tag.Site{background:#0891b2;}
.bc-tag.Ddfodf,.bc-tag.DdfOdf,.bc-tag.ddfodf{background:#9a3412;}
.bc-tag.Domain,.bc-tag.domain{background:#0e7490;}
.bc-tag.Olo,.bc-tag.olo{background:#4338ca;}
.bc-empty{color:var(--text3);font-size:11px;font-style:italic;}

/* ── Layout ── */
.layout{flex:1;display:flex;overflow:hidden;position:relative;}

/* ── Tree panel ── */
.tree-panel{
  width:420px;flex-shrink:0;background:var(--surface);
  border-right:1px solid var(--border);
  display:flex;flex-direction:column;overflow:hidden;
}
.tp-header{
  padding:10px 14px;border-bottom:1px solid var(--border);
  display:flex;align-items:center;justify-content:space-between;flex-shrink:0;
}
.tp-title{font-size:12px;font-weight:600;color:var(--text2);
  text-transform:uppercase;letter-spacing:.6px;}
.tp-header-right{display:flex;align-items:center;gap:8px;}
.tp-count{font-size:11px;color:var(--text3);}
.tree-scroll{flex:1;overflow-y:auto;padding:6px 0;}
.tree-empty{padding:40px 20px;text-align:center;color:var(--text3);line-height:1.8;}
.tree-loading{padding:20px;text-align:center;color:var(--text2);}

/* ── Tree items ── */
.tree-item{
  display:flex;align-items:center;gap:6px;
  padding:5px 14px;cursor:pointer;
  border-left:3px solid transparent;transition:all .1s;
  user-select:none;
}
.tree-item:hover{background:var(--surface2);}
.tree-item.selected{background:var(--accent-light);border-left-color:var(--accent);}
.tree-item.expanded>.ti-toggle{transform:rotate(90deg);}
.ti-toggle{
  width:14px;height:14px;display:flex;align-items:center;justify-content:center;
  font-size:9px;color:var(--text3);flex-shrink:0;transition:transform .15s;
}
.ti-indent{width:14px;flex-shrink:0;}
.ti-tag{
  font-size:9px;font-weight:700;padding:1px 5px;border-radius:3px;
  flex-shrink:0;letter-spacing:.3px;
}
.ti-tag.Circuit,.ti-tag.circuit{background:#edfafe;color:#0093a5;}
.ti-tag.Customer,.ti-tag.customer{background:#dcfce7;color:#166534;}
.ti-tag.Node,.ti-tag.node{background:#ede9fe;color:#5b21b6;}
.ti-tag.Equipment,.ti-tag.equipment{background:#fef3c7;color:#92400e;}
.ti-tag.Location,.ti-tag.location{background:#cffafe;color:#164e63;}
.ti-tag.Order,.ti-tag.order{background:#fce7f3;color:#9d174d;}
.ti-tag.Port,.ti-tag.port,.ti-tag.portTemplate,.ti-tag.internalPort{background:#e0e7ff;color:#0093a5;}
.ti-tag.Shelf,.ti-tag.shelf{background:#f3e8ff;color:#6b21a8;}
.ti-tag.Slot,.ti-tag.slot{background:#dbeafe;color:#1e40af;}
.ti-tag.Card,.ti-tag.card,.ti-tag.nodeCardFilling,.ti-tag.cardsPerSlot,.ti-tag.cardCodesPerSlot{background:#fef9c3;color:#713f12;}
.ti-tag.Relation,.ti-tag.relation{background:#f0fdf4;color:#166534;border:1px solid #86efac;}
.ti-tag.Rack,.ti-tag.rack{background:#e2e8f0;color:#334155;}
.ti-tag.Block,.ti-tag.block{background:#fee2e2;color:#991b1b;}
.ti-tag.Ddf,.ti-tag.ddf{background:#ffedd5;color:#9a3412;}
.ti-tag.Domain,.ti-tag.domain{background:#cffafe;color:#0e7490;}
.ti-tag.Olo,.ti-tag.olo{background:#e0e7ff;color:#4338ca;}
.ti-name{flex:1;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.ti-name strong{font-weight:600;}
.ti-id{font-size:10px;color:var(--text3);font-family:var(--mono);flex-shrink:0;}
/* 📝 Update Circuit button, top-right of the tree panel header — styled to
   match the "+ New X" create-button chip look (.btn-create) so it reads as
   the same family of action. Shown only while a circuit is loaded — see
   showTreeEditButton()/hideTreeEditButton() in ui-common.js. */
.ti-edit-btn{border:1px solid #93c5fd;background:#dbeafe;
  color:#1d4ed8;cursor:pointer;font-size:11px;font-weight:600;letter-spacing:.3px;
  padding:2px 8px;border-radius:4px;flex-shrink:0;line-height:1.3;white-space:nowrap;}
.ti-edit-btn:hover{background:#bfdbfe;border-color:#60a5fa;}
/* Read-only users: Cable Connect / Remove IP buttons stay visible (so the
   feature is discoverable) but render disabled rather than being hidden
   outright, unlike Update Circuit/Update Node/Assign IP above. */
.cable-connect-btn:disabled,.dom-ip-remove:disabled{opacity:.35;cursor:not-allowed;}
.ti-status{
  font-size:9px;font-weight:600;padding:1px 5px;border-radius:3px;flex-shrink:0;
}
.ti-status.IS{background:#dcfce7;color:#166534;}
.ti-status.PL{background:#fef3c7;color:#92400e;}
.ti-status.MI{background:#ede9fe;color:#5b21b6;}
.ti-status.RFC{background:#fee2e2;color:#991b1b;}

/* ── Equipment Definition tree — scoped to #tree-panel.def-mode only, so
   Instance-mode trees (Node/Circuit/Customer/etc.) are unaffected. Bumped
   up from the base 9-12px sizes because the Definition tree packs 5 levels
   (Node>Shelf>Slot>Option>CardCode) and users found the base sizing too
   small to read comfortably at that depth. */
.tree-panel.def-mode .tp-title{font-size:13.5px;}
.tree-panel.def-mode .tp-count{font-size:12px;}
.tree-panel.def-mode .ti-tag{font-size:10.5px;padding:2px 6px;}
.tree-panel.def-mode .ti-name{font-size:13.5px;}
.tree-panel.def-mode .ti-id{font-size:11.5px;}
.tree-panel.def-mode .ti-status{font-size:10px;padding:2px 6px;}
.tree-panel.def-mode .tree-item{padding:7px 14px;}

/* ── Children indented ── */
.tree-children{border-left:1px dashed var(--border);margin-left:20px;}

/* ── Detail panel ── */
.detail-panel{
  width:340px;flex-shrink:0;background:var(--surface);
  border-left:1px solid var(--border);
  display:flex;flex-direction:column;overflow:hidden;
  transition:width .2s ease-out;
}
.detail-panel.collapsed{width:0;border-left:none;}
/* Anchored to .breadcrumb-row (position:relative) instead of .layout —
   canvas-area's own top row is different per view (Circuits by Customer/
   Order/Site/Rack toolbars, the Circuit Detail carriers workspace's action
   bar, plain placeholders, ...) and every one of them has, at some point,
   ended up with its own right-aligned text sitting exactly where a
   .layout-anchored pill would float. The breadcrumb row is the one place
   above .layout that's always a plain, stable single line with empty space
   on the right — anchoring here sidesteps the whole whack-a-mole problem
   instead of patching it view by view. */
.breadcrumb-row{position:relative;}
#dp-reopen{
  /* Not draggable (tried and reverted per user request — kept simple/
     static). Collapsed to just the icon by default (max-width clips the
     label span to 0) — expands on hover/focus to show the "Details" label.
     Anchored via `right:8px` (no `left`), so growing max-width keeps the
     right edge fixed and the box expands towards the left, same pattern as
     the session badge in nits-auth-guard.js. */
  position:absolute;top:50%;right:8px;transform:translateY(-50%);z-index:100;
  background:var(--accent);color:white;border:none;
  border-radius:20px;padding:8px;font-size:11px;
  font-weight:600;cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,.15);
  display:none;
  max-width:34px;overflow:hidden;white-space:nowrap;
  transition:max-width .18s ease,padding .18s ease;
}
#dp-reopen:hover{background:#007585;}
#dp-reopen:hover,#dp-reopen:focus{max-width:140px;padding:6px 12px;}
#dp-reopen .dp-reopen-label{
  display:inline-block;margin-left:5px;opacity:0;
  transition:opacity .12s ease .04s;
}
#dp-reopen:hover .dp-reopen-label,#dp-reopen:focus .dp-reopen-label{opacity:1;}
.dp-header{
  padding:10px 14px;border-bottom:1px solid var(--border);
  display:flex;align-items:center;gap:8px;flex-shrink:0;
}
.dp-badge{font-size:11px;font-weight:700;padding:2px 8px;border-radius:10px;color:#fff;}
.dp-badge.Customer{background:#16a34a;}
.dp-badge.Circuit{background:#0093a5;}
.dp-badge.Node{background:#7c3aed;}
.dp-badge.Equipment{background:#d97706;}
.dp-badge.Location{background:#0891b2;}
.dp-badge.Order{background:#db2777;}
.dp-badge.Port{background:#0093a5;}
.dp-badge.Rack{background:#475569;}
.dp-badge.Block{background:#991b1b;}
.dp-badge.Ddf,.dp-badge.DdfOdf,.dp-badge.ddfodf{background:#9a3412;}
.dp-badge.Domain,.dp-badge.domain{background:#0e7490;}
.dp-badge.Olo,.dp-badge.olo{background:#4338ca;}
.dp-badge.Shelf{background:#6b21a8;}
.dp-id{font-size:12px;font-weight:600;flex:1;}
.dp-close,.dp-minimize{
  background:none;border:1px solid var(--border);border-radius:4px;
  color:var(--text3);padding:2px 7px;cursor:pointer;font-size:11px;
}
.dp-close{color:var(--red);border-color:#fecaca;}
.dp-close:hover{background:#fee2e2;}
/* Small icon-only toolbar control (e.g. node workspace's "reset layout") —
   same visual language as .dp-close/node-detail-close, sized as a square
   so a single glyph sits centered rather than padded like a text button. */
.ctrl-btn{
  background:none;border:1px solid var(--border);border-radius:4px;
  color:var(--text2);font-size:13px;cursor:pointer;
  width:24px;height:24px;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;padding:0;
}
.ctrl-btn:hover{background:var(--accent-light);color:var(--accent);border-color:var(--accent-border);}
.dp-scroll{flex:1;overflow-y:auto;}
.dp-section{padding:10px 14px;border-bottom:1px solid var(--border);}
.dp-section-title{
  font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.6px;
  color:var(--text3);margin-bottom:8px;
}
.dp-row{display:flex;justify-content:space-between;align-items:baseline;
  padding:3px 0;gap:8px;border-bottom:1px solid #f3f4f6;}
.dp-row:last-child{border-bottom:none;}
.dp-key{font-size:10px;color:var(--text3);text-transform:uppercase;letter-spacing:.4px;flex-shrink:0;}
.dp-val{font-size:11px;color:var(--text);text-align:right;word-break:break-all;
  font-family:var(--mono);max-width:200px;overflow:hidden;text-overflow:ellipsis;}
.dp-empty{padding:40px 16px;text-align:center;color:var(--text3);line-height:1.8;}

/* ── Relations ── */
.dp-relations{padding:10px 14px;}
.dp-rel-title{font-size:10px;font-weight:600;text-transform:uppercase;
  letter-spacing:.6px;color:var(--text3);margin-bottom:8px;}
.rel-tags{display:flex;flex-wrap:wrap;gap:5px;}
.rel-tag{
  font-size:11px;padding:3px 10px;border-radius:4px;cursor:pointer;
  border:1px solid var(--border);background:var(--surface2);
  color:var(--accent);font-weight:500;transition:all .1s;
}
.rel-tag:hover{background:var(--accent-light);border-color:var(--accent-border);}

/* ── Canvas area ── */
.canvas-area{
  flex:1;background:var(--bg);position:relative;overflow:hidden;
  display:flex;flex-direction:column;
}
.canvas-area > .canvas-placeholder{
  margin:auto;text-align:center;
}
.canvas-placeholder{text-align:center;color:var(--text3);line-height:2;}
.canvas-placeholder h3{font-size:16px;font-weight:600;color:var(--text2);margin-bottom:8px;}
.canvas-placeholder p{font-size:12px;}

/* ── Tabs ── */
.tab-bar{
  display:flex;gap:0;border-bottom:1px solid var(--border);
  padding:0 14px;background:var(--surface);flex-shrink:0;
}
.tab{
  padding:8px 14px;font-size:11px;font-weight:500;color:var(--text2);
  cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;
}
.tab.active{color:var(--accent);border-bottom-color:var(--accent);}
.tab:hover:not(.active){color:var(--text);}

/* ── Cards in canvas ── */
.cards-grid{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(195px,1fr));
  gap:8px;padding:10px;
  overflow-y:auto;width:100%;height:100%;align-content:flex-start;
}
.result-card{
  background:var(--surface);border:1px solid var(--border);border-radius:8px;
  padding:10px;width:100%;cursor:pointer;transition:all .15s;
  box-shadow:var(--shadow);display:flex;flex-direction:column;gap:0;
  min-height:100px;overflow:hidden;box-sizing:border-box;
}
.result-card:hover{box-shadow:var(--shadow-lg);border-color:var(--accent-border);}
.result-card.selected{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-light);}
.rc-tag{display:inline-block;font-size:9px;font-weight:700;padding:1px 6px;
  border-radius:3px;margin-bottom:6px;}
.rc-name{font-size:12px;font-weight:600;color:var(--text);margin-bottom:3px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.3;}
.rc-sub{font-size:10px;color:var(--text2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.rc-id{font-size:9px;color:var(--text3);font-family:var(--mono);margin-top:4px;}

/* ── Status indicator ── */
#status-bar{
  position:fixed;bottom:0;left:0;right:0;height:var(--statusbar-h);
  background:var(--surface);border-top:1px solid var(--border);
  display:flex;align-items:center;padding:0 14px;gap:12px;
  font-size:10px;color:var(--text3);z-index:100;
}
.sb-dot{width:6px;height:6px;border-radius:50%;display:inline-block;margin-right:4px;}
.sb-dot.ok{background:var(--green);}
.sb-dot.err{background:var(--red);}
.sb-dot.loading{background:var(--amber);animation:pulse 1s infinite;}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.4}}

* { scrollbar-width: auto; scrollbar-color: var(--text3) var(--surface2); }
::-webkit-scrollbar{width:6px;height:6px;}
::-webkit-scrollbar-track{background:var(--surface2);}
::-webkit-scrollbar-thumb{background:color-mix(in srgb, var(--text3) 55%, transparent);
  border-radius:4px;border:1px solid var(--surface2);background-clip:padding-box;}
::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb, var(--text2) 80%, transparent);}

/* ── Split view ── */
.split-view{display:flex;gap:0;height:100%;width:100%;overflow:hidden;}
.split-left{flex-shrink:0;border-right:1px solid var(--border);
  overflow:hidden;display:flex;flex-direction:column;}
.split-right{flex:1;overflow:auto;padding:16px;min-width:0;display:flex;
  align-items:flex-start;justify-content:flex-start;}
/* Shared by both the circuit and node workspaces' split panes (see circuit.css
   and node.css #cct-*/#node-* layout-fix blocks, which used to sit next to
   this rule before the CSS split — kept here since .split-left/.split-right
   themselves are generic, not circuit- or node-specific). */
.split-left, .split-right { min-width: 0; }
.sv-header{padding:10px 14px;border-bottom:1px solid var(--border);
  font-size:11px;font-weight:600;color:var(--text2);flex-shrink:0;
  text-transform:uppercase;letter-spacing:.5px;}
.sv-tabs-wrap{display:flex;align-items:stretch;flex-shrink:0;
  border-bottom:2px solid var(--border);overflow:hidden;}
.sv-tabs{display:flex;flex-wrap:nowrap;overflow-x:auto;flex:1;min-width:0;
  scrollbar-width:none;-ms-overflow-style:none;}
.sv-tabs::-webkit-scrollbar{display:none;height:0;}
.sv-tab-nav{flex-shrink:0;width:20px;display:none;align-items:center;
  justify-content:center;cursor:pointer;background:var(--surface);
  border:none;border-left:1px solid var(--border);color:var(--text2);
  font-size:13px;font-weight:700;user-select:none;}
.sv-tab-nav.prev{border-left:none;border-right:1px solid var(--border);}
.sv-tab-nav:hover{color:var(--accent);background:var(--accent-light);}
.sv-tab-nav[disabled]{opacity:.3;cursor:default;pointer-events:none;}
.sv-tab{
  padding:6px 10px;font-size:10px;font-weight:600;cursor:pointer;
  border-bottom:2px solid transparent;color:var(--text2);
  text-align:center;min-width:52px;flex-shrink:0;
  transition:color .15s,background .15s;user-select:none;
  white-space:nowrap;
}
.sv-tab:hover{color:var(--accent);background:var(--accent-light);}
.sv-tab.active{color:var(--accent);border-bottom-color:var(--accent);background:var(--accent-light);}

/* ── Draggable divider between tab panel and detail panel ────────────────── */
.hsplit-resizer{flex-shrink:0;width:6px;cursor:ew-resize;
  background:var(--surface);border-left:1px solid var(--border);
  border-right:2px solid var(--accent);position:relative;transition:background .1s;}
.hsplit-resizer:hover{background:var(--accent-light);}
.hsplit-resizer .hsplit-grip{position:absolute;top:50%;left:50%;
  transform:translate(-50%,-50%) rotate(90deg);width:16px;height:3px;
  background:var(--text3);border-radius:2px;opacity:.5;}

/* ── Draggable divider on each table column header — lets a planner widen a
   truncated column (long card/circuit names, CardComCode strings, etc that
   otherwise clip with an ellipsis). Attached by makeColumnsResizable() /
   makeGridColumnsResizable() to every header cell except the last. ── */
.col-resize-handle{position:absolute;top:0;right:0;bottom:0;width:6px;
  cursor:col-resize;z-index:5;}
.col-resize-handle:hover,.col-resize-handle:active{background:rgba(255,255,255,.35);}

/* ── Inline hyperlink used inside table cells (e.g. Ports tab's Circuit /
   CableDetails columns) — a plain-text cell value that navigates somewhere
   on click, distinct from the row itself being clickable. ── */
.port-link{color:var(--accent);font-weight:600;cursor:pointer;}
.port-link:hover{text-decoration:underline;}
