:root {
      --ink: #0f172a;
      --ink-soft: #334155;
      --muted: #64748b;
      --line: #e2e8f0;
      --line-strong: #cbd5e1;
      --bg: #f8fafc;
      --panel: #ffffff;
      --accent: #1d4ed8;
      --accent-soft: #dbeafe;
      --header-h: 60px;
      --sidebar-w: 288px;
      --maxw: 1180px;
      font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    }

    * {
      box-sizing: border-box;
    }

    html, body {
      height: 100%;
    }

    html {
      -webkit-text-size-adjust: 100%;
      text-size-adjust: 100%;
    }

    body {
      margin: 0;
      color: var(--ink);
      background: var(--bg);
      line-height: 1.6;
      display: flex;
      flex-direction: column;
      min-height: 100%;
    }

    /* Masthead — aligned with A&J Studio Corporate Governance */
    .masthead {
      position: sticky;
      top: 0;
      z-index: 50;
      flex: 0 0 auto;
      height: var(--header-h);
      display: flex;
      align-items: center;
      gap: 14px;
      padding: 0 max(20px, env(safe-area-inset-right)) 0 max(20px, env(safe-area-inset-left));
      background: #0f172a;
      color: #f8fafc;
      box-shadow: 0 1px 0 rgba(15, 23, 42, 0.08);
    }

    .brand {
      display: flex;
      align-items: center;
      gap: 12px;
      min-width: 0;
      color: inherit;
      text-decoration: none;
    }

    .brand-text {
      display: flex;
      flex-direction: column;
      min-width: 0;
      line-height: 1.2;
    }

    .brand-title {
      font-weight: 700;
      font-size: 17px;
    }

    .brand-subtitle {
      font-size: 12.5px;
      color: #cbd5e1;
      letter-spacing: 0.3px;
    }

    .nav-toggle {
      display: none;
      flex-shrink: 0;
      flex-direction: column;
      justify-content: center;
      gap: 4px;
      width: 44px;
      height: 44px;
      padding: 0 8px;
      background: transparent;
      border: 1px solid rgba(248, 250, 252, 0.25);
      border-radius: 8px;
      cursor: pointer;
    }

    .nav-toggle span {
      display: block;
      height: 2px;
      background: #f8fafc;
      border-radius: 2px;
    }

    .nav-backdrop {
      display: none;
    }

    .spa-nav {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 0.35rem;
      margin-left: auto;
    }

    .spa-nav button {
      font: inherit;
      font-size: 0.88rem;
      font-weight: 600;
      padding: 0.4rem 0.85rem;
      border: 1px solid rgba(248, 250, 252, 0.22);
      border-radius: 8px;
      background: transparent;
      color: #e2e8f0;
      cursor: pointer;
    }

    .spa-nav button:hover {
      background: rgba(248, 250, 252, 0.08);
    }

    .spa-nav button.is-on {
      background: #f8fafc;
      border-color: #f8fafc;
      color: var(--ink);
    }

    .masthead :focus-visible {
      outline: 2px solid #f8fafc;
      outline-offset: 2px;
    }

    .spa-tab {
      display: none;
      flex: 1 1 auto;
      min-height: 0;
    }

    .spa-tab.is-on {
      display: flex;
    }

    .spa-topo-page.is-on {
      flex-direction: column;
      min-height: 0;
      padding: 0;
      background: var(--bg);
    }

    .topo-toolbar {
      flex: 0 0 auto;
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      justify-content: space-between;
      gap: 0.75rem 1rem;
      padding: 0.65rem 0.9rem;
      border-bottom: 1px solid var(--line);
      background: var(--panel);
    }

    .topo-toolbar-copy {
      min-width: 0;
    }

    .topo-toolbar-title {
      margin: 0;
      font-size: 0.95rem;
      font-weight: 700;
      color: var(--ink);
    }

    .topo-toolbar-hint {
      margin: 0.15rem 0 0;
      font-size: 0.78rem;
      color: var(--muted);
    }

    .topo-export-button {
      flex-shrink: 0;
      font: inherit;
      font-size: 0.88rem;
      font-weight: 600;
      padding: 0.45rem 0.95rem;
      border: none;
      border-radius: 999px;
      background: var(--accent);
      color: #fff;
      cursor: pointer;
      box-shadow: 0 4px 12px rgba(29, 78, 216, 0.28);
    }

    .topo-export-button:hover,
    .topo-export-button:focus-visible {
      background: #1e40af;
    }

    .topo-export-button:active {
      background: #1e3a8a;
    }

    .topo-export-button:disabled {
      opacity: 0.65;
      cursor: wait;
    }

    /*
     * Spec tables: keep cells on one line and scroll wide schedules
     * horizontally instead of squeezing them into the reading column.
     */
    .spa-spec .spa-article .table-scroll,
    .spa-spec .spa-article .design-devices-wrap,
    .spa-spec .spa-article .power-table-wrap,
    .spa-spec .spa-article .power-tree-wrap,
    .spa-spec .spa-article .appliances-wrap {
      max-width: 100%;
      overflow-x: auto;
      overflow-y: visible;
      -webkit-overflow-scrolling: touch;
      margin: 0.75rem 0 1.4rem;
    }

    .spa-spec .spa-article .power-table-wrap,
    .spa-spec .spa-article .power-tree-wrap {
      margin: 0.65rem 0 1rem;
    }

    /*
     * Same scroll rule as other Spec table wraps (overflow-x: auto above):
     * no bar when the pane is wide enough; bar appears when it is not.
     * Leaf cells stay nowrap; min-width keeps the fixed columns from crushing.
     */
    .spa-spec .spa-article table.power-tree {
      width: 100%;
      min-width: 50rem;
      max-width: none;
      table-layout: fixed;
    }

    .spa-spec .spa-article table.power-tree tr.power-tree-handle > td {
      white-space: normal;
    }

    .spa-spec .spa-article table.power-tree tr.power-tree-leaf > td {
      white-space: nowrap;
    }

    .appliances-table {
      font-size: 0.92rem;
    }

    .spa-spec .spa-article .appliances-wrap .appliances-table th,
    .spa-spec .spa-article .appliances-wrap .appliances-table td {
      vertical-align: top;
    }

    .spa-spec .spa-article .appliances-wrap .appliances-table td.device-cell {
      vertical-align: middle;
    }

    .spa-spec .spa-article .appliances-wrap .appliances-table th.brand-cell,
    .spa-spec .spa-article .appliances-wrap .appliances-table td.brand-cell {
      vertical-align: middle;
      text-align: center;
    }

    .spa-spec .spa-article .appliances-wrap .appliances-table .brand-logo-link {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 100%;
      line-height: 0;
    }

    .spa-spec .spa-article .appliances-wrap .appliances-table .brand-logo {
      height: 28px;
      width: auto;
      max-width: 7.5rem;
      object-fit: contain;
      display: block;
      margin-inline: auto;
    }

    .appliances-table .udc-device:not(:has(img)) {
      align-items: flex-start;
    }

    .appliances-table .num {
      font-variant-numeric: tabular-nums;
      text-align: right;
    }


    .spa-doc.is-on {
      display: block;
      overflow: auto;
      /* clip keeps the pane from shifting sideways; nested wraps can still pan-x. */
      overflow-x: clip;
    }

    .design-shell {
      display: grid;
      grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
      column-gap: 40px;
      align-items: start;
      box-sizing: border-box;
      width: 100%;
      max-width: var(--maxw);
      margin: 0 auto;
      min-height: 100%;
      padding: 0 24px;
    }

    .design-toc {
      position: sticky;
      top: 0;
      justify-self: stretch;
      align-self: start;
      box-sizing: border-box;
      width: 100%;
      max-width: none;
      max-height: calc(100vh - var(--header-h));
      max-height: calc(100dvh - var(--header-h));
      overflow: auto;
      overflow-x: hidden;
      overscroll-behavior: contain;
      padding: 28px 8px 28px 0;
      font-family: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
    }

    .design-toc-title {
      margin: 0 0 10px;
      color: var(--muted);
      font-size: 12px;
      font-weight: 700;
      letter-spacing: 0.8px;
      text-transform: uppercase;
      padding-left: 12px;
    }

    .design-toc-list {
      list-style: none;
      margin: 0;
      padding: 0;
    }

    .design-toc-list a {
      display: block;
      padding: 7px 12px;
      border-left: 2px solid transparent;
      border-radius: 0 6px 6px 0;
      color: var(--ink-soft);
      text-decoration: none;
      font-size: 14px;
      line-height: 1.35;
      overflow-wrap: anywhere;
      white-space: normal;
    }

    .design-toc-list a:hover {
      background: var(--accent-soft);
      color: var(--accent);
    }

    .design-toc-list a.is-active {
      border-left-color: var(--accent);
      background: var(--accent-soft);
      color: var(--accent);
      font-weight: 600;
    }

    .design-toc-list .toc-h2 {
      margin-top: 0.35rem;
      font-size: 14px;
    }

    .design-toc-list .toc-h2:first-child {
      margin-top: 0;
    }

    .design-toc-list .toc-h3 {
      padding-left: 0;
      font-size: 13px;
    }

    .design-toc-list .toc-h3 a {
      padding-left: 28px;
      font-size: 13px;
    }



    .spa-spec .spa-article {
      box-sizing: border-box;
      min-width: 0;
      max-width: none;
      /*
       * Bottom room so the last Contents target can reach the reading line
       * under the masthead; without it the page ends first and that item
       * never becomes active.
       */
      padding: 28px 0 calc(100vh - var(--header-h) - 2rem);
      padding: 28px 0 calc(100dvh - var(--header-h) - 2rem);
      color: var(--ink);
      font-family: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
      font-size: 0.95rem;
      line-height: 1.7;
      /* clip (not hidden): still trims paint, but nested x-scrollports can pan. */
      overflow-x: clip;
    }

    .spa-spec .spa-article h2 {
      margin-top: 2.7rem;
      font-size: clamp(1.2rem, 1.05rem + 0.5vw, 1.3125rem);
      letter-spacing: -0.01em;
      border-bottom-color: var(--line);
      color: var(--ink);
    }

    .spa-spec .spa-article h2:first-child {
      margin-top: 0;
    }

    .spa-spec .spa-article .lede {
      color: var(--ink);
    }

    .spa-spec .spa-article a {
      color: inherit;
      text-decoration: underline;
      text-decoration-style: dotted;
      text-decoration-color: color-mix(in srgb, var(--ink) 28%, transparent);
      text-underline-offset: 0.16em;
    }

    .spa-spec .spa-article a:hover,
    .spa-spec .spa-article a:focus-visible {
      color: var(--accent);
      text-decoration: underline;
      text-decoration-style: solid;
      text-decoration-color: var(--accent);
    }

    .spa-spec .spa-article h2 a.heading-ref,
    .spa-spec .spa-article h3 a.heading-ref,
    .spa-spec .spa-article h4 a.heading-ref {
      color: inherit;
      text-decoration: none;
    }

    .spa-spec .spa-article h2 a.heading-ref:hover,
    .spa-spec .spa-article h3 a.heading-ref:hover,
    .spa-spec .spa-article h4 a.heading-ref:hover {
      color: var(--accent);
      text-decoration: underline;
      text-decoration-style: solid;
      text-decoration-color: var(--accent);
    }

    .spa-spec .spa-article table {
      width: max-content;
      min-width: 100%;
      max-width: none;
    }

    .spa-spec .spa-article th,
    .spa-spec .spa-article td {
      white-space: nowrap;
    }

    /* PoE sub-labels stay multi-line under the watt figure. */
    .spa-spec .spa-article .poe-sub {
      white-space: normal;
    }

    .spa-spec .spa-article table.door-access-compare {
      width: 100%;
      min-width: 0;
      max-width: 100%;
      table-layout: auto;
    }

    .spa-spec .spa-article table.door-access-compare th,
    .spa-spec .spa-article table.door-access-compare td {
      white-space: nowrap;
      vertical-align: middle;
    }

    .spa-spec .spa-article table.door-access-compare td[rowspan] {
      vertical-align: middle;
    }

    .spa-spec .spa-article table.door-access-compare .cell-stack {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 0.12rem;
    }

    .spa-spec .spa-article table.door-access-compare .cell-door {
      color: var(--ink);
      font-weight: 650;
      font-size: 1em;
      line-height: 1.3;
      white-space: nowrap;
    }

    .spa-spec .spa-article table.door-access-compare .cell-meta {
      font-size: 0.82em;
      line-height: 1.3;
      color: #555;
      white-space: nowrap;
    }

    .spa-spec .spa-article table.rack-face {
      width: max-content;
      min-width: 22rem;
      max-width: none;
      table-layout: auto;
    }

    .spa-spec .spa-article table.rack-face th,
    .spa-spec .spa-article table.rack-face td {
      padding: 0.35rem 0.5rem;
      white-space: nowrap;
      vertical-align: middle;
    }

    .spa-spec .spa-article table.rack-face td:has(.rack-ports) {
      vertical-align: top;
    }

    .spa-spec .spa-article table.rack-face .rack-u {
      width: 3rem;
      text-align: center;
      font-variant-numeric: tabular-nums;
      color: var(--ink-soft);
    }

    .spa-spec .spa-article table.rack-face tbody .rack-u {
      font-weight: 500;
    }

    .spa-spec .spa-article table.rack-face tbody tr {
      height: 3.6rem;
    }

    .spa-spec .spa-article table.rack-face .rack-slot {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      justify-content: center;
      gap: 0.12rem;
    }

    .spa-spec .spa-article table.rack-face .rack-slot:has(.rack-ports) {
      justify-content: flex-start;
    }

    .spa-spec .spa-article table.rack-face .rack-name {
      color: var(--ink);
      font-weight: 650;
      line-height: 1.3;
    }

    .spa-spec .spa-article table.rack-face .rack-note {
      font-size: 0.82em;
      line-height: 1.3;
      color: #777;
    }

    .spa-spec .spa-article table.rack-face tr.rack-gap td {
      background: #f8fafc;
    }

    .spa-spec .spa-article table.rack-face .rack-ports {
      --rack-port: 26px;
      --rack-gap: 2px;
      display: flex;
      width: max-content;
      margin-top: 0.35rem;
      gap: var(--rack-gap);
    }

    /* Patch panels share the XG's 24 RJ45 columns. Those start at the left; two SFP28 sit at the right. */
    .spa-spec .spa-article table.rack-face .rack-ports.align-xg {
      margin-left: 0;
    }

    /* Same 26 columns as the XG face: P1–P24, then the two right-hand SFP28. */
    .spa-spec .spa-article table.rack-face .rack-ports.place {
      display: grid;
      grid-template-columns: repeat(26, var(--rack-port));
      align-items: center;
    }

    .spa-spec .spa-article table.rack-face .udc-port.keystone {
      --port-c: #cbd5e1;
      background: #fff;
      border: 1px solid #cbd5e1;
    }

    h1 {
      margin-bottom: 0.5rem;
    }

    h2 {
      margin-top: 2.5rem;
      margin-bottom: 0.75rem;
      padding-bottom: 0.35rem;
      border-bottom: 1px solid var(--line);
    }

    h3 {
      margin-top: 1.75rem;
      margin-bottom: 0.5rem;
    }

    h4 {
      margin-top: 1.25rem;
      margin-bottom: 0.4rem;
    }

    p,
    ul,
    ol {
      margin: 0.5rem 0 0.75rem;
    }

    ul,
    ol {
      padding-left: 1.4rem;
    }

    li {
      margin: 0.25rem 0;
    }

    table {
      border-collapse: collapse;
      width: max-content;
      max-width: none;
    }

    th,
    td {
      border: 1px solid var(--line);
      padding: 0.5rem 0.75rem;
      text-align: left;
      vertical-align: top;
      white-space: nowrap;
    }

    th {
      background: #f1f5f9;
    }

    a {
      color: var(--accent);
    }

    code {
      font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
      font-size: 0.92em;
      background: #f1f5f9;
      padding: 0.1em 0.35em;
      border-radius: 3px;
    }

    .lede {
      color: var(--ink);
      margin-bottom: 1.25rem;
    }

    .note {
      border: 1px solid var(--line);
      border-left: 4px solid var(--accent);
      border-radius: 10px;
      padding: 0.75rem 1rem;
      margin: 1rem 0;
      background: #eff6ff;
    }

    .checklist li {
      margin: 0.4rem 0;
    }

    /* Port icons */
    .udc-device {
      display: inline-flex;
      align-items: center;
      gap: 0.45rem;
    }

    .udc-device img {
      width: 28px;
      height: 28px;
      object-fit: contain;
      flex-shrink: 0;
    }

    .udc-device-meta {
      display: inline-flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 0.1rem;
      min-width: 0;
    }

    .udc-device-title {
      display: inline-flex;
      flex-wrap: wrap;
      align-items: baseline;
      gap: 0.35rem;
      line-height: 1.25;
    }

    .udc-sku {
      font-size: 0.72rem;
      line-height: 1.2;
      color: #777;
      font-variant-numeric: tabular-nums;
    }

    .udc-ports {
      display: inline-flex;
      flex-wrap: nowrap;
      align-items: center;
      gap: 0.45rem 0.5rem;
    }

    /*
     * Count sits under the chip but stays out of flow so the port square
     * keeps the same height as bare chips and stays vertically centered.
     */
    .udc-port-wrap {
      position: relative;
      display: inline-flex;
      flex-direction: row;
      align-items: center;
      justify-content: center;
    }

    .udc-count {
      font-size: 0.65rem;
      line-height: 1;
      color: #555;
      font-variant-numeric: tabular-nums;
      text-align: center;
    }

    .udc-port-wrap > .udc-count {
      position: absolute;
      top: calc(100% + 0.1rem);
      left: 50%;
      transform: translateX(-50%);
      white-space: nowrap;
    }

    .udc-port {
      position: relative;
      display: inline-flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      box-sizing: border-box;
      width: 26px;
      min-width: 26px;
      max-width: 26px;
      height: 26px;
      padding: 0;
      border-radius: 4px;
      --port-c: #666;
      color: #141414;
      font-size: 7px;
      font-weight: 700;
      letter-spacing: -0.04em;
      line-height: 1;
      background-clip: padding-box;
      -webkit-print-color-adjust: exact;
      print-color-adjust: exact;
      vertical-align: middle;
      gap: 0;
      overflow: hidden;
    }

    .udc-port.gbe1 { --port-c: #38cc65; background: #38cc65; }
    .udc-port.gbe2p5 { --port-c: #99c5ff; background: #99c5ff; }
    .udc-port.gbe10 { --port-c: #3a9fcb; background: #3a9fcb; }
    .udc-port.fe { --port-c: #f0b429; background: #f0b429; } /* 100M */
    .udc-port.other {
      --port-c: #c4785a;
      background: #c4785a; /* 非以太网：光纤 / USB / CAN / REX / DPS / LOCK */
      color: #fff;
    }

    /* Kit rows: equal flex bands + full-bleed dashed lines across Device/Port/PoE */
    td:has(> .udc-device-stack),
    td:has(> .kit-stack) {
      padding: 0;
      height: 1px;
      vertical-align: top;
    }

    .udc-device-stack,
    .kit-stack {
      display: flex;
      flex-direction: column;
      align-items: stretch;
      gap: 0;
      width: 100%;
      height: 100%;
      min-height: 100%;
      box-sizing: border-box;
    }

    .udc-device-stack > .udc-device,
    .udc-device-stack > a:first-child {
      display: flex;
      align-items: center;
      gap: 0.45rem;
      flex: 1 1 0;
      min-height: 2.75rem;
      padding: 0.5rem 0.75rem;
      box-sizing: border-box;
    }

    .udc-accessory {
      display: flex;
      align-items: center;
      gap: 0.45rem;
      flex: 1 1 0;
      min-height: 2.75rem;
      margin: 0;
      padding: 0.5rem 0.75rem 0.5rem 2.1rem;
      border-top: none;
      background-image: repeating-linear-gradient(
        to right,
        #ccc 0,
        #ccc 0.45rem,
        transparent 0.45rem,
        transparent 0.7rem
      );
      background-size: 100% 1px;
      background-repeat: repeat-x;
      background-position: left top;
      font-size: inherit;
      color: inherit;
      box-sizing: border-box;
    }

    .udc-accessory img {
      width: 28px;
      height: 28px;
      object-fit: contain;
      flex-shrink: 0;
    }

    .kit-seg {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: flex-start;
      flex: 1 1 0;
      min-height: 2.75rem;
      padding: 0.5rem 0.75rem;
      box-sizing: border-box;
      width: 100%;
    }

    .kit-seg.acc {
      margin: 0;
      border-top: none;
      background-image: repeating-linear-gradient(
        to right,
        #ccc 0,
        #ccc 0.45rem,
        transparent 0.45rem,
        transparent 0.7rem
      );
      background-size: 100% 1px;
      background-repeat: repeat-x;
      background-position: left top;
    }

    .poe-cell {
      vertical-align: top;
      min-width: 5.5rem;
    }

    td.port-cell {
      min-width: 4.5rem;
      vertical-align: middle !important;
    }

    /* Remove the inline-flex baseline gap so standalone port groups center exactly. */
    td.port-cell > .udc-ports {
      display: flex;
      width: max-content;
    }

    .design-devices-wrap .devices-table > tbody > tr > td.protocol-cell {
      vertical-align: middle;
      white-space: nowrap;
      color: var(--ink-soft);
    }

    .design-devices-wrap .devices-table > tbody > tr > td.price-cell {
      vertical-align: middle;
      text-align: right;
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
      color: var(--ink-soft);
    }

    .devices-table td.device-cell {
      vertical-align: middle;
    }

    .devices-table td.device-cell.is-pending {
      background: #eef2f6;
    }

    .devices-table td.device-cell.is-purchased {
      background: #e6f4ea;
    }

    .device-legend {
      display: inline-block;
      padding: 0.05rem 0.4rem;
      border-radius: 4px;
      font-size: 0.92em;
    }

    .device-legend.is-pending {
      background: #eef2f6;
    }

    .device-legend.is-purchased {
      background: #e6f4ea;
    }

    .order-fees-table td:first-child,
    .order-fees-table th:first-child {
      white-space: nowrap;
    }

    .order-fees-table tfoot .order-fees-sum th,
    .order-fees-table tfoot .order-fees-sum td {
      font-weight: 700;
      border-top: 1px solid var(--line);
      padding-top: 0.65rem;
      vertical-align: top;
    }

    .order-fees-ccy {
      display: block;
      font-variant-numeric: tabular-nums;
      line-height: 1.35;
    }

    .stock-out {
      color: #c0392b;
      font-weight: 600;
    }

    .poe-val {
      display: block;
      line-height: 1.25;
      font-variant-numeric: tabular-nums;
    }

    .poe-sub {
      display: block;
      margin-top: 0.12rem;
      font-size: 0.7rem;
      color: #666;
      white-space: normal;
      max-width: 9rem;
      line-height: 1.25;
    }

    .poe-lbl {
      font-size: 0.65em;
      font-weight: 600;
      letter-spacing: 0.02em;
      color: #888;
    }

    th.port-group {
      text-align: center;
    }

    th.port-sub {
      font-weight: 600;
      font-size: 0.85rem;
      background: #f0f0f0;
    }

    .spa-spec .spa-article table.device-list {
      width: 100%;
      min-width: 48rem;
      table-layout: fixed;
    }

    .spa-spec .spa-article table.device-list col.col-category {
      width: 10.25rem;
    }

    .spa-spec .spa-article table.device-list col.col-price {
      width: 12rem;
    }

    table.device-list thead th:first-child,
    table.device-list tbody td:first-child:not([class]) {
      vertical-align: middle;
    }

    /* §1.3: port chips sit in their own row, so a hanging ×n needs room inside the cell. */
    table.device-list td.port-cell:has(.udc-count) {
      padding-bottom: 1.05rem;
    }

    table.device-list .udc-sku {
      display: block;
      line-height: 1.35;
    }

    /* Stacked annotations make the name block taller than the icon. Keep the icon with the title. */
    table.device-list td[colspan="2"] > .udc-device {
      align-items: flex-start;
    }

    table.device-list td[colspan="2"] > .udc-device > img {
      margin-top: 0.12rem;
    }

    .udc-port.sfp {
      --port-c: #2b2b2b;
      flex-shrink: 0;
      background: #2b2b2b;
      color: #fafafa;
      white-space: nowrap;
    }

    .udc-port.sfp .udc-poe {
      width: 14px;
      height: 14px;
    }

    .udc-sfp-txt {
      display: block;
      font-size: 7px;
      line-height: 1;
      font-weight: 700;
      color: inherit;
    }

    .udc-poe {
      width: 14px;
      height: 14px;
    }

    .udc-port.sfp .udc-poe,
    .udc-port.other .udc-poe {
      color: #fafafa;
    }

    /* Idle and loose ports keep an opaque fill and the same border weight as a device frame. */
    .udc-port.idle,
    .udc-port.loose {
      background: #fff;
      background-color: #fff;
      box-shadow: none;
      /* One weight for every rule in the drawing: same as a device frame. */
      border: 1px solid var(--port-c);
      color: var(--port-c);
    }

    .udc-port.gbe1.idle { border-color: #38cc65; color: #38cc65; }
    .udc-port.gbe2p5.idle { border-color: #99c5ff; color: #99c5ff; }
    .udc-port.gbe10.idle { border-color: #3a9fcb; color: #3a9fcb; }
    .udc-port.other.idle { border-color: #c4785a; color: #c4785a; }
    .udc-port.sfp.idle { border-color: #2b2b2b; color: #2b2b2b; }

    .udc-port.idle.dash,
    .udc-port.loose {
      border-style: dashed;
    }

    .udc-port.idle .udc-poe {
      color: #141414;
    }

    .udc-port.idle .udc-sfp-txt {
      color: var(--port-c);
    }

    .vlan-management { --vlan-color: #005ea8; --vlan-fill: #edf3f7; }
    .vlan-servers { --vlan-color: #6a3d9a; --vlan-fill: #f2eff5; }
    .vlan-iot { --vlan-color: #a15c00; --vlan-fill: #f7f2ea; }
    .vlan-security { --vlan-color: #b3263e; --vlan-fill: #f7eff0; }

    .topo-wrap {
      display: flex;
      flex-direction: column;
      gap: 0.45rem;
      margin: 0;
      padding: 0.55rem 0.7rem 0.7rem;
      flex: 1 1 auto;
      min-height: 0;
      height: 100%;
    }

    .topo-canvas {
      position: relative;
      width: 100%;
      min-height: 0;
      height: 100%;
      overflow: auto;
      background: var(--panel);
      outline: 1px solid var(--line);
      outline-offset: -1px;
    }

    .topo-stage {
      position: relative;
      margin-inline: auto;
    }

    .topo-edges {
      position: absolute;
      left: 0;
      top: 0;
      z-index: 4;
      pointer-events: none;
    }

    .topo-link {
      fill: none;
      stroke: #e65100;
      stroke-width: 1;
      stroke-linecap: round;
      stroke-linejoin: round;
      vector-effect: non-scaling-stroke;
      shape-rendering: geometricPrecision;
      marker-end: url(#topo-arrow-cat6a);
      pointer-events: none;
    }

    .topo-link.cable-cat6a { stroke: #e65100; marker-end: url(#topo-arrow-cat6a); }
    .topo-link.cable-cat6 { stroke: #1565c0; marker-end: url(#topo-arrow-cat6); }
    .topo-link.cable-dac { stroke: #111111; marker-end: url(#topo-arrow-dac); }
    .topo-link.cable-can { stroke: #00897b; marker-end: url(#topo-arrow-can); }
    .topo-link.cable-lock12 { stroke: #8e24aa; marker-end: url(#topo-arrow-lock12); }


    .topo-link-label {
      fill: #30363d;
      stroke: #fff;
      stroke-width: 3px;
      paint-order: stroke fill;
      font-size: 0.58rem;
      font-weight: 700;
      text-anchor: middle;
      dominant-baseline: central;
      pointer-events: none;
    }

    .topo-link-label-link,
    .topo-link-label-link .topo-link-label {
      color: #30363d;
      cursor: pointer;
      pointer-events: all;
    }

    .topo-link-label-link:hover .topo-link-label,
    .topo-link-label-link:focus .topo-link-label {
      fill: #30363d;
      text-decoration: underline;
      text-decoration-color: #30363d;
    }

    .topo-node {
      position: absolute;
      z-index: 1;
      box-sizing: border-box;
      display: grid;
      grid-template-columns: max-content auto max-content;
      justify-items: center;
      align-items: center;
      width: max-content;
      padding: 0.42rem;
      gap: 0.28rem 0.32rem;
      /*
       * Frames are outlines, never borders. Blink floors a border's used width
       * to whole device pixels (1px becomes 0.667px on a 150% display) but
       * prints it at the full 1px, so a bordered box has one height on screen
       * and another on paper. Stacked boxes accumulated that difference into a
       * 7px drift between the ports and the SVG cables. An outline draws in the
       * same place and contributes nothing to layout.
       */
      border: 0;
      outline: 1px solid #bbb;
      outline-offset: -1px;
      border-radius: 0.32rem;
      background: #fff;
      color: #1a1a1a;
      font: inherit;
      font-size: 0.7rem;
      line-height: 1.2;
      text-align: center;
      cursor: default;
    }

    .topo-node,
    .topo-bundle-device {
      transition: box-shadow 120ms ease;
    }

    /* XG: compact header above an equal-height dual-sided fanout section. */
    .topo-node.topo-xg {
      z-index: auto;
      grid-template-columns: max-content minmax(0, 1fr) max-content;
      grid-template-rows: max-content max-content minmax(0, 1fr);
      align-items: stretch;
      align-content: stretch;
      column-gap: 0;
      row-gap: 0.28rem;
    }

    .topo-node.topo-xg > .topo-mid {
      position: relative;
      grid-column: 1 / -1;
      grid-row: 2;
      align-self: start;
      justify-self: stretch;
      min-width: 11.5rem;
      padding-inline: 0;
      padding-bottom: calc(0.3rem + 1px);
    }

    .topo-node.topo-xg > .topo-mid::after {
      content: "";
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      border-top: 1px solid #c7d0d8;
    }

    .topo-node.topo-xg > .topo-ports {
      position: relative;
      z-index: 3;
    }

    .topo-node.topo-xg > .topo-ports.up {
      grid-column: 1 / -1;
      grid-row: 1;
      position: relative;
      flex-direction: row;
      align-self: center;
      width: 100%;
      min-width: 100%;
      min-height: 26px;
    }

    .topo-node.topo-xg > .topo-ports.left {
      grid-column: 1;
      grid-row: 3;
    }

    .topo-node.topo-xg > .topo-ports.right {
      grid-column: 3;
      grid-row: 3;
    }

    .topo-node.topo-xg > .topo-ports.left,
    .topo-node.topo-xg > .topo-ports.right {
      position: relative;
      align-self: stretch;
      height: 100%;
      justify-content: flex-start;
    }

    .topo-node.topo-xg > .topo-ports.left > .topo-slot,
    .topo-node.topo-xg > .topo-ports.right > .topo-slot {
      position: absolute;
      left: 0;
      right: 0;
      height: auto;
    }

    .topo-node.topo-backup {
      outline-style: dashed;
    }

    .topo-counted-port {
      display: inline-flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 0.03rem;
      line-height: 1;
    }

    .topo-port-count {
      color: #526170;
      font-size: 0.48rem;
      font-weight: 700;
      white-space: nowrap;
    }

    .topo-bundle {
      position: absolute;
      z-index: 2;
      box-sizing: border-box;
      display: grid;
      grid-template-columns: max-content max-content max-content;
      width: max-content;
      padding: 0.42rem;
      border: 0;
      outline: 0;
      border-radius: 0.42rem;
      background: transparent;
      color: #1a1a1a;
      font: inherit;
      font-size: 0.7rem;
      line-height: 1.2;
    }

    /*
     * The group frame and every rule inside a group are drawn on out-of-flow
     * pseudo elements so they carry real borders - same device-pixel weight as a
     * device frame, same vector output on paper - without adding anything to
     * layout, which the print alignment depends on.
     */
    .topo-bundle::before {
      content: "";
      position: absolute;
      inset: 0;
      border: 1px dashed #8b99a6;
      border-radius: inherit;
      pointer-events: none;
    }

    .topo-bundle-door-matrix::before {
      display: none;
    }

    /* Reserves GAP_X + port-wrap so inner devices keep the same XG gap as other nodes */
    .topo-bundle-port-gutter {
      width: calc(32px + 2.4rem);
      pointer-events: none;
    }

    .topo-bundle-diagram {
      display: flex;
      flex-direction: column;
      justify-content: center;
      gap: 0.42rem;
      padding-right: 0.42rem;
    }

    .topo-bundle-row {
      display: flex;
      align-items: center;
      gap: 0.35rem;
      width: max-content;
    }

    .topo-bundle-device {
      box-sizing: border-box;
      display: grid;
      grid-template-columns: max-content auto max-content;
      align-items: center;
      justify-items: center;
      width: max-content;
      padding: 0.35rem;
      gap: 0.22rem 0.28rem;
      border: 0;
      outline: 1px solid #bbb;
      outline-offset: -1px;
      border-radius: 0.32rem;
      background: #fff;
      text-align: center;
    }

    .topo-bundle-device.topo-backup {
      outline-style: dashed;
    }

    .topo-bundle-device .topo-mid {
      max-width: 13rem;
    }

    .topo-bundle-device .topo-name {
      white-space: nowrap;
    }

    .topo-bundle-device .topo-ports {
      min-width: 26px;
    }

    .topo-bundle-door-matrix {
      grid-template-columns: max-content max-content;
      padding: 0;
      border: 0;
      outline: 0;
      border-radius: 0;
    }

    .topo-bundle-door-matrix .topo-bundle-diagram {
      gap: 0.42rem;
      padding-right: 0;
    }

    .topo-door-matrix-row {
      box-sizing: border-box;
      display: block;
      align-items: stretch;
      width: max-content;
      padding: 0;
    }

    .topo-door-matrix-row + .topo-door-matrix-row {
      margin-top: 0.42rem;
    }

    .topo-door-matrix-branch {
      display: grid;
      grid-template-columns: max-content max-content;
      align-items: stretch;
      gap: 0.7rem;
      width: max-content;
    }

    .topo-door-matrix-root {
      align-self: stretch;
    }

    .topo-door-matrix-root > .topo-mid {
      min-width: 11rem;
    }

    .topo-door-matrix-root > .topo-ports.down {
      position: relative;
      align-self: stretch;
      justify-content: flex-start;
    }

    .topo-bundle-door-matrix .topo-bundle-device {
      padding: 0.42rem;
      gap: 0.28rem 0.32rem;
    }

    /* Logical mirror: reverse only layout columns, never text or glyphs. */
    .topo-bundle.flow-left:not(.topo-bundle-door-matrix) > .topo-bundle-port-gutter {
      grid-column: 3;
      grid-row: 1;
    }

    .topo-bundle.flow-left:not(.topo-bundle-door-matrix) > .topo-bundle-diagram {
      grid-column: 2;
      grid-row: 1;
      padding-right: 0;
      padding-left: 0.42rem;
    }

    .topo-bundle.flow-left:not(.topo-bundle-door-matrix) > .topo-bundle-locations {
      grid-column: 1;
      grid-row: 1;
      margin-left: 0;
      padding-left: 0;
      padding-right: 1px;
    }

    .topo-bundle.flow-left:not(.topo-bundle-door-matrix) > .topo-bundle-locations::before {
      left: auto;
      right: 0;
      border-left: 0;
      border-right: 1px dashed #8b99a6;
    }

    .topo-bundle-door-matrix.flow-left > .topo-bundle-port-gutter {
      grid-column: 2;
      grid-row: 1;
    }

    .topo-bundle-door-matrix.flow-left > .topo-bundle-diagram {
      grid-column: 1;
      grid-row: 1;
    }

    .topo-bundle.flow-left .topo-bundle-device > .topo-ports.up {
      grid-column: 3;
      grid-row: 1;
    }

    .topo-bundle.flow-left .topo-bundle-device > .topo-mid {
      grid-column: 2;
      grid-row: 1;
    }

    .topo-bundle.flow-left .topo-bundle-device > .topo-ports.down {
      grid-column: 1;
      grid-row: 1;
    }

    .topo-bundle-door-matrix.flow-left .topo-door-matrix-root {
      grid-column: 2;
      grid-row: 1;
    }

    .topo-bundle-door-matrix.flow-left .topo-door-matrix-endpoints {
      grid-column: 1;
      grid-row: 1;
    }

    .topo-door-matrix-endpoints {
      display: grid;
      grid-template-rows: repeat(4, minmax(1.35rem, auto));
      align-items: center;
      gap: 0.12rem;
      width: max-content;
    }

    .topo-door-matrix-endpoint {
      width: 100%;
    }

    .topo-door-matrix-reader { grid-row: 1; }
    .topo-door-matrix-camera { grid-row: 2; }
    .topo-door-matrix-strike { grid-row: 4; }

    .topo-door-matrix-camera .topo-mid {
      max-width: 14rem;
    }

    .topo-bundle-locations {
      position: relative;
      display: grid;
      align-self: stretch;
      margin-left: 0;
      padding-left: 1px;
    }

    .topo-bundle-locations::before {
      content: "";
      position: absolute;
      left: 0;
      top: 0;
      bottom: 0;
      border-left: 1px dashed #8b99a6;
    }

    .topo-bundle-location {
      position: relative;
      display: flex;
      align-items: center;
      padding: 0.34rem 0.5rem;
      color: #596775;
      font-size: 0.64rem;
      white-space: nowrap;
    }

    .topo-bundle-location:not(:first-child) {
      padding-top: calc(0.34rem + 1px);
    }

    .topo-bundle-location:not(:first-child)::before {
      content: "";
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      border-top: 1px dashed #8b99a6;
    }

    .topo-mid {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      padding: 0;
      gap: 0.12rem;
      min-width: 0;
      white-space: nowrap;
    }

    .topo-mid * {
      white-space: nowrap;
    }

    .topo-embeds {
      display: flex;
      flex-direction: row;
      align-items: center;
      justify-content: center;
      gap: 0.18rem;
      width: max-content;
    }

    .topo-node[data-id="ha"] > .topo-mid > .topo-embeds {
      flex-direction: column;
      align-items: stretch;
    }

    .topo-node[data-id="ha"] > .topo-ports.down {
      display: grid;
      grid-template-columns: repeat(3, 26px);
      gap: 0.1rem;
      width: max-content;
      justify-items: center;
      align-items: center;
    }

    .topo-node.topo-tb {
      grid-template-columns: 1fr;
      grid-template-rows: auto auto auto;
      justify-items: center;
      padding: 0.42rem;
    }

    .topo-node.topo-tb .topo-ports {
      flex-direction: row;
      justify-content: center;
      align-self: center;
      width: max-content;
      max-width: 100%;
      height: auto;
      min-height: 26px;
    }

    .topo-node.topo-tb .topo-ports.up {
      width: 100%;
      justify-content: center;
    }

    .topo-node.topo-tb .topo-slot {
      flex-direction: row;
      width: auto;
    }

    .topo-node.topo-tb .topo-ports.down:empty {
      display: none;
    }

    .topo-node.topo-core-vertical {
      grid-template-columns: 1fr;
      grid-template-rows: max-content auto max-content;
      align-items: center;
      justify-items: stretch;
      min-width: 0;
    }

    .topo-node.topo-core-vertical > .topo-ports {
      position: relative;
      width: 100%;
      min-height: 26px;
    }

    .topo-node.topo-core-vertical > .topo-mid {
      justify-self: center;
    }

    .topo-node.topo-core-vertical .topo-counted-port {
      flex-direction: row;
      gap: 0.16rem;
    }

    /* Tall enough that the surge chips sit on the box centre and the count stays inside the frame. */
    .topo-node[data-id="ups"] {
      min-height: 4.5rem;
    }

    .topo-node[data-id="ups"] > .topo-ports.down .topo-counted-port {
      position: relative;
    }

    .topo-node[data-id="ups"] > .topo-ports.down .topo-port-count {
      position: absolute;
      top: calc(100% + 0.03rem);
      left: 50%;
      transform: translateX(-50%);
    }

    .topo-node.flow-left > .topo-ports.up {
      grid-column: 3;
      grid-row: 1;
    }

    .topo-node.flow-left > .topo-mid {
      grid-column: 2;
      grid-row: 1;
    }

    .topo-node.flow-left > .topo-ports.down {
      grid-column: 1;
      grid-row: 1;
    }

    .topo-node.is-fanout {
      align-items: stretch;
      align-content: stretch;
      grid-template-rows: 1fr;
    }

    .topo-node.is-fanout .topo-ports.up {
      justify-content: center;
      align-self: center;
    }

    .topo-node.is-fanout[data-id="flex"] > .topo-ports.up {
      position: relative;
      justify-content: flex-start;
      align-self: stretch;
      width: 2.4rem;
      min-width: 2.4rem;
    }

    .topo-node.is-fanout .topo-ports.down {
      position: relative;
      align-self: stretch;
      height: 100%;
      justify-content: flex-start;
    }

    .topo-node.is-fanout .topo-ports.down .topo-slot {
      position: absolute;
      left: 0;
      right: 0;
      height: auto;
    }

    .topo-node.is-fanout .topo-mid {
      justify-content: center;
    }

    .topo-name {
      display: block;
      margin: 0 auto;
      white-space: nowrap;
      font-weight: 700;
      font-size: 0.74rem;
      color: #1a1a1a;
      line-height: 1.25;
      text-decoration: none;
      cursor: pointer;
    }

    /*
     * Same pairing as the VLANS legend swatch: desaturated fill, saturated
     * frame. Devices without a VLAN keep the neutral grey frame.
     */
    .topo-node[class*="vlan-"],
    .topo-bundle-device[class*="vlan-"] {
      background-color: var(--vlan-fill);
      outline-color: var(--vlan-color);
      -webkit-print-color-adjust: exact;
      print-color-adjust: exact;
    }

    .topo-node[class*="vlan-"] .topo-name,
    .topo-bundle-device[class*="vlan-"] .topo-name {
      color: #1a1a1a;
    }

    .topo-name:hover {
      text-decoration: underline;
    }

    .topo-node small {
      display: block;
      color: #666;
      font-size: 0.62rem;
      font-weight: 400;
      line-height: 1.25;
      white-space: nowrap;
    }

    .topo-ports {
      display: flex;
      flex-direction: column;
      flex-wrap: nowrap;
      justify-content: center;
      align-items: center;
      gap: 0.1rem;
      width: auto;
      min-width: 26px;
      min-height: 26px;
      overflow: visible;
    }

    .topo-ports.down:empty {
      min-width: 0;
      width: 0;
      min-height: 0;
      overflow: hidden;
    }

    .topo-slot {
      display: flex;
      flex-direction: column;
      justify-content: center;
      gap: 0.14rem;
      align-items: center;
      box-sizing: border-box;
      width: 100%;
    }

    /*
     * The frame colour now carries VLAN meaning, so hover reads as a halo ring
     * outside the frame instead of a colour change. box-shadow keeps it out of
     * layout, which the print alignment depends on.
     */
    .topo-node:hover,
    .topo-node:focus-visible,
    .topo-bundle-device:hover,
    .topo-bundle-device:focus-within {
      box-shadow: 0 0 0 3px rgba(26, 107, 181, 0.32);
    }

    .topo-legend-card {
      pointer-events: all;
      cursor: default;
    }

    .topo-legend-card > rect:first-child {
      transition: stroke 120ms ease, stroke-width 120ms ease, filter 120ms ease;
    }

    .topo-legend-card:hover > rect:first-child {
      filter: drop-shadow(0 0 3px rgba(26, 107, 181, 0.55));
    }

    .topo-embed {
      display: block;
      margin-top: 0.06rem;
      padding: 0.08rem 0.28rem;
      border: 0;
      outline: 1px dashed #bbb;
      outline-offset: -1px;
      border-radius: 0.22rem;
      background: #f7f7f7;
      line-height: 1.2;
    }

    .topo-embed-name {
      font-size: 0.58rem;
      font-weight: 600;
      color: #444;
      text-decoration: none;
      white-space: nowrap;
    }

    .topo-embed-name:hover,
    .topo-embed-name:focus-visible {
      text-decoration: underline;
    }

    .topo-poe {
      width: 100%;
      min-width: 7.4rem;
      margin-top: 0.18rem;
      text-align: left;
    }

    .topo-poe-head {
      display: flex;
      justify-content: space-between;
      align-items: baseline;
      gap: 0.45rem;
      font-size: 0.58rem;
      color: #666;
      line-height: 1.2;
      margin-bottom: 0.12rem;
    }

    .topo-poe-num {
      font-variant-numeric: tabular-nums;
      font-weight: 600;
      color: #333;
      white-space: nowrap;
    }

    .topo-poe-track {
      box-sizing: border-box;
      height: 4px;
      min-height: 4px;
      max-height: 4px;
      flex: 0 0 4px;
      border-radius: 999px;
      background: #e6e6e6;
      overflow: hidden;
    }

    .topo-poe-fill {
      box-sizing: border-box;
      display: block;
      height: 100%;
      border-radius: inherit;
      background: #18b86a;
    }

    .topo-poe.is-over .topo-poe-fill {
      background: #e24b4a;
    }

    .topo-poe.is-over .topo-poe-num {
      color: #c0392b;
    }

    .topo-device-power {
      position: relative;
      display: flex;
      justify-content: space-between;
      align-items: baseline;
      gap: 0.45rem;
      width: 100%;
      min-width: 7.4rem;
      margin-top: 0.16rem;
      padding-top: calc(0.14rem + 1px);
      color: #666;
      font-size: 0.58rem;
      line-height: 1.2;
      text-align: left;
      white-space: nowrap;
    }

    .topo-device-power::before {
      content: "";
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      border-top: 1px solid #e2e2e2;
    }

    .topo-device-power strong {
      color: #333;
      font-weight: 600;
      white-space: nowrap;
    }

    .power-card {
      min-width: 0;
      padding: 0.85rem 0.9rem;
      border: 1px solid #cfcfcf;
      border-radius: 0.45rem;
      background: #f3f3f3;
    }

    .power-card-wide {
      width: 100%;
      box-sizing: border-box;
    }

    .power-card-title {
      margin: 0;
      color: #555;
      font-size: 0.82rem;
      font-weight: 650;
    }

    .power-card-value {
      margin: 0.14rem 0 0.55rem;
      font-size: 1.45rem;
      font-weight: 700;
      line-height: 1.2;
      font-variant-numeric: tabular-nums;
    }

    .power-card-value small {
      color: #666;
      font-size: 0.72rem;
      font-weight: 500;
    }

    .power-meter {
      height: 0.38rem;
      overflow: hidden;
      border-radius: 999px;
      background: rgba(0, 0, 0, 0.08);
    }

    .power-meter > span {
      display: block;
      height: 100%;
      border-radius: inherit;
      background: #18b86a;
    }

    .power-callout {
      margin: 0.65rem 0 0;
      padding: 0.55rem 0.7rem;
      border-left: 3px solid #d98b16;
      background: #fff8e8;
      color: #4a3a20;
      font-size: 0.82rem;
      line-height: 1.45;
    }

    .power-callout p {
      margin: 0.55rem 0 0;
    }

    .power-callout p:last-child {
      margin-bottom: 0;
    }

    .power-formula {
      margin: 0.5rem 0 0;
      color: #555;
      font-size: 0.82rem;
    }

    .power-card > .power-formula:first-of-type {
      margin-top: 0.55rem;
    }

    table.power-tree {
      border-collapse: collapse;
    }

    table.power-tree .power-tree-col-load {
      width: 22%;
    }

    table.power-tree .power-tree-col-power {
      width: 6%;
    }

    table.power-tree .power-tree-col-pd {
      width: 22%;
    }

    table.power-tree .power-tree-col-pse {
      width: 28%;
    }

    table.power-tree .power-tree-col-notes {
      width: 22%;
    }

    table.power-tree td {
      padding: 0.38rem 0.3rem;
      vertical-align: middle;
      border-top: 1px solid #e5e5e5;
      font-size: 0.76rem;
      line-height: 1.3;
    }

    table.power-tree td.num {
      text-align: right;
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
    }

    table.power-tree .power-formula,
    table.power-tree .power-formula code {
      white-space: normal;
      overflow-wrap: anywhere;
    }

    table.power-tree .power-callout {
      white-space: normal;
    }

    /* Hierarchy via card fills — span row itself stays clear. */
    table.power-tree tr.power-tree-handle {
      cursor: pointer;
    }

    table.power-tree tr.power-tree-handle > td {
      padding: 0.55rem 0.65rem;
      border-top: 1px solid #e5e5e5;
      background: transparent;
    }

    table.power-tree tr.power-tree-handle:hover > td {
      background: transparent;
    }

    table.power-tree tr.power-tree-handle:focus-visible .power-card {
      outline: 2px solid #2f6fed;
      outline-offset: 2px;
    }

    .power-tree-handle-body {
      min-width: 0;
    }

    /*
     * Same cool steel family, stepped hue/value so nesting reads at a glance.
     * Level 0 denser slate-blue; level 1 softer sky; level 2 pale ice.
     */
    table.power-tree tr.power-tree-handle[data-level="0"] .power-card {
      background: #b9c8db;
      border-color: #8fa3bc;
    }

    table.power-tree tr.power-tree-handle[data-level="1"] .power-card {
      background: #d2e2f0;
      border-color: #a7bdd2;
    }

    table.power-tree tr.power-tree-handle[data-level="2"] .power-card {
      background: #e8f1f8;
      border-color: #c3d4e4;
    }

    table.power-tree tr.power-tree-handle[data-level="0"]:hover .power-card {
      background: #aebfd5;
    }

    table.power-tree tr.power-tree-handle[data-level="1"]:hover .power-card {
      background: #c6d9eb;
    }

    table.power-tree tr.power-tree-handle[data-level="2"]:hover .power-card {
      background: #dce8f3;
    }

    table.power-tree tr.power-tree-leaf {
      background: #fff;
    }

    table.power-tree tr.power-tree-leaf:nth-child(even) {
      background: #fafafa;
    }

    #export-root {
      position: absolute;
      left: -280in;
      top: 0;
      width: 24in;
      pointer-events: none;
    }

    /*
     * buildSheet() sizes this box in inches and the browser prints it directly.
     * Metadata sits in the topology's empty upper-left area, so the full sheet
     * height is available to the 1:1 stage.
     */
    .export-sheet {
      position: relative;
      box-sizing: border-box;
      display: block;
      background: #fff;
      color: #172635;
      border: 2px solid #17324d;
      /* Whole pixels: keeps the drawing origin on the page's pixel grid. The
         2px margin centres the 2240x1664 sheet in the 2244x1668 page box. */
      margin: 2px;
      padding: 8px;
    }

    .blueprint-viewport {
      position: relative;
      box-sizing: border-box;
      width: 100%;
      height: 100%;
      min-width: 0;
      min-height: 0;
      padding: 0;
      overflow: hidden;
      background: #fff;
    }

    .blueprint-placement {
      position: absolute;
      left: 0;
      top: 0;
      width: max-content;
      font-size: 0.7rem;
      line-height: 1.2;
    }

    .blueprint-meta {
      position: absolute;
      left: 16px;
      top: 16px;
      z-index: 5;
      box-sizing: border-box;
      width: 475px;
      color: #172635;
      pointer-events: none;
    }

    .blueprint-meta h2 {
      margin: 0;
      padding: 0;
      border: 0;
      font-size: 20pt;
      line-height: 1.1;
      letter-spacing: 0.025em;
    }

    .blueprint-meta-subtitle {
      margin: 0.04in 0 0.1in;
      color: #40566c;
      font-size: 9.5pt;
      line-height: 1.2;
    }

    .blueprint-meta-details {
      display: grid;
      grid-template-columns: max-content max-content;
      gap: 0.06in 0.22in;
      font-size: 8.5pt;
      line-height: 1.25;
    }

    .blueprint-meta-details strong {
      display: block;
      color: #607386;
      font-size: 7pt;
      font-weight: 650;
      letter-spacing: 0.05em;
      text-transform: uppercase;
    }

    body.export-source-measure #tab-topology {
      position: fixed !important;
      left: 0 !important;
      top: 0 !important;
      display: flex !important;
      flex-direction: column !important;
      visibility: hidden !important;
      width: 132rem !important;
      height: 78rem !important;
      pointer-events: none !important;
    }

    /*
     * Export reminder: the browser's own print dialog writes the PDF, so its
     * defaults (headers, scale) decide whether the sheet is usable.
     */
    .print-hint {
      position: fixed;
      right: max(1rem, env(safe-area-inset-right));
      top: calc(var(--header-h) + 0.75rem);
      z-index: 40;
      width: min(19rem, calc(100vw - 2rem));
      padding: 0.9rem 1rem 0.85rem;
      border: 1px solid var(--line-strong);
      border-radius: 10px;
      background: var(--panel);
      box-shadow: 0 10px 30px rgba(15, 23, 42, 0.18);
      color: var(--ink);
      font-size: 0.78rem;
      line-height: 1.45;
    }

    .print-hint[hidden] {
      display: none;
    }

    .print-hint-title {
      margin: 0;
      color: var(--ink);
      font-size: 0.86rem;
      font-weight: 700;
      letter-spacing: 0.02em;
    }

    .print-hint-sheet {
      margin: 0.1rem 0 0.5rem;
      color: var(--muted);
      font-size: 0.7rem;
      letter-spacing: 0.04em;
    }

    .print-hint ul {
      margin: 0;
      padding: 0 0 0 1rem;
    }

    .print-hint strong {
      color: var(--ink);
    }

    .print-hint-mute {
      display: flex;
      align-items: center;
      gap: 0.4rem;
      margin: 0.7rem 0 0.55rem;
      color: var(--muted);
      font-size: 0.72rem;
    }

    .print-hint-actions {
      display: flex;
      justify-content: flex-end;
      gap: 0.5rem;
    }

    .print-hint-actions button {
      padding: 0.3rem 0.7rem;
      border: 1px solid var(--line-strong);
      border-radius: 8px;
      background: var(--panel);
      color: var(--ink);
      font: inherit;
      cursor: pointer;
    }

    .print-hint-actions button.is-primary {
      border-color: var(--accent);
      background: var(--accent);
      color: #fff;
    }

    @media print {
      html,
      body {
        height: auto;
        background: #fff;
      }

      /* Port fills and rules must survive Chrome's "Background graphics" default. */
      body.print-topology * {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
      }

      body.print-topology {
        display: block;
        min-height: 0;
        margin: 0;
      }

      body.print-topology .masthead,
      body.print-topology .nav-backdrop,
      body.print-topology .print-hint,
      body.print-topology .spa-tab,
      body.print-topology .topo-toolbar {
        display: none !important;
      }

      /* Topology: a single Arch C sheet, printed straight out of #export-root. */
      body.print-topology #export-root {
        position: static;
        left: auto;
        top: auto;
        width: auto;
        pointer-events: auto;
      }

      body.print-topology .export-sheet {
        break-inside: avoid;
      }
    }

    /* Laptop-width: keep Contents beside the article, narrower list. */
    @media (min-width: 861px) and (max-width: 1100px) {
      :root {
        --sidebar-w: 248px;
      }

      .design-shell {
        column-gap: 24px;
        padding-left: 16px;
        padding-right: 16px;
      }

      .topo-wrap {
        height: auto;
      }

    }

    /* Phone / narrow: off-canvas Contents drawer, matching Corporate Governance. */
    @media (max-width: 860px) {
      body.tab-spec .nav-toggle {
        display: flex;
      }

      .nav-backdrop:not([hidden]) {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 44;
        margin: 0;
        padding: 0;
        border: 0;
        appearance: none;
        background: rgba(15, 23, 42, 0.45);
        cursor: pointer;
        touch-action: none;
      }

      body.nav-open {
        overflow: hidden;
      }

      .brand-subtitle {
        display: none;
      }

      .design-shell,
      .spa-spec .spa-article {
        min-width: 0;
      }

      .design-shell {
        display: block;
        padding: 0;
        max-width: none;
      }

      .design-toc {
        position: fixed;
        top: var(--header-h);
        left: calc(min(84vw, var(--sidebar-w)) * -1);
        bottom: auto;
        width: min(84vw, var(--sidebar-w));
        height: calc(100vh - var(--header-h));
        height: calc(100dvh - var(--header-h));
        max-height: calc(100dvh - var(--header-h));
        background: var(--panel);
        border-right: 1px solid var(--line);
        padding: 12px 12px max(28px, env(safe-area-inset-bottom));
        transform: none;
        transition: left 0.22s ease;
        z-index: 45;
        box-shadow: 6px 0 24px rgba(15, 23, 42, 0.12);
        overscroll-behavior: contain;
        -webkit-overflow-scrolling: touch;
      }

      .design-toc.is-open,
      body.nav-open .design-toc {
        left: 0 !important;
        transform: none;
      }

      .design-toc-list a {
        min-height: 44px;
        display: flex;
        align-items: center;
      }

      .spa-spec .spa-article {
        max-width: none;
        padding: 20px max(20px, env(safe-area-inset-right)) calc(100dvh - var(--header-h) - 2rem) max(20px, env(safe-area-inset-left));
        overflow-x: clip;
      }

      .topo-wrap {
        height: auto;
      }

      .topo-toolbar {
        padding-left: max(0.9rem, env(safe-area-inset-left));
        padding-right: max(0.9rem, env(safe-area-inset-right));
      }

    }

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

    /* Keep the Contents drawer above the scrolling Spec pane. */
    .design-toc.is-open {
      z-index: 45;
    }

    :focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 2px;
    }

.spa-loading { padding: 1.25rem; color: var(--muted); }
