    html, body { margin: 0; background: #0d0d0f; overflow: hidden; }
    canvas { display: block; width: 100vw; height: 100vh; }

    /* ── Global focus-outline policy ───────────────────────────────────────
       Companion to the global mouseup-blur handler at the top of the script.
       We hide the focus ring for mouse clicks (which would otherwise look
       like the widget is still "selected" after a click) but keep it for
       keyboard navigation via :focus-visible — so Tab-through is still
       discoverable for anyone who needs it.
       Applies to every interactive element on the page; new UI gets the
       right behaviour automatically with no per-panel CSS. */
    button:focus, input:focus, select:focus, textarea:focus,
    a:focus, label:focus, [tabindex]:focus { outline: none; }
    button:focus-visible, input:focus-visible, select:focus-visible,
    textarea:focus-visible, a:focus-visible, [tabindex]:focus-visible {
      outline: 1px solid #7af; outline-offset: 1px;
    }

    #hud {
      position: fixed; top: 1rem; left: 1rem;
      color: #ccc; font: 13px/1.6 monospace;
      pointer-events: none; text-shadow: 0 1px 3px #000;
    }
    /* Legacy #debug-panel CSS retired — controls now live in the Dev panel.
       Note: the State readout's `<span class="dbk">` / `<span class="dbv">`
       markup is now styled by `#dev-panel .dev-readout .dbk/.dbv` further
       down in this stylesheet. */

    /* ── Build panel (floating right quadrant) ──────────────────────── */
    /* ── Reusable panel resize handles ──────────────────────────────────────
       Eight handles per panel: 4 thin edges (n/s/e/w) for one-axis resize +
       4 corners (ne/nw/se/sw) for two-axis resize. Each handle is invisible
       (hit zone only) and sits flush with the inside edge so the panel's
       overflow:hidden still works. Hover changes the cursor; the JS in
       `_makeResizable` does the actual sizing. */
    .panel-resize-handle { position: absolute; z-index: 5; }
    .panel-resize-n  { top: 0;        left: 0; right: 0;  height: 6px;  cursor: ns-resize; }
    .panel-resize-s  { bottom: 0;     left: 0; right: 0;  height: 6px;  cursor: ns-resize; }
    .panel-resize-e  { right: 0;      top: 0; bottom: 0;  width: 6px;   cursor: ew-resize; }
    .panel-resize-w  { left: 0;       top: 0; bottom: 0;  width: 6px;   cursor: ew-resize; }
    .panel-resize-ne { top: 0;    right: 0; width: 12px; height: 12px;  cursor: nesw-resize; z-index: 6; }
    .panel-resize-nw { top: 0;    left: 0;  width: 12px; height: 12px;  cursor: nwse-resize; z-index: 6; }
    .panel-resize-se { bottom: 0; right: 0; width: 12px; height: 12px;  cursor: nwse-resize; z-index: 6; }
    .panel-resize-sw { bottom: 0; left: 0;  width: 12px; height: 12px;  cursor: nesw-resize; z-index: 6; }

    #build-panel {
      position: fixed; right: 1.25rem; top: 10vh; height: 80vh; width: min(510px, 33.33vw);
      background: rgba(6,8,14,0.90);
      border: 1px solid rgba(255,255,255,0.09);
      border-radius: 10px;
      color: #ccc; font: 11px/1.5 monospace;
      pointer-events: auto; user-select: none;
      display: flex; flex-direction: column;
      overflow: hidden; z-index: 12;
    }
    #build-panel.bp-hidden { display: none; }
    #bp-header {
      padding: 0.5rem 0.6rem 0.4rem 0.85rem;
      border-bottom: 1px solid rgba(255,255,255,0.07);
      color: rgba(255,255,255,0.35); font-size: 10px;
      letter-spacing: 0.12em; text-transform: uppercase; flex-shrink: 0;
      display: flex; align-items: center; justify-content: space-between;
    }
    #bp-close-btn {
      background: none; border: none; cursor: pointer;
      color: rgba(255,255,255,0.30); font: 16px/1 monospace;
      padding: 0 0.2rem; flex-shrink: 0;
      transition: color 0.1s;
    }
    #bp-close-btn:hover { color: #ff8080; }
    #bp-footer {
      padding: 0.45rem 0.85rem;
      border-top: 1px solid rgba(255,255,255,0.07);
      color: rgba(255,255,255,0.25); font-size: 10px;
      letter-spacing: 0.08em; flex-shrink: 0;
    }
    /* Tab strip between header and tabbed content.
       Styled to match #soc-tabs / .soc-tab in the Social panel for visual
       consistency across the two tabbed UIs. */
    #bp-tabs {
      display: flex; gap: 0;
      padding: 0 0.5rem;
      border-bottom: 1px solid rgba(255,255,255,0.07);
      flex-shrink: 0;
    }
    .bp-tab {
      position: relative;
      background: none; border: none;
      padding: 8px 18px;
      color: rgba(255,255,255,0.40);
      font: 11px/1 monospace; letter-spacing: 0.08em;
      text-transform: uppercase;
      cursor: pointer;
      border-bottom: 2px solid transparent;
      margin-bottom: -1px;  /* overlap the section's bottom border */
      transition: color 0.12s, border-color 0.12s;
      outline: none;
    }
    .bp-tab:hover { color: rgba(255,255,255,0.7); }
    .bp-tab.bp-tab-active {
      color: #ffd590;
      border-bottom-color: #ffd590;
    }
    /* Scrolling tab content. Buildings or Color sections live here. */
    #bp-tab-scroll {
      flex: 1 1 auto; min-height: 100px;
      overflow-y: auto; padding: 0.65rem 0.75rem 0.75rem;
    }
    /* Unified scrollbar style — 8px wide, transparent track, soft thumb.
       Applied everywhere a scrollable region exists across the panels:
         · build panel main scroll       (#bp-tab-scroll)
         · build panel inventory grid    (#bp-inventory-grid)
         · social panel outer scroll     (#soc-body) — drives the System tab
         · social friend-list inner      (.soc-list-scroll)
         · settings body                 (#sp-body)
         · dev panel body                (#dev-body)
       One source of truth so adjusting once updates every panel. */
    #bp-tab-scroll::-webkit-scrollbar,
    #bp-inventory-grid::-webkit-scrollbar,
    #soc-body::-webkit-scrollbar,
    .soc-list-scroll::-webkit-scrollbar,
    #sp-body::-webkit-scrollbar,
    #dev-body::-webkit-scrollbar { width: 8px; height: 8px; }
    #bp-tab-scroll::-webkit-scrollbar-track,
    #bp-inventory-grid::-webkit-scrollbar-track,
    #soc-body::-webkit-scrollbar-track,
    .soc-list-scroll::-webkit-scrollbar-track,
    #sp-body::-webkit-scrollbar-track,
    #dev-body::-webkit-scrollbar-track { background: transparent; }
    #bp-tab-scroll::-webkit-scrollbar-thumb,
    #bp-inventory-grid::-webkit-scrollbar-thumb,
    #soc-body::-webkit-scrollbar-thumb,
    .soc-list-scroll::-webkit-scrollbar-thumb,
    #sp-body::-webkit-scrollbar-thumb,
    #dev-body::-webkit-scrollbar-thumb {
      background: rgba(255,255,255,0.10);
      border-radius: 4px;
    }
    #bp-tab-scroll::-webkit-scrollbar-thumb:hover,
    #bp-inventory-grid::-webkit-scrollbar-thumb:hover,
    #soc-body::-webkit-scrollbar-thumb:hover,
    .soc-list-scroll::-webkit-scrollbar-thumb:hover,
    #sp-body::-webkit-scrollbar-thumb:hover,
    #dev-body::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.22); }
    .bp-tab-pane { display: none; }
    .bp-tab-pane.bp-tab-pane-active { display: block; }
    .bp-section { margin-bottom: 1.1rem; }
    .bp-section-header {
      color: rgba(255,255,255,0.32); font-size: 9.5px; letter-spacing: 0.14em;
      text-transform: uppercase; margin-bottom: 0.4rem;
      padding-bottom: 0.2rem; border-bottom: 1px solid rgba(255,255,255,0.06);
    }
    /* Building cards flow with a fixed per-card width (like inventory tiles)
       so resizing the panel changes how MANY cards fit per row, not how big
       each card is. align-content pins lines to the top so wrapping doesn't
       leave dead vertical space. */
    .bp-section-cards {
      display: flex; flex-wrap: wrap; gap: 0.4rem;
      align-content: flex-start;
    }

    /* Shared filter input — palettes, buildings, inventory all use this. */
    .bp-filter-input {
      width: 100%; box-sizing: border-box;
      padding: 0.45rem 0.6rem;
      background: rgba(255,255,255,0.04);
      border: 1px solid rgba(255,255,255,0.10);
      border-radius: 4px;
      color: rgba(255,255,255,0.85);
      font: 11px/1 monospace; letter-spacing: 0.04em;
      outline: none;
      margin-bottom: 0.55rem;
      transition: border-color 0.12s, background 0.12s;
      flex-shrink: 0;  /* don't let inventory's filter collapse when grid grows */
    }
    .bp-filter-input::placeholder { color: rgba(255,255,255,0.30); }
    .bp-filter-input:focus {
      border-color: rgba(255,213,144,0.45);
      background: rgba(255,255,255,0.06);
    }
    /* Search + tag-filter dropdown laid out side-by-side. The search input
       grows; the dropdown stays narrow on the right. */
    .bp-filter-row {
      display: flex; gap: 0.4rem;
      margin-bottom: 0.55rem;
      flex-shrink: 0;
    }
    .bp-filter-row .bp-filter-input {
      flex: 1 1 auto;
      margin-bottom: 0;
    }
    /* Custom tag-filter dropdown with multi-select checkboxes. Native <select>
       can't host checkboxes, so we build a button + popup. Multiple checks are
       ANDed by the filter logic. */
    .bp-tag-filter {
      position: relative;
      flex: 0 0 auto;
    }
    .bp-tag-filter-btn {
      min-width: 110px; box-sizing: border-box;
      padding: 0.45rem 0.6rem;
      background: rgba(255,255,255,0.04);
      border: 1px solid rgba(255,255,255,0.10);
      border-radius: 4px;
      color: rgba(255,255,255,0.85);
      font: 11px/1 monospace; letter-spacing: 0.04em;
      outline: none; cursor: pointer;
      display: flex; align-items: center; gap: 0.35rem;
      transition: border-color 0.12s, background 0.12s;
    }
    .bp-tag-filter-btn::after {
      content: '▾'; margin-left: auto; opacity: 0.5;
    }
    .bp-tag-filter-btn:hover { border-color: rgba(255,255,255,0.20); }
    .bp-tag-filter.bp-tag-filter-open .bp-tag-filter-btn,
    .bp-tag-filter.bp-tag-filter-active .bp-tag-filter-btn {
      border-color: rgba(255,213,144,0.45);
    }
    .bp-tag-filter-btn-count {
      display: none;
      background: rgba(255,213,144,0.55);
      color: #1a1c24;
      border-radius: 8px;
      padding: 0 5px;
      font: bold 9px/1.5 monospace;
      flex-shrink: 0;
    }
    .bp-tag-filter.bp-tag-filter-active .bp-tag-filter-btn-count { display: inline-block; }

    .bp-tag-filter-popup {
      display: none;
      position: fixed;  /* fixed so the popup escapes its panel's overflow:hidden;
                            JS sets `top`/`left` based on the button's rect when opened */
      min-width: 170px;
      background: rgba(15,17,24,0.97);
      border: 1px solid rgba(255,255,255,0.12);
      border-radius: 5px;
      padding: 0.4rem 0.3rem;
      z-index: 60;
      box-shadow: 0 4px 14px rgba(0,0,0,0.45);
    }
    .bp-tag-filter.bp-tag-filter-open .bp-tag-filter-popup { display: block; }
    .bp-tag-filter-popup label {
      display: flex; align-items: center; gap: 0.45rem;
      padding: 0.3rem 0.4rem;
      cursor: pointer;
      font: 11px/1 monospace; letter-spacing: 0.02em;
      color: rgba(255,255,255,0.78);
      border-radius: 3px;
      user-select: none;
    }
    .bp-tag-filter-popup label:hover {
      background: rgba(255,255,255,0.06);
      color: #fff;
    }
    .bp-tag-filter-popup input[type=checkbox] {
      flex-shrink: 0;
      width: 12px; height: 12px;
      margin: 0;
      accent-color: rgba(255,213,144,0.85);
      cursor: pointer;
      outline: none;  /* no focus rectangle — keyboard focus is dropped on change */
    }
    .bp-tag-filter-popup input[type=checkbox]::-moz-focus-inner { border: 0; }
    .bp-tag-filter-popup input[type=checkbox]:focus { outline: none; }
    /* Pool building cards into a single flex flow when filtering is active.
       Two `display: contents` layers flatten .bp-section and .bp-section-cards
       so cards become direct flex items of #bp-building-sections. */
    #bp-building-sections.filtering {
      display: flex; flex-wrap: wrap;
      gap: 0.4rem;
      align-content: flex-start;
    }
    #bp-building-sections.filtering .bp-section,
    #bp-building-sections.filtering .bp-section-cards { display: contents; }
    #bp-building-sections.filtering .bp-section-header { display: none; }
    /* When filtering is active, replace the per-section headers with a single
       "Results" label so cards don't jump vertically by the missing header
       height. `flex: 0 0 100%` is the flex equivalent of `grid-column: 1/-1`
       — it spans a full row so cards wrap below it. */
    .bp-filtered-header {
      display: none;
      color: rgba(255,255,255,0.32); font-size: 9.5px; letter-spacing: 0.14em;
      text-transform: uppercase;
      padding-bottom: 0.2rem;
      border-bottom: 1px solid rgba(255,255,255,0.06);
    }
    #bp-building-sections.filtering .bp-filtered-header {
      display: block;
      flex: 0 0 100%;
    }
    #bp-palette-list { display: flex; flex-direction: column; gap: 0.35rem; }
    .bp-palette-row {
      display: flex; align-items: center;
      padding: 0.4rem 0.55rem;
      border: 1px solid rgba(255,255,255,0.07);
      border-radius: 5px;
      background: rgba(255,255,255,0.015);
      cursor: pointer;
      transition: background 0.12s, border-color 0.12s, opacity 0.12s;
    }
    .bp-palette-row:hover {
      background: rgba(255,255,255,0.05);
      border-color: rgba(255,255,255,0.18);
    }
    .bp-palette-row.bp-palette-active {
      background: rgba(100,170,255,0.10);
      border-color: rgba(100,170,255,0.45);
    }
    .bp-palette-row.bp-palette-locked { cursor: not-allowed; }
    .bp-palette-row.bp-palette-locked .bp-palette-name,
    .bp-palette-row.bp-palette-locked .bp-palette-groups { opacity: 0.40; }
    .bp-palette-name {
      flex: 0 0 auto; min-width: 80px;
      margin-right: 1.1rem;  /* breathing room between the name and the swatch groups */
      color: rgba(255,255,255,0.78);
      font: 10px/1.2 monospace; letter-spacing: 0.06em;
    }
    .bp-palette-row.bp-palette-active .bp-palette-name { color: #cfe6ff; }
    .bp-palette-groups {
      display: flex; gap: 0.45rem; flex: 0 0 auto;
    }
    .bp-palette-group { /* swatch grid only; group name shows on hover via `title` */ }
    .bp-palette-group-swatches {
      display: grid; grid-template-columns: 12px 12px; grid-template-rows: 12px 12px; gap: 1px;
      border: 1px solid rgba(0,0,0,0.45);
    }
    .bp-palette-swatch { width: 12px; height: 12px; }
    /* Lock indicator — SVG, styled to match the line-art icons in the bottom toolbar
       (.bt-icon). currentColor lets us tint by row state without per-icon CSS. */
    .bp-palette-lock {
      flex: 0 0 auto;
      width: 18px; height: 18px;
      margin-left: auto;  /* push to the right edge of the row */
      display: flex; align-items: center; justify-content: center;
      color: rgba(255,255,255,0.55);
    }
    .bp-palette-lock svg { width: 100%; height: 100%; }
    .bp-palette-row.bp-palette-locked .bp-palette-lock { color: rgba(255,180,80,0.85); }
    .bp-palette-row.bp-palette-active   .bp-palette-lock { color: rgba(207,230,255,0.75); }

    /* Splitter handle between tab content and inventory. Drag to resize.
       The visible bar is only 4px tall, but the element is 12px tall so it's
       easy to grab — the visible bar sits in the middle via a pseudo-element. */
    #bp-splitter {
      flex: 0 0 auto;
      height: 12px;
      cursor: row-resize;
      position: relative;
      background: transparent;
    }
    #bp-splitter::before {
      content: '';
      position: absolute;
      inset: 4px 0;  /* 4px from top + bottom → 4px visible bar centred */
      background: rgba(255,255,255,0.06);
      transition: background 0.12s;
    }
    #bp-splitter:hover::before,
    #bp-splitter.dragging::before { background: rgba(255,213,144,0.45); }

    /* ── Inventory section (always visible, own scroll) ──────────────────── */
    /* `height` is the user-controlled size (set by drag, persisted in
       userSettings.bpInventoryHeight). Min/max guard against the panel being
       resized into impossible shapes — without these the inventory could swallow
       the tab content or shrink to a single header line. */
    #bp-inventory-section {
      flex: 0 0 auto;
      height: 30vh;
      min-height: 60px;
      max-height: calc(80vh - 150px);
      display: flex; flex-direction: column;
      padding: 0.55rem 0.75rem 0.6rem;
    }
    .bp-inv-section-header {
      color: rgba(255,255,255,0.32); font-size: 9.5px; letter-spacing: 0.14em;
      text-transform: uppercase; margin-bottom: 0.4rem; flex-shrink: 0;
    }
    #bp-inventory-grid {
      flex: 1 1 auto;
      display: flex; flex-wrap: wrap; gap: 5px;
      align-content: flex-start;  /* stack rows from top — without this the
                                     wrapped second row gets pushed down by
                                     align-content: stretch (the default). */
      overflow-y: auto;
    }
    /* (#bp-inventory-grid scrollbar inherits from the unified rule above.) */
    /* cost-html resource colours (kept for card cost display) */
    .bp-fe  { color: #e87; } .bp-si { color: #8ef; } .bp-gl { color: #6cf; } .bp-st { color: #ba8; }

    /* ── Bottom toolbar ───────────────────────────────────────────────────── */
    #bottom-toolbar {
      position: fixed; bottom: 0.75rem; left: 50%; transform: translateX(-50%);
      display: flex; gap: 20px; align-items: flex-end;
      pointer-events: none; z-index: 20;
      user-select: none; -webkit-user-select: none;
    }
    .bt-section {
      display: flex; flex-direction: column; align-items: center; gap: 5px;
    }
    .bt-label {
      font: 9px/1 monospace; letter-spacing: 0.18em; text-transform: uppercase;
      color: rgba(255,255,255,0.60); pointer-events: none; user-select: none;
    }
    .bt-group {
      display: flex; gap: 4px;
      background: rgba(6,8,14,0.88);
      border: 1px solid rgba(255,255,255,0.09);
      border-radius: 8px; padding: 5px;
      pointer-events: auto;
    }
    .bt-btn {
      position: relative;
      width: 56px; height: 56px;
      border-radius: 6px; border: 1px solid rgba(255,255,255,0.08);
      background: rgba(255,255,255,0.03); color: rgba(255,255,255,0.40);
      display: flex; flex-direction: column; align-items: center;
      justify-content: center; gap: 3px; padding: 0;
      cursor: pointer; transition: background 0.12s, color 0.12s, border-color 0.12s;
    }
    .bt-btn:hover {
      background: rgba(255,255,255,0.07); color: rgba(255,255,255,0.72);
      border-color: rgba(255,255,255,0.18);
    }
    .bt-btn.bt-active-build    { background: rgba(100,170,255,0.13); border-color: rgba(100,170,255,0.35); color: #8ec8ff; }
    .bt-btn.bt-active-mine     { background: rgba(255,185,60,0.13);  border-color: rgba(255,185,60,0.35);  color: #ffc870; }
    .bt-btn.bt-active-power    { background: rgba(80,210,150,0.13);  border-color: rgba(80,210,150,0.35);  color: #6edbb0; }
    .bt-btn.bt-active-items    { background: rgba(195,140,255,0.13); border-color: rgba(195,140,255,0.35); color: #c88cff; }
    .bt-btn.bt-active-ore      { background: rgba(225,80,60,0.13);   border-color: rgba(225,80,60,0.40);   color: #ff7e6e; }
    .bt-btn.bt-active-social   { background: rgba(255,200,140,0.13); border-color: rgba(255,200,140,0.35); color: #ffd590; }
    .bt-btn.bt-active-settings { background: rgba(200,200,210,0.14); border-color: rgba(200,200,210,0.35); color: #d8dae0; }
    .bt-btn.bt-active-feats    { background: rgba(255,200,90,0.14);  border-color: rgba(255,200,90,0.40);  color: #ffd070; }
    /* Pulse animation while a manual cloud save is in flight.  Click handler
       adds .bt-saving, removes it when _saveToCloud resolves; the existing
       "Saved ✓" toast then flashes naturally. */
    @keyframes bt-save-pulse {
      0%, 100% { background: rgba(120,200,170,0.10); border-color: rgba(120,200,170,0.32); }
      50%      { background: rgba(120,200,170,0.26); border-color: rgba(120,200,170,0.62); }
    }
    .bt-btn.bt-saving {
      animation: bt-save-pulse 0.75s ease-in-out infinite;
      color: #6edbb0;
    }
    .bt-btn.bt-saving:hover { color: #aef0c0; }
    /* Disabled state — guest can't open Social, hovering does nothing visual. */
    .bt-btn.bt-disabled {
      opacity: 0.40;
      cursor: not-allowed;
    }
    .bt-btn.bt-disabled:hover {
      background: rgba(255,255,255,0.03);
      border-color: rgba(255,255,255,0.08);
      color: rgba(255,255,255,0.40);
    }
    .bt-key {
      position: absolute; top: 4px; left: 5px;
      font: bold 9px/1 monospace; color: rgba(255,255,255,0.50); pointer-events: none;
    }
    .bt-icon { width: 28px; height: 28px; flex-shrink: 0; }
    .bt-icon svg { width: 100%; height: 100%; }
    .bt-name {
      font: 8px/1 monospace; letter-spacing: 0.10em; text-transform: uppercase;
      pointer-events: none;
    }

    /* ── Building radial action menu ──────────────────────────────────────── */
    #building-radial {
      position: fixed; pointer-events: auto; z-index: 25;
      display: flex; gap: 10px;
      transform: translate(-50%, calc(-100% - 14px));
    }
    #building-radial.brm-hidden { display: none; }
    .brm-btn {
      width: 38px; height: 38px; border-radius: 50%;
      border: 1px solid rgba(255,255,255,0.18);
      background: rgba(10,12,18,0.92);
      color: #ddd; font-size: 15px; cursor: pointer;
      display: flex; align-items: center; justify-content: center;
      transition: background 0.12s, border-color 0.12s;
    }
    .brm-btn:hover { background: rgba(40,55,80,0.97); border-color: rgba(255,255,255,0.38); }
    #brm-delete { color: #ff8080; }
    #brm-delete:hover { background: rgba(70,18,18,0.97); border-color: rgba(255,80,80,0.5); }
    #brm-move { color: #80c8ff; }
    #brm-move:hover { background: rgba(15,45,70,0.97); border-color: rgba(80,180,255,0.5); }
    #brm-edit { color: #ffe080; }
    #brm-edit:hover { background: rgba(50,45,12,0.97); border-color: rgba(255,210,80,0.5); }

    /* ── Building info panel ──────────────────────────────────────────────── */
    #building-info-panel {
      position: fixed; bottom: 5rem; left: 50%; transform: translateX(-50%);
      background: rgba(10,12,18,0.92); border: 1px solid rgba(255,255,255,0.12);
      border-radius: 8px; padding: 10px 14px; min-width: 200px; max-width: 320px;
      color: #ccc; font-size: 11px; pointer-events: auto; z-index: 20;
    }
    #building-info-panel.bip-hidden { display: none; }
    .bip-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
    .bip-title { font-weight: bold; color: #eee; font-size: 13px; letter-spacing: 0.04em; }
    .bip-close { background: none; border: none; color: #888; cursor: pointer; font-size: 14px; padding: 0 2px; }
    .bip-close:hover { color: #fff; }
    .bip-row { display: flex; justify-content: space-between; margin: 3px 0; }
    .bip-label { color: rgba(255,255,255,0.45); }
    .bip-val { color: #dde; }
    .bip-inventory { margin-top: 8px; border-top: 1px solid rgba(255,255,255,0.08); padding-top: 6px; }
    .bip-inv-row { display: flex; align-items: center; gap: 8px; margin: 2px 0; }
    .bip-inv-icon { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
    /* Per-item background colour is set inline via itemDotColor() — see the
       bip-inventory-row HTML in the building info panel renderer. */
    /* ── Player inventory bar ──────────────────────────────────────────────── */
    #player-inventory { display: none !important; }
    .pi-slot {
      width: 54px; height: 54px;
      background: rgba(0,0,0,0.55);
      border: 1px solid rgba(255,255,255,0.28);
      border-radius: 7px;
      display: flex; flex-direction: column;
      align-items: center; justify-content: center; gap: 2px;
      font: 10px/1.3 monospace; color: #ccc;
    }
    .pi-slot .pi-icon { width: 14px; height: 14px; border-radius: 50%; flex-shrink: 0; }
    .pi-slot .pi-count { color: #efa; font-size: 13px; font-weight: bold; line-height: 1; }
    .pi-slot .pi-label { color: rgba(255,255,255,0.4); font-size: 9px; }
    /* Collection radius ring is rendered in WebGL (RingRenderer), not as a DOM element */
    /* ── Flying item particles ──────────────────────────────────────────────── */
    .fly-particle {
      position: fixed; pointer-events: none; z-index: 16;
      width: 10px; height: 10px; border-radius: 50%;
      transform: translate(-50%, -50%);
      box-shadow: 0 0 5px currentColor;
    }
    /* ── Interact / collect prompt ──────────────────────────────────────────── */
    #interact-prompt {
      position: fixed; bottom: 3rem; left: 50%; transform: translateX(-50%);
      background: rgba(0,0,0,0.65); border: 1px solid rgba(255,255,255,0.15);
      border-radius: 5px; padding: 4px 14px;
      color: #afa; font: 12px/1.8 monospace;
      pointer-events: none; z-index: 10;
      opacity: 0; transition: opacity 0.15s;
    }
    #interact-prompt.visible { opacity: 1; }
    /* ── Collect button (drill panel) ───────────────────────────────────────── */
    .bip-collect-btn {
      margin-top: 8px; width: 100%;
      background: rgba(80,180,80,0.15); border: 1px solid rgba(80,180,80,0.3);
      border-radius: 4px; padding: 5px 0;
      color: #8d8; font: 11px/1 monospace; cursor: pointer;
      transition: background 0.12s;
    }
    .bip-collect-btn:hover:not(:disabled) { background: rgba(80,180,80,0.30); }
    .bip-collect-btn:disabled { opacity: 0.35; cursor: default; }
    /* ── Drill placement preview label ────────────────────────────────────
       Floats just above the hovered face during Drill placement.  Two rows:
         row 1 (.dpl-resources) — each ore/terrain in its own item colour
         row 2 (.dpl-yield)     — coverage fraction + percent, colour-coded
                                  by yield quality (red 1/7 → green ≥4/7)
       Position (left/top) is set per-frame from the face centroid's screen
       projection — translate(-50%, -100%) anchors the bottom-centre of the
       label to that point so it sits above the ghost building. */
    #drill-preview-label {
      position: fixed; transform: translate(-50%, -100%);
      display: flex; flex-direction: column; align-items: center;
      background: rgba(0,0,0,0.80); border-radius: 5px; padding: 4px 9px 5px;
      font-family: monospace;
      pointer-events: none; z-index: 20; white-space: nowrap;
      box-shadow: 0 2px 10px rgba(0,0,0,0.65);
      line-height: 1.25;
    }
    #drill-preview-label .dpl-resources { font-size: 11px; }
    #drill-preview-label .dpl-yield     { font-size: 10px; font-weight: bold; letter-spacing: 0.05em; }
    #drill-preview-label.dpl-hidden { display: none; }
    /* ── Building inventory badges (shown when RMB held) ─────────────────── */
    .ci-icon {
      position: fixed; pointer-events: none; z-index: 14;
      transform: translate(-50%, -100%);
      display: none;
      flex-direction: column; gap: 2px;   /* constant layout — set once in CSS */
      background: rgba(6, 8, 16, 0.82);
      border: 1px solid rgba(255,255,255,0.12);
      border-radius: 5px;
      padding: 3px 8px;
      font-size: 12px; font-family: monospace;
      white-space: nowrap;
      box-shadow: 0 1px 6px rgba(0,0,0,0.5);
      color: #fff;
    }
    /* ── Controls hint panel ─────────────────────────────────────────────── */
    #controls-hint {
      position: fixed; bottom: 1.5rem; left: 1rem;
      z-index: 12; pointer-events: none;
      background: rgba(6, 8, 16, 0.72);
      border: 1px solid rgba(255,255,255,0.07);
      border-radius: 8px;
      padding: 7px 11px;
      display: flex; flex-direction: column; gap: 3px;
      font: 10px/1.5 monospace;
      color: rgba(255,255,255,0.45);
      transition: opacity 0.2s ease;
    }
#controls-hint .ch-row { display: flex; align-items: center; gap: 6px; }
    #controls-hint kbd {
      display: inline-block;
      background: rgba(255,255,255,0.08);
      border: 1px solid rgba(255,255,255,0.16);
      border-radius: 3px;
      padding: 0px 5px;
      font: 10px/1.6 monospace;
      color: rgba(255,255,255,0.75);
      white-space: nowrap;
    }
    /* ── Power generation/consumption labels (shown when P is on) ────────── */
    .pw-badge {
      position: fixed; pointer-events: none; z-index: 14;
      transform: translate(-50%, -100%);
      display: none;
      align-items: center; gap: 2px;
      background: rgba(4, 6, 14, 0.70);
      border: 1px solid rgba(255,255,255,0.08);
      border-radius: 4px;
      padding: 1px 5px;
      font-size: 10px; font-family: monospace;
      color: #fff; white-space: nowrap;
      opacity: 0.65;
    }
    /* ── Per-island power network portrait cards ────────────────────────── */
    .pw-portrait {
      position: fixed; pointer-events: none; z-index: 16;
      transform: translate(-50%, -100%);
      display: none; flex-direction: column;
      min-width: 148px;
      background: rgba(4, 6, 20, 0.95);
      border: 2px solid #4af;
      border-radius: 9px;
      padding: 8px 13px 10px;
      font-family: monospace;
      box-shadow: 0 4px 24px rgba(0,0,0,0.80);
    }
    .pwp-header {
      font-size: 11px; font-weight: bold; letter-spacing: 0.10em; text-transform: uppercase;
      text-align: center; margin-bottom: 6px; padding-bottom: 5px;
      border-bottom: 1px solid rgba(255,255,255,0.10);
    }
    .pwp-row { display: flex; justify-content: space-between; align-items: baseline; padding: 2px 0; }
    .pwp-lbl { color: rgba(255,255,255,0.38); font-size: 9px; letter-spacing: 0.07em; text-transform: uppercase; }
    .pwp-val { font-size: 15px; font-weight: bold; }
    .pwp-divider { border-top: 1px solid rgba(255,255,255,0.08); margin: 4px 0 3px; }
    .pwp-net-row .pwp-val { font-size: 18px; }
    .pwp-max { color: rgba(255,255,255,0.30); font-size: 11px; font-weight: normal; }
    .pwp-bar {
      height: 5px; background: rgba(255,255,255,0.10);
      border-radius: 3px; overflow: hidden; margin-top: 6px;
    }
    .pwp-bar-fill { height: 100%; border-radius: 3px; }
    .pwp-bar-wrap { margin-top: 6px; }
    /* ── Per-cluster ore deposit label (Phase 1d) ───────────────────────── */
    /* Same screen-projected anchoring as .pw-portrait but stripped down to a
       single colored pill — there's no per-deposit numeric state to show,
       only the ore name.  Border + text colour set inline from
       ORE_DEFS.overlay so palette edits propagate without CSS churn. */
    .ore-label {
      position: fixed; pointer-events: none; z-index: 16;
      transform: translate(-50%, -100%);
      display: none;
      background: rgba(4, 6, 20, 0.92);
      border: 1.5px solid currentColor;
      border-radius: 999px;
      padding: 2px 9px 3px;
      font-family: monospace;
      font-size: 11px; font-weight: bold;
      letter-spacing: 0.06em; text-transform: uppercase;
      box-shadow: 0 2px 10px rgba(0,0,0,0.6);
      white-space: nowrap;
    }
    /* ── Low-power icon overlay + magnet collect icon ───────────────────── */
    .low-power-icon {
      position: fixed; pointer-events: none; z-index: 15;
      font-size: 14px; text-shadow: 0 0 4px rgba(0,0,0,0.8);
      transform: translate(-50%, -100%);
    }
    #magnet-icon, #trash-icon {
      position: fixed; pointer-events: none; z-index: 15;
      transform: translate(-50%, calc(-100% - 6px));
      display: none;
      align-items: center; gap: 5px;
      background: rgba(6, 8, 16, 0.88);
      border-radius: 7px;
      padding: 4px 9px;
      font-size: 14px;
      line-height: 1;
      white-space: nowrap;
      box-shadow: 0 2px 8px rgba(0,0,0,0.6);
      transition: top 0.06s ease;
    }
    #magnet-icon {
      border: 1px solid rgba(255, 205, 50, 0.65);
      color: #ffd93d;
    }
    #trash-icon {
      border: 1px solid rgba(255, 80, 80, 0.65);
      color: #ff7070;
    }
    #magnet-icon span, #trash-icon span {
      font-size: 10px; opacity: 0.75; letter-spacing: 0.04em; font-family: monospace;
    }
    .bp-res.insufficient .bp-count { color: #f66; }
    .bp-card {
      background: rgba(255,255,255,0.04);
      border: 1px solid rgba(255,255,255,0.10);
      border-radius: 6px; padding: 0.35rem 0.4rem 0.4rem;
      cursor: pointer; transition: border-color 0.12s, background 0.12s;
      text-align: center;
      box-sizing: border-box;
      /* Fixed card size + flex-wrap on the parent: same tile always, varying
         columns per row. min-height matches the tallest natural card (2-line
         name + icon) so wrapping doesn't introduce uneven row heights. */
      flex: 0 0 90px; width: 90px;
      min-height: 86px;
      display: flex; flex-direction: column; justify-content: center; align-items: center;
      /* position+overflow let the diagonal corner banner clip cleanly to
         the card's rounded rectangle. */
      position: relative;
      overflow: hidden;
    }
    .bp-card:hover { background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.22); }
    .bp-card.selected { border-color: #7af; background: rgba(100,170,255,0.13); }
    .bp-card svg { display: block; margin: 0 auto; width: 44px; height: 44px; color: #9bc; flex-shrink: 0; }
    .bp-card.selected svg { color: #7af; }
    /* PNG icons (e.g. Solar Panel uses solarpanel.png) sized to match the
       SVG icons.  No color filter — the PNG ships with its own palette
       and a transparent background.  The selected-card highlight is the
       border + tinted card bg from .bp-card.selected; PNGs don't tint.
       A white silhouette outline (chained drop-shadows in the four
       cardinal directions) traces every alpha edge so the dark-blue
       regions of the icon don't disappear into the dark card surface.
       1px offsets at the 44px rendered size give a clean ~1px halo. */
    .bp-card .bp-card-img {
      display: block;
      margin: 0 auto;
      width: 44px; height: 44px;
      flex-shrink: 0;
      object-fit: contain;
      image-rendering: auto;
      filter:
        drop-shadow( 1px  0   0 #fff)
        drop-shadow(-1px  0   0 #fff)
        drop-shadow( 0    1px 0 #fff)
        drop-shadow( 0   -1px 0 #fff);
    }
    .bp-card-name { font-size: 10px; color: #ccc; margin-top: 0.15rem; letter-spacing: 0.02em; line-height: 1.15; }
    .bp-card.cant-afford { opacity: 0.65; }
    /* Top-right diagonal "WIP" banner — shown on building cards whose
       BUILDING_DEFS entry has `upcoming: true`.  Construction-tape
       aesthetic: amber main band framed by amber + dark diagonal hazard
       stripes at the top and bottom edges only, with bold black text
       on the solid amber center for max contrast.  Letting the stripes
       run through the WHOLE banner (the v466 design) chopped the text
       up against alternating yellow / black backgrounds and the 1-pixel
       outline wasn't enough to keep it legible — confining the stripes
       to thin top + bottom bands gives the same construction-sign feel
       while leaving a clean amber strip behind the letters.
       The strip is sized to span the corner from card-edge to card-edge:
       rotated 45° clockwise, anchored above the top-right corner with a
       horizontal extent wider than the card so the chord sits well
       inside the rounded rect.  pointer-events stays disabled so clicks
       still reach the card body. */
    .bp-card-wip-banner {
      position: absolute;
      top: 11px; right: -32px;
      width: 110px; height: 18px;
      /* Two-layer background: top layer paints a solid amber band over
         the middle 10px, leaving the hazard stripes underneath visible
         only in the top 3px and bottom 3px of the banner.  A 1-pixel
         black band sits between each stripe row and the amber center
         so the yellow halves of the hazard stripes don't bleed straight
         into the (also yellow) center fill — gives the stripe edges a
         crisp boundary against the solid label area. */
      background-color: #f5b500;
      background-image:
        linear-gradient(
          to bottom,
          transparent 0,  transparent 3px,
          #1a1a1a   3px,  #1a1a1a   4px,
          #f5b500   4px,  #f5b500   14px,
          #1a1a1a   14px, #1a1a1a   15px,
          transparent 15px, transparent 18px
        ),
        repeating-linear-gradient(
          -45deg,
          #f5b500 0, #f5b500 6px,
          #1a1a1a 6px, #1a1a1a 12px
        );
      color: #1a1a1a;
      font-size: 11px; font-weight: 900;
      line-height: 18px;
      text-align: center;
      /* Negative letter-spacing tightens W.I.P. to roughly half the width
         it had at 0.2em (the v=467 setting); combined with a 0.5px text
         stroke, the letters read as a single compact "stamp" rather than
         a spaced-out caption. */
      letter-spacing: -0.02em;
      -webkit-text-stroke: 0.5px #1a1a1a;
      text-transform: uppercase;
      border-top:    1px solid rgba(0,0,0,0.95);
      border-bottom: 1px solid rgba(0,0,0,0.95);
      transform: rotate(45deg);
      transform-origin: 50% 50%;
      pointer-events: none;
      box-shadow: 0 1px 2px rgba(0,0,0,0.4);
      /* Lift the banner above the icon's stacking context.  Without this,
         the `filter: drop-shadow(...)` on .bp-card-img creates its own
         stacking context that paints over the banner in DOM order; an
         explicit z-index ensures the W.I.P. tape always sits on top of
         the icon graphic regardless of which child renders last. */
      z-index: 2;
    }
    /* Material debug legend */
    #mat-legend {
      display: none;
      position: fixed; bottom: 1.5rem; left: 1rem;
      background: rgba(0,0,0,0.6);
      border: 1px solid rgba(255,255,255,0.08);
      border-radius: 6px;
      padding: 0.5rem 0.75rem;
      color: #ccc; font: 12px/1.8 monospace;
      pointer-events: none;
    }
    #mat-legend.visible { display: block; }
    .mat-legend-row { display: flex; align-items: center; gap: 8px; }
    .mat-swatch {
      width: 14px; height: 14px; border-radius: 2px;
      flex-shrink: 0; border: 1px solid rgba(255,255,255,0.15);
    }


    /* Node visualizer */
    #node-viz {
      position: fixed; top: 50%; left: 50%;
      transform: translate(-50%, -50%);
      background: rgba(0,0,0,0.90);
      border: 1px solid rgba(255,255,255,0.12);
      border-radius: 8px;
      padding: 0.6rem 0.75rem 0.5rem;
      z-index: 50; pointer-events: none;
    }
    #node-viz.nv-hidden { display: none; }
    #node-viz-title {
      color: rgba(255,255,255,0.28); font: 10px/2 monospace;
      letter-spacing: 0.12em; text-align: center;
    }
    #node-viz-grid {
      display: grid;
      grid-template-columns: 14px 1fr;
      grid-template-rows: 1fr 14px;
      gap: 0;
    }
    #node-viz-ylabel {
      grid-column: 1; grid-row: 1;
      writing-mode: vertical-rl; transform: rotate(180deg);
      display: flex; justify-content: space-between;
      color: rgba(255,255,255,0.22); font: 9px monospace;
      padding: 2px 0;
    }
    #node-viz-canvas {
      grid-column: 2; grid-row: 1;
      display: block; border-radius: 3px;
      image-rendering: pixelated;
      width: 600px; height: 600px;
    }
    #node-viz-xlabel {
      grid-column: 2; grid-row: 2;
      display: flex; justify-content: space-between;
      color: rgba(255,255,255,0.22); font: 9px monospace;
      padding: 3px 0 0;
    }
    #node-viz-mats {
      display: flex; gap: 4px; margin-top: 0.5rem; flex-wrap: wrap;
    }
    .nv-mat {
      background: rgba(255,255,255,0.05);
      border: 1px solid rgba(255,255,255,0.12);
      border-radius: 4px; color: rgba(255,255,255,0.5);
      font: 10px/1 monospace; padding: 3px 7px;
      cursor: pointer; pointer-events: auto;
      transition: background 0.1s, color 0.1s, border-color 0.1s;
    }
    .nv-mat:hover { background: rgba(255,255,255,0.1); color: #fff; }
    .nv-mat.active { background: rgba(122,170,255,0.18); border-color: #7af; color: #7af; }

    /* ── Dev panel (` to open) ────────────────────────────────────────────── */
    /* Single floating panel that lists every Dev-registered viewer/flag/action.
       Mirrors the Settings panel chrome (header bar with X, drag handle on
       header, 8 resize handles via _registerPanel) so the two panels look and
       behave identically.  #dev-body is innerHTML-replaced on each render;
       the header + close button + resize handles persist. */
    #dev-panel {
      position: fixed; top: 60px; right: 16px;
      width: 320px; max-height: 90vh;
      background: rgba(6,8,14,0.96);
      border: 1px solid rgba(255,255,255,0.09); border-radius: 10px;
      color: #ccc; font: 12px/1.5 monospace;
      z-index: 60;
      display: flex; flex-direction: column;
      overflow: hidden;
      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
      /* Make every label/section/chip un-selectable so click-and-drag on a
         row doesn't highlight text instead of toggling the control. */
      user-select: none;
      -webkit-user-select: none;
    }
    #dev-panel.dev-hidden { display: none; }
    #dev-header {
      display: flex; align-items: center; justify-content: space-between;
      padding: 0.55rem 0.75rem;
      border-bottom: 1px solid rgba(255,255,255,0.07);
      font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase;
      color: rgba(255,255,255,0.45);
      flex-shrink: 0;
    }
    #dev-close-btn {
      background: none; border: none; color: rgba(255,255,255,0.3);
      cursor: pointer; font: 15px/1 monospace; padding: 0 2px;
    }
    #dev-close-btn:hover { color: #fff; }
    #dev-body {
      padding: 0.5rem 0.75rem 0.75rem;
      flex: 1 1 auto;
      overflow-y: auto;
      min-height: 0;
    }
    #dev-panel .dev-section {
      color: rgba(255,255,255,0.32); letter-spacing: 0.10em;
      font-size: 9px; padding-top: 8px; padding-bottom: 3px;
    }
    /* Section headers are clickable buttons that collapse/expand the rows
       below them.  Caret indicates state (▾ open, ▸ closed). */
    #dev-panel .dev-section-toggle {
      display: flex; align-items: center; gap: 4px;
      width: 100%; box-sizing: border-box;
      background: none; border: none; cursor: pointer;
      color: rgba(255,255,255,0.55); letter-spacing: 0.10em;
      font: 9px monospace; text-align: left;
      padding: 8px 0 3px;
      transition: color 0.1s;
    }
    #dev-panel .dev-section-toggle:hover { color: #7af; }
    #dev-panel .dev-section-caret {
      display: inline-block; width: 10px;
      color: rgba(122,170,255,0.55);
    }
    #dev-panel .dev-section-toggle.collapsed { color: rgba(255,255,255,0.32); }
    #dev-panel .dev-row {
      display: flex; justify-content: space-between; align-items: center;
      width: 100%; box-sizing: border-box;
      background: rgba(255,255,255,0.04);
      border: 1px solid rgba(255,255,255,0.10);
      border-radius: 3px; color: rgba(255,255,255,0.78);
      font: 11px/1.5 monospace;
      padding: 3px 7px; margin-bottom: 3px;
      cursor: pointer; text-align: left;
      transition: background 0.1s, border-color 0.1s, color 0.1s;
    }
    #dev-panel .dev-row:hover { background: rgba(255,255,255,0.10); color: #fff; }
    #dev-panel .dev-viewer.active {
      background: rgba(122,170,255,0.18); border-color: #7af; color: #7af;
    }
    #dev-panel .dev-key {
      color: rgba(122,170,255,0.55); font-size: 9px;
      background: rgba(122,170,255,0.08);
      padding: 1px 5px; border-radius: 2px; min-width: 14px; text-align: center;
    }
    #dev-panel .dev-flag input { cursor: pointer; }
    #dev-panel .dev-flag-right {
      display: flex; gap: 6px; align-items: center;
    }
    /* Numeric-var rows: single-line label · slider · value · keychip.
       Each column is sized so the row stays one line at panel width 320px:
       label fixed (75px, ellipsis if longer), slider grows, value compact
       right-aligned readout, keychip (if any) tucked at the far right. */
    #dev-panel .dev-var-num {
      gap: 8px; padding: 4px 7px;
    }
    #dev-panel .dev-var-num .dev-var-label {
      flex: 0 0 75px;
      font-size: 10px; color: rgba(255,255,255,0.62);
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    #dev-panel .dev-var-num input[type=range] {
      flex: 1; min-width: 0; cursor: pointer; accent-color: #7af;
    }
    #dev-panel .dev-var-num .dev-var-val {
      flex: 0 0 auto; min-width: 36px;
      font-size: 10px; color: #7af; text-align: right;
    }
    #dev-panel .dev-var-enum select {
      background: rgba(255,255,255,0.05);
      color: rgba(255,255,255,0.78);
      border: 1px solid rgba(255,255,255,0.15);
      border-radius: 3px;
      font: 10px monospace; padding: 1px 3px;
    }
    #dev-panel .dev-var-color input[type=color] {
      background: none; border: 1px solid rgba(255,255,255,0.15);
      border-radius: 3px; cursor: pointer;
      width: 36px; height: 18px; padding: 0;
    }
    /* Readout blocks: multi-line live HTML inside a section. */
    #dev-panel .dev-readout {
      background: rgba(0,0,0,0.30);
      border: 1px solid rgba(255,255,255,0.08);
      border-radius: 3px;
      padding: 4px 7px;
      margin-bottom: 3px;
      color: rgba(255,255,255,0.72);
      font: 10px/1.55 monospace;
      white-space: pre-wrap;
    }
    #dev-panel .dev-readout .dbk { color: rgba(255,255,255,0.45); }
    #dev-panel .dev-readout .dbv { color: #7af; }
    #dev-panel .dev-readout-err {
      color: #f88; font-style: italic;
    }
    #dev-panel .dev-empty {
      color: rgba(255,255,255,0.30); font-style: italic;
      text-align: center; padding: 10px 0;
    }

    /* ── Dev toast overlay ────────────────────────────────────────────────── */
    /* Floating stack of fade-in/fade-out messages.  Anchored top-right just
       below where the Dev panel's default position would be — visible whether
       the panel is open or not.  Pointer-events: none so toasts never block
       canvas interaction.  Each toast is appended to #dev-toasts; JS handles
       the fade-out and removal. */
    #dev-toasts {
      position: fixed; top: 12px; left: 50%;
      transform: translateX(-50%);
      z-index: 70;                 /* above #dev-panel (60) so they're always visible */
      display: flex; flex-direction: column; gap: 4px;
      pointer-events: none;
      max-width: min(560px, 90vw);
    }
    .dev-toast {
      background: rgba(6,8,14,0.94);
      border: 1px solid rgba(255,255,255,0.12);
      border-left: 3px solid rgba(122,170,255,0.55);   /* default: info (blue) */
      border-radius: 4px;
      padding: 5px 10px;
      color: rgba(255,255,255,0.85);
      font: 11px/1.4 monospace;
      box-shadow: 0 4px 12px rgba(0,0,0,0.5);
      opacity: 0; transform: translateY(-6px);
      transition: opacity 0.18s ease-out, transform 0.18s ease-out;
      max-width: 100%;
      white-space: pre-wrap;
      word-break: break-word;
      pointer-events: auto;        /* allow click-to-dismiss */
      cursor: pointer;
    }
    .dev-toast.dev-toast-show {
      opacity: 1; transform: translateY(0);
    }
    .dev-toast.dev-toast-warn  { border-left-color: #fa6; color: #ffd9a3; }
    .dev-toast.dev-toast-error { border-left-color: #f77; color: #ffc0c0; }
    .dev-toast.dev-toast-ok    { border-left-color: #5eb; color: #c4ffe0; }

    /* ── Building inspector overlay ──────────────────────────────────────── */
    /* Follows mouse cursor when hovering a placed building.  Dumps the full
       buildingStates entry (every field, raw values) — separate from the
       in-game building info panel which is curated for players.  Toggled via
       Dev viewer 'buildingInspector'. */
    #dev-bi-overlay {
      position: fixed; left: 0; top: 0;
      background: rgba(6,8,14,0.96);
      border: 1px solid rgba(122,170,255,0.35);
      border-radius: 6px;
      padding: 5px 8px;
      color: #cde; font: 11px/1.45 monospace;
      z-index: 60;
      pointer-events: none;        /* never intercept canvas events */
      max-width: 320px;
      box-shadow: 0 6px 20px rgba(0,0,0,0.5);
      user-select: none; -webkit-user-select: none;
    }
    #dev-bi-overlay.dev-hidden { display: none; }
    .dev-bi-header {
      color: #7af; font-weight: bold; letter-spacing: 0.06em;
      padding-bottom: 3px; margin-bottom: 4px;
      border-bottom: 1px solid rgba(122,170,255,0.20);
      font-size: 11px;
    }
    .dev-bi-row {
      display: flex; gap: 8px; align-items: baseline;
      font-size: 10px;
    }
    .dev-bi-k {
      flex: 0 0 90px;
      color: rgba(255,255,255,0.45);
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .dev-bi-v {
      flex: 1 1 auto; min-width: 0;
      color: #efa;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .dev-bi-empty {
      color: rgba(255,255,255,0.35); font-style: italic;
    }

    /* ── Surface material viewer (B) ──────────────────────────────────────── */
    /* Equirectangular projection of moon material classification.
       Same lat/long convention as the HUD: lat = asin(y), lon = atan2(x, z). */
    #surface-viz {
      position: fixed; top: 50%; left: 50%;
      transform: translate(-50%, -50%);
      background: rgba(0,0,0,0.92);
      border: 1px solid rgba(255,255,255,0.12);
      border-radius: 8px;
      padding: 0.6rem 0.75rem 0.5rem;
      z-index: 50; pointer-events: none;
      display: none;
    }
    #surface-viz.open { display: block; }
    #surface-viz-title {
      color: rgba(255,255,255,0.28); font: 10px/2 monospace;
      letter-spacing: 0.12em; text-align: center;
    }
    #surface-viz-grid {
      display: grid;
      grid-template-columns: 22px 1fr;
      grid-template-rows: 1fr 14px;
      gap: 0;
    }
    #surface-viz-ylabel {
      grid-column: 1; grid-row: 1;
      display: flex; flex-direction: column; justify-content: space-between;
      color: rgba(255,255,255,0.22); font: 9px monospace;
      padding: 2px 4px 2px 0; text-align: right;
    }
    #surface-viz-canvas {
      grid-column: 2; grid-row: 1;
      display: block; border-radius: 3px;
      image-rendering: pixelated;
      width: 600px; height: 300px;
    }
    #surface-viz-xlabel {
      grid-column: 2; grid-row: 2;
      display: flex; justify-content: space-between;
      color: rgba(255,255,255,0.22); font: 9px monospace;
      padding: 3px 0 0;
    }
    #surface-viz-legend {
      display: flex; gap: 4px; margin-top: 0.5rem; flex-wrap: wrap;
      justify-content: center;
    }
    #surface-viz-legend .sv-item {
      display: flex; align-items: center; gap: 4px;
      color: rgba(255,255,255,0.55); font: 10px/1 monospace;
      padding: 3px 6px;
      background: rgba(255,255,255,0.04);
      border: 1px solid rgba(255,255,255,0.10);
      border-radius: 3px;
    }
    #surface-viz-legend .sv-swatch {
      width: 10px; height: 10px; border-radius: 2px;
      border: 1px solid rgba(255,255,255,0.15);
    }

    /* Perf readout palette — colour spans emitted by perfMon.buildHTML(),
       rendered inside the Dev panel's .dev-readout block (whose monospace
       font + spacing rules are defined alongside the rest of #dev-panel). */
    .ph  { color: rgba(255,255,255,0.3); font-size: 10px; letter-spacing:.08em; }
    .pk  { color: #7af; }
    .pv  { color: #efa; }
    .bar { color: #4a8; }
    .hi  { color: #fa6; }

    /* ── Static loading backdrop (sits behind auth, fades when game starts) ── */
    #loading-backdrop {
      position: fixed; inset: 0; z-index: 50;
      background: url('loading-bg.jpg') center/cover no-repeat #0f0700;
      pointer-events: none;
      transition: opacity 1.0s ease;
    }

    /* ── Guest-conflict modal ─────────────────────────────────────────────── */
    #guest-conflict-modal {
      position: fixed; inset: 0; z-index: 400;
      background: rgba(6,8,14,0.72);
      display: flex; align-items: center; justify-content: center;
    }
    .gcm-card {
      background: rgba(18,22,38,0.99);
      border: 1px solid rgba(255,255,255,0.12);
      border-radius: 16px; padding: 2rem 2.25rem;
      display: flex; flex-direction: column; gap: 0.85rem;
      max-width: 380px; width: 90%;
    }
    .gcm-icon  { font-size: 2rem; text-align: center; }
    .gcm-title {
      color: #e8eaf0; font: 700 18px/1.3 system-ui, sans-serif;
      letter-spacing: -0.02em; margin: 0; text-align: center;
    }
    .gcm-colony {
      color: rgba(255,200,90,0.9); font: 600 14px/1.4 system-ui, sans-serif;
      text-align: center; margin: 0;
    }
    .gcm-body  {
      color: rgba(255,255,255,0.5); font: 12px/1.65 monospace;
      margin: 0; text-align: center;
    }
    .gcm-actions { display: flex; flex-direction: column; gap: 0.55rem; margin-top: 0.25rem; }
    .gcm-btn-confirm {
      background: rgba(190,55,35,0.82); color: #fff;
      border: 1px solid rgba(255,100,80,0.35); border-radius: 6px;
      padding: 0.65rem 1.25rem; cursor: pointer;
      font: 500 13px/1.5 system-ui, sans-serif; width: 100%;
      transition: background 0.15s;
    }
    .gcm-btn-confirm:hover { background: rgba(215,65,45,0.95); }
    .gcm-btn-cancel {
      background: none; border: 1px solid rgba(255,255,255,0.12); border-radius: 6px;
      color: rgba(255,255,255,0.55); padding: 0.65rem 1.25rem; cursor: pointer;
      font: 500 13px/1.5 system-ui, sans-serif; width: 100%;
      transition: all 0.15s;
    }
    .gcm-btn-cancel:hover { background: rgba(255,255,255,0.06); color: rgba(255,255,255,0.85); }

    /* ── Auth overlay ─────────────────────────────────────────────────────── */
    #auth-overlay {
      position: fixed; inset: 0; z-index: 200;
      background: rgba(6,8,14,0.55);
      display: flex; align-items: center; justify-content: center;
    }
    #auth-card {
      background: rgba(18,22,38,0.98);
      border: 1px solid rgba(255,255,255,0.1);
      border-radius: 16px; padding: 2.5rem 2.75rem;
      display: flex; flex-direction: column; align-items: center; gap: 1.1rem;
      max-width: 340px; width: 90%;
    }
    #auth-title {
      color: #e8eaf0; font: 700 22px/1.2 system-ui, sans-serif;
      letter-spacing: -0.02em; margin: 0;
    }
    #auth-subtitle {
      color: rgba(255,255,255,0.38); font: 13px/1.6 monospace;
      margin: 0; text-align: center;
    }
    #auth-google-btn {
      display: flex; align-items: center; justify-content: center; gap: 10px;
      background: #fff; color: #3c4043;
      border: 1px solid #dadce0; border-radius: 6px;
      padding: 0.65rem 1.25rem; cursor: pointer;
      font: 500 14px/1.5 system-ui, sans-serif;
      width: 100%; transition: background 0.15s;
    }
    #auth-google-btn:hover { background: #f8f9fa; }
    #auth-google-btn:disabled { opacity: 0.6; cursor: default; }
    #auth-google-btn img { width: 18px; height: 18px; }
    #auth-guest-btn {
      background: none; border: none; cursor: pointer;
      color: rgba(255,255,255,0.35); font: 12px/1.5 monospace;
      padding: 0.1rem 0; transition: color 0.15s;
    }
    #auth-guest-btn:hover { color: rgba(255,255,255,0.65); }
    /* hint-mode (returning user) */
    .auth-hint-name {
      color: #e8eaf0; font: 600 16px/1.3 system-ui, sans-serif;
      letter-spacing: -0.01em;
    }
    .auth-hint-email { color: rgba(255,255,255,0.4); font: 12px/1.4 monospace; }
    .auth-continue-btn {
      display: flex; align-items: center; justify-content: center;
      background: #4285f4; color: #fff;
      border: none; border-radius: 6px;
      padding: 0.65rem 1.25rem; cursor: pointer;
      font: 500 14px/1.5 system-ui, sans-serif;
      width: 100%; transition: background 0.15s;
    }
    .auth-continue-btn:hover { background: #3367d6; }
    .auth-continue-btn:disabled { opacity: 0.6; cursor: default; }
    .auth-switch-btn {
      background: none; border: none;
      color: rgba(255,255,255,0.38); font: 12px/1.5 monospace;
      cursor: pointer; padding: 0; text-decoration: underline;
      transition: color 0.15s;
    }
    .auth-switch-btn:hover { color: rgba(255,255,255,0.7); }
    #auth-status-msg { color: rgba(255,255,255,0.35); font: 11px/1.5 monospace; }

    /* ── Hardware-acceleration warning banner ─────────────────────────────── */
    #hw-warn {
      position: fixed; bottom: 1rem; left: 50%; transform: translateX(-50%);
      z-index: 600;
      display: flex; align-items: center; gap: 0.75rem;
      background: rgba(200,90,20,0.92); backdrop-filter: blur(6px);
      border: 1px solid rgba(255,160,60,0.5);
      border-radius: 8px; padding: 0.6rem 1rem;
      font: 12px/1.4 monospace; color: #ffe8cc;
      max-width: min(560px, 90vw);
      box-shadow: 0 4px 24px rgba(0,0,0,0.6);
      transition: opacity 0.4s ease;
    }
    #hw-warn.hw-warn-hide { opacity: 0; pointer-events: none; }
    #hw-warn-icon { font-size: 1.3em; flex-shrink: 0; }
    #hw-warn-text { flex: 1; }
    #hw-warn-text a { color: #ffd09a; }
    #hw-warn-dismiss {
      background: none; border: 1px solid rgba(255,200,120,0.4);
      border-radius: 4px; color: #ffe8cc; cursor: pointer;
      font: inherit; padding: 2px 8px; flex-shrink: 0;
    }
    #hw-warn-dismiss:hover { background: rgba(255,255,255,0.1); }

    /* ── User bar (top-right corner) ──────────────────────────────────────── */
    #user-bar {
      position: fixed; top: 0.75rem; right: 1rem;
      align-items: center; gap: 0.5rem;
      z-index: 20; pointer-events: auto;
      user-select: none;
      display: none;
    }
    .ub-btn {
      background: rgba(255,255,255,0.07);
      border: 1px solid rgba(255,255,255,0.12);
      border-radius: 5px; color: rgba(255,255,255,0.6);
      font: 11px/1 monospace; padding: 4px 8px; cursor: pointer;
      outline: none; user-select: none; -webkit-user-select: none;
      transition: background 0.12s, color 0.12s;
    }
    .ub-btn:hover { background: rgba(255,255,255,0.14); color: #fff; }
    #save-status {
      position: fixed;
      bottom: calc(0.75rem + 76px);   /* above the bottom toolbar (toolbar ≈ 66px tall + 12px margin) */
      left: 50%; transform: translateX(-50%);
      font: 10px/1 monospace; color: #6f6;
      opacity: 0; transition: opacity 0.4s;
      pointer-events: none;
      z-index: 25;
    }
    /* ── Offline-sim toast ────────────────────────────────────────────────── */
    #offline-toast {
      position: fixed; top: 40%; left: 50%;
      transform: translateX(-50%) translateY(-50%);
      background: rgba(6,8,14,0.90);
      border: 1px solid rgba(255,255,255,0.09); border-radius: 10px;
      color: #ccc; font: 11px/1.5 monospace;
      padding: 0.6rem 1.1rem; z-index: 100;
      pointer-events: none; white-space: nowrap;
      opacity: 0;
    }
    @keyframes ot-riseout {
      /* hold fully visible for 5 s (5/7 ≈ 71.4%), then rise + fade over 2 s */
      0%     { opacity: 1; transform: translateX(-50%) translateY(-50%); }
      71.4%  { opacity: 1; transform: translateX(-50%) translateY(-50%); }
      100%   { opacity: 0; transform: translateX(-50%) translateY(calc(-50% - 64px)); }
    }
    #offline-toast.ot-visible {
      animation: ot-riseout 7s ease-in forwards;
    }

    /* ── Loading overlay ─────────────────────────────────────────────────── */
    #loading-overlay {
      position: fixed; inset: 0; z-index: 500;
      background:
        linear-gradient(to bottom,
          rgba(6,8,14,0.15) 0%,
          rgba(6,8,14,0.55) 55%,
          rgba(6,8,14,0.95) 78%
        ),
        url('loading-bg.jpg') center/cover no-repeat #0f0700;
      display: flex; flex-direction: column;
      justify-content: flex-end; align-items: center;
      padding-bottom: 9vh;
      transition: opacity 0.75s ease;
      pointer-events: all;
    }
    #loading-overlay.lo-fadeout { opacity: 0; pointer-events: none; }
    #loading-panel {
      width: 300px; display: flex; flex-direction: column; gap: 0.6rem;
    }
    .lo-bar-row { display: flex; flex-direction: column; gap: 0.3rem; }
    .lo-label {
      color: rgba(255,255,255,0.32); font: 10px/1 monospace;
      letter-spacing: 0.10em; text-transform: uppercase;
    }
    .lo-track {
      width: 100%; height: 2px;
      background: rgba(255,255,255,0.07); border-radius: 1px; overflow: hidden;
    }
    .lo-fill {
      height: 100%; width: 0%;
      background: rgba(122,175,255,0.65); border-radius: 1px;
      transition: width 0.28s ease;
    }
    #lo-tip {
      margin-top: 0.85rem;
      color: rgba(255,255,255,0.22); font: 11px/1.6 monospace;
      text-align: center; min-height: 2.4em;
      transition: opacity 0.45s ease;
    }
    #lo-tip.lo-tip-fading { opacity: 0; }

    /* ── Settings panel ───────────────────────────────────────────────────── */
    /* ── Achievements panel ─────────────────────────────────────────────── */
    #achievements-panel {
      position: fixed; top: 50%; left: 50%;
      transform: translate(-50%, -50%);
      background: rgba(6,8,14,0.96);
      border: 1px solid rgba(255,255,255,0.09); border-radius: 10px;
      color: #ccc; font: 12px/1.5 monospace;
      width: 360px; z-index: 50; pointer-events: auto;
      user-select: none; -webkit-user-select: none;
      display: flex; flex-direction: column;
      max-height: 80vh;
      overflow: hidden;
    }
    #achievements-panel.ach-hidden { display: none; }
    #ach-header {
      display: flex; align-items: center; justify-content: space-between;
      padding: 0.55rem 0.75rem;
      border-bottom: 1px solid rgba(255,255,255,0.07);
      font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase;
      color: rgba(255,255,255,0.45);
      flex-shrink: 0;
    }
    #ach-close-btn {
      background: none; border: none; color: rgba(255,255,255,0.3);
      cursor: pointer; font: 15px/1 monospace; padding: 0 2px;
      outline: none;
    }
    #ach-close-btn:hover { color: #fff; }
    #ach-body {
      padding: 0.65rem 0.85rem 0.85rem;
      flex: 1 1 auto;
      overflow-y: auto;
      min-height: 0;
    }
    .ach-empty {
      color: rgba(255,255,255,0.40);
      font: 11px/1.5 monospace;
      text-align: center;
      padding: 1.5rem 0.5rem;
    }
    /* Achievements panel inherits the unified scrollbar look. */
    #ach-body::-webkit-scrollbar { width: 8px; height: 8px; }
    #ach-body::-webkit-scrollbar-track { background: transparent; }
    #ach-body::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.10); border-radius: 4px; }
    #ach-body::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.22); }

    #settings-panel {
      position: fixed; top: 50%; right: 1.25rem;
      transform: translateY(-50%);
      background: rgba(6,8,14,0.96);
      border: 1px solid rgba(255,255,255,0.09); border-radius: 10px;
      color: #ccc; font: 12px/1.5 monospace;
      width: 350px; z-index: 50; pointer-events: auto;
      user-select: none; -webkit-user-select: none;
      /* Flex column so #sp-body can flex-fill the resized panel and scroll. */
      display: flex; flex-direction: column;
      max-height: 90vh;  /* default cap when content tall + viewport short */
      overflow: hidden;
    }
    /* Editable inputs inside the settings panel still need text selection. */
    #settings-panel input[type=text] { user-select: text; -webkit-user-select: text; }
    #settings-panel.sp-hidden { display: none; }
    #sp-header {
      display: flex; align-items: center; justify-content: space-between;
      padding: 0.55rem 0.75rem;
      border-bottom: 1px solid rgba(255,255,255,0.07);
      font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase;
      color: rgba(255,255,255,0.45);
    }
    #sp-close-btn {
      background: none; border: none; color: rgba(255,255,255,0.3);
      cursor: pointer; font: 15px/1 monospace; padding: 0 2px;
    }
    #sp-close-btn:hover { color: #fff; }
    #sp-body {
      padding: 0.5rem 0.75rem 0.75rem;
      display: flex; flex-direction: column; gap: 0.1rem;
      flex: 1 1 auto;
      overflow-y: auto;
      min-height: 0;  /* required for flex children to shrink below content height */
    }
    .sp-section-hdr {
      color: rgba(255,255,255,0.28); font-size: 10px;
      letter-spacing: 0.1em; text-transform: uppercase;
      margin: 0.55rem 0 0.25rem;
    }
    .sp-toggle-row {
      display: flex; align-items: center; justify-content: space-between;
      padding: 0.3rem 0; cursor: pointer; gap: 0.5rem;
      color: rgba(255,255,255,0.7);
    }
    .sp-toggle-row input[type=checkbox] { accent-color: #7af; cursor: pointer; }
    .sp-select-row {
      display: flex; align-items: center; justify-content: space-between;
      padding: 0.3rem 0; gap: 0.5rem; color: rgba(255,255,255,0.7);
    }
    .sp-select-row select {
      background: rgba(255,255,255,0.07); border: 1px solid rgba(255,255,255,0.14);
      border-radius: 4px; color: #ccc; font: 11px/1.5 monospace;
      padding: 2px 6px; cursor: pointer; outline: none;
      color-scheme: dark;  /* dark native dropdown popup, matches social select */
    }
    .sp-select-row select:focus { border-color: rgba(120,170,255,0.45); }
    .sp-select-row select option {
      background: #0a0e16; color: #ccc;
    }
    .sp-keybind-row {
      display: flex; align-items: center; justify-content: space-between;
      padding: 0.2rem 0; color: rgba(255,255,255,0.5);
    }
    .sp-keybind-row kbd {
      background: rgba(255,255,255,0.07);
      border: 1px solid rgba(255,255,255,0.14); border-radius: 4px;
      padding: 1px 6px; font: 11px/1.6 monospace; color: #7af;
    }
    .sp-input-row { display: flex; align-items: center; gap: 6px; padding: 0.3rem 0; }
    .sp-input-row input[type=text] {
      flex: 1; background: rgba(255,255,255,0.07);
      border: 1px solid rgba(255,255,255,0.14); border-radius: 4px;
      color: #ccc; font: 11px/1.5 monospace; padding: 3px 7px;
      outline: none;
    }
    .sp-input-row input[type=text]::placeholder { color: rgba(255,255,255,0.22); }
    .sp-input-row input[type=text]:focus { border-color: rgba(120,170,255,0.45); }
    .sp-input-row button {
      background: rgba(255,255,255,0.07);
      border: 1px solid rgba(255,255,255,0.14); border-radius: 4px;
      color: rgba(255,255,255,0.6); font: 11px/1.5 monospace;
      padding: 3px 9px; cursor: pointer; transition: background 0.12s;
    }
    .sp-input-row button:hover { background: rgba(255,255,255,0.14); color: #fff; }
    /* Extra breathing room between the "Display Name" label and the input. */
    .sp-name-row > span { margin-right: 10px; }

    /* ── Social panel ─────────────────────────────────────────────────────── */
    #social-panel {
      /* Anchored to top so switching tabs doesn't make the panel jump y-position
         when content height changes (was previously top:50% + translateY). */
      position: fixed; top: 5rem; right: 1.25rem;
      background: rgba(6,8,14,0.96);
      border: 1px solid rgba(255,255,255,0.09); border-radius: 10px;
      color: #ccc; font: 12px/1.5 monospace;
      width: 320px; max-height: calc(100vh - 6rem);
      display: flex; flex-direction: column;
      z-index: 50; pointer-events: auto;
      user-select: none; -webkit-user-select: none;
    }
    /* Inputs inside the social panel still need text selection (typing). */
    #social-panel input[type=text] { user-select: text; -webkit-user-select: text; }
    #social-panel.sp-hidden { display: none; }
    #soc-header {
      display: flex; align-items: center; justify-content: space-between;
      padding: 0.55rem 0.75rem;
      border-bottom: 1px solid rgba(255,255,255,0.07);
      font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase;
      color: rgba(255,255,255,0.45);
      flex-shrink: 0;
    }
    #soc-close-btn {
      background: none; border: none; color: rgba(255,255,255,0.3);
      cursor: pointer; font: 15px/1 monospace; padding: 0 2px;
    }
    #soc-close-btn:hover { color: #fff; }
    #soc-tabs {
      display: flex; gap: 0;
      padding: 0 0.5rem;
      border-bottom: 1px solid rgba(255,255,255,0.07);
      flex-shrink: 0;
    }
    .soc-tab {
      position: relative;
      background: none; border: none;
      padding: 8px 18px;
      color: rgba(255,255,255,0.40);
      font: 11px/1 monospace; letter-spacing: 0.08em;
      text-transform: uppercase;
      cursor: pointer;
      border-bottom: 2px solid transparent;
      margin-bottom: -1px;  /* overlap the section's bottom border */
      transition: color 0.12s, border-color 0.12s;
      outline: none;        /* no focus box on click — active state already shows selection */
    }
    .soc-tab:hover { color: rgba(255,255,255,0.7); }
    .soc-tab-active {
      color: #ffd590;
      border-bottom-color: #ffd590;
    }
    /* Strip default browser focus outline from custom buttons across the UI.
       Each carries its own hover/active visual treatment so the OS ring is
       redundant and looks cluttered. */
    .bt-btn, .soc-tab, .bp-tab, .soc-mini-btn, .soc-input-row button, .soc-row-btn,
    .soc-leave-btn, #vb-return-btn, .dnm-btn,
    #sp-colony-save-btn, #sp-close-btn, #soc-close-btn, #bp-close-btn,
    #user-bar .ub-btn, #auth-google-btn, #auth-guest-btn {
      outline: none;
    }
    .bt-btn::-moz-focus-inner, .soc-tab::-moz-focus-inner, .bp-tab::-moz-focus-inner,
    .soc-mini-btn::-moz-focus-inner, .soc-input-row button::-moz-focus-inner,
    .soc-row-btn::-moz-focus-inner, .soc-leave-btn::-moz-focus-inner,
    #vb-return-btn::-moz-focus-inner, .dnm-btn::-moz-focus-inner {
      border: 0;
    }
    .soc-tab-badge {
      display: none;
      background: #f55; color: #fff;
      font: bold 9px/1 monospace;
      border-radius: 7px; padding: 1px 5px;
      margin-left: 4px; vertical-align: middle;
    }
    .soc-tab-badge.visible { display: inline-block; }
    .soc-tab-content { display: flex; flex-direction: column; }
    #soc-body {
      padding: 0.25rem 0.75rem 0.75rem;
      overflow-y: auto;
      display: flex; flex-direction: column;
    }
    .soc-section { margin-bottom: 0.35rem; }
    .soc-section-hdr {
      color: rgba(255,255,255,0.28); font-size: 10px;
      letter-spacing: 0.1em; text-transform: uppercase;
      margin: 0.55rem 0 0.25rem;
      display: flex; align-items: center; justify-content: space-between;
    }
    .soc-count {
      color: rgba(255,200,140,0.55);
      font-size: 9px; letter-spacing: 0;
    }
    .soc-mycode-row {
      display: flex; align-items: stretch; gap: 6px;
      padding: 0.3rem 0;
    }
    .soc-code {
      flex: 1;
      background: rgba(255,255,255,0.05);
      border: 1px solid rgba(255,255,255,0.10);
      border-radius: 4px;
      padding: 4px 9px;
      color: rgba(255,200,140,0.95);
      font: 13px/1.4 monospace; letter-spacing: 0.05em;
      text-align: center;
      display: flex; align-items: center; justify-content: center;
      /* Display-only — no text-cursor on click; copy button is the canonical way to copy. */
      cursor: default;
      user-select: none; -webkit-user-select: none;
    }
    /* Other readonly display text in the social panel — no caret on click. */
    .soc-row-name, .soc-row-code,
    .soc-system-name, .soc-system-meta, .soc-system-empty,
    .soc-list-empty {
      cursor: default;
      user-select: none; -webkit-user-select: none;
    }
    .soc-mini-btn {
      background: rgba(255,255,255,0.07);
      border: 1px solid rgba(255,255,255,0.14); border-radius: 4px;
      color: rgba(255,255,255,0.6);
      padding: 0 9px; cursor: pointer; transition: background 0.12s, color 0.12s;
      display: flex; align-items: center; justify-content: center;
      min-width: 32px;
    }
    .soc-mini-btn svg { width: 16px; height: 16px; flex-shrink: 0; }
    .soc-mini-btn:hover { background: rgba(255,255,255,0.14); color: #fff; }
    .soc-toggle-row {
      display: flex; align-items: center; justify-content: space-between;
      padding: 0.3rem 0; cursor: pointer; gap: 0.5rem;
      color: rgba(255,255,255,0.7);
    }
    .soc-toggle-row input[type=checkbox] { accent-color: #7af; cursor: pointer; }
    .soc-input-row { display: flex; align-items: center; gap: 6px; padding: 0.3rem 0; }
    .soc-input-row input[type=text] {
      flex: 1; background: rgba(255,255,255,0.07);
      border: 1px solid rgba(255,255,255,0.14); border-radius: 4px;
      color: #ccc; font: 11px/1.5 monospace; padding: 3px 7px;
      outline: none; letter-spacing: 0.05em;
    }
    .soc-input-row input[type=text]::placeholder { color: rgba(255,255,255,0.22); }
    .soc-input-row input[type=text]:focus { border-color: rgba(120,170,255,0.45); }
    .soc-input-row button {
      background: rgba(255,255,255,0.07);
      border: 1px solid rgba(255,255,255,0.14); border-radius: 4px;
      color: rgba(255,255,255,0.6); font: 11px/1.5 monospace;
      padding: 3px 9px; cursor: pointer; transition: background 0.12s;
    }
    .soc-input-row button:hover { background: rgba(255,255,255,0.14); color: #fff; }
    .soc-status-msg {
      font: 10px/1.4 monospace;
      padding: 2px 0; min-height: 12px;
    }
    .soc-msg-error { color: #f88; }
    .soc-msg-ok    { color: #6f9; }
    .soc-list { display: flex; flex-direction: column; gap: 3px; }
    .soc-list-empty {
      color: rgba(255,255,255,0.22);
      font: 10px/1.5 monospace; font-style: italic;
      padding: 4px 0;
    }
    /* Scrollable friends list — caps height so the rest of the tab stays visible. */
    .soc-list-scroll {
      max-height: 320px;
      overflow-y: auto;
      padding-right: 2px;  /* leave space for the scrollbar so rows don't shift */
    }
    /* (.soc-list-scroll scrollbar styling inherits from the unified rule above.) */
    /* Expandable Add-Friend area, revealed when ➕ is active. */
    .soc-add-expand { margin-top: 0.4rem; }
    /* ➕ button highlighted while the expand area is open. */
    .soc-mini-btn.soc-add-active {
      background: rgba(126,218,156,0.18);
      border-color: rgba(126,218,156,0.40);
      color: #aef0c0;
    }
    .soc-row {
      display: flex; align-items: center; justify-content: space-between;
      gap: 6px;
      padding: 5px 7px;
      background: rgba(255,255,255,0.025);
      border: 1px solid rgba(255,255,255,0.06);
      border-radius: 4px;
    }
    .soc-row-info { flex: 1; min-width: 0; }
    .soc-row-name {
      color: rgba(255,255,255,0.75);
      font: 11px/1.3 monospace;
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    .soc-row-code {
      color: rgba(255,200,140,0.45);
      font: 9px/1.2 monospace; letter-spacing: 0.05em;
    }
    .soc-row-actions { display: flex; gap: 3px; flex-shrink: 0; }
    .soc-row-btn {
      background: rgba(255,255,255,0.05);
      border: 1px solid rgba(255,255,255,0.10); border-radius: 3px;
      color: rgba(255,255,255,0.55); font: 10px/1.3 monospace;
      padding: 2px 6px; cursor: pointer; transition: background 0.12s;
    }
    .soc-row-btn:hover { background: rgba(255,255,255,0.12); color: #fff; }
    .soc-btn-accept { color: #7eda9c; border-color: rgba(126,218,156,0.25); }
    .soc-btn-accept:hover { background: rgba(126,218,156,0.15); color: #aef0c0; }
    .soc-btn-visit  { color: #8ec8ff; border-color: rgba(142,200,255,0.30); }
    .soc-btn-visit:hover  { background: rgba(142,200,255,0.15); color: #b8dcff; }
    .soc-btn-kick   { color: #d97070; border-color: rgba(217,112,112,0.25); }
    .soc-btn-kick:hover   { background: rgba(217,112,112,0.15); color: #f0a0a0; }

    /* System section content */
    .soc-system-info {
      padding: 5px 8px;
      background: rgba(255,200,140,0.05);
      border: 1px solid rgba(255,200,140,0.18);
      border-radius: 4px;
    }
    .soc-system-name {
      color: #ffd590; font: 12px/1.3 monospace; font-weight: bold;
    }
    .soc-system-meta {
      color: rgba(255,255,255,0.40); font: 10px/1.4 monospace;
    }
    .soc-system-empty {
      color: rgba(255,255,255,0.45); font: 10px/1.5 monospace;
      padding: 0.2rem 0 0.4rem;
    }
    .soc-input-row select {
      flex: 1; background: rgba(255,255,255,0.07);
      border: 1px solid rgba(255,255,255,0.14); border-radius: 4px;
      color: #ccc; font: 11px/1.5 monospace; padding: 3px 6px;
      outline: none; cursor: pointer;
      color-scheme: dark;  /* tells the browser to use dark native UI for the dropdown popup */
    }
    .soc-input-row select:focus { border-color: rgba(120,170,255,0.45); }
    .soc-input-row select option {
      background: #0a0e16; color: #ccc;
    }
    .soc-leave-btn {
      width: 100%; margin-top: 0.4rem;
      background: rgba(217,112,112,0.08);
      border: 1px solid rgba(217,112,112,0.25); border-radius: 4px;
      color: #d97070; font: 11px/1.4 monospace;
      padding: 5px 9px; cursor: pointer; transition: background 0.12s, color 0.12s;
    }
    .soc-leave-btn:hover { background: rgba(217,112,112,0.18); color: #f0a0a0; }
    .soc-btn-decline, .soc-btn-remove, .soc-btn-withdraw {
      color: #d97070; border-color: rgba(217,112,112,0.25);
    }
    .soc-btn-decline:hover, .soc-btn-remove:hover, .soc-btn-withdraw:hover {
      background: rgba(217,112,112,0.15); color: #f0a0a0;
    }

    /* Social button badge */
    #bt-social-badge {
      position: absolute; top: 2px; right: 4px;
      background: #f55; color: #fff;
      font: bold 9px/1 monospace;
      border-radius: 8px; padding: 2px 5px;
      display: none; pointer-events: none;
    }
    #bt-social-badge.visible { display: inline-block; }

    /* Display-name prompt (first sign-in if colonyName empty) */
    #display-name-modal {
      position: fixed; inset: 0;
      background: rgba(2,4,8,0.78);
      display: none; align-items: center; justify-content: center;
      z-index: 200;
    }
    #display-name-modal.visible { display: flex; }
    .dnm-card {
      background: #0a0e16;
      border: 1px solid rgba(255,255,255,0.10);
      border-radius: 12px;
      padding: 1.25rem 1.5rem;
      width: 320px;
      font: 12px/1.5 monospace;
      color: #ccc;
    }
    .dnm-title { font-size: 14px; color: #fff; margin: 0 0 0.5rem; }
    .dnm-body  { color: rgba(255,255,255,0.55); margin: 0 0 0.85rem; }
    .dnm-input {
      width: 100%; background: rgba(255,255,255,0.07);
      border: 1px solid rgba(255,255,255,0.14); border-radius: 4px;
      color: #ccc; font: 12px/1.5 monospace; padding: 6px 9px;
      outline: none; box-sizing: border-box;
    }
    .dnm-input:focus { border-color: rgba(120,170,255,0.45); }
    .dnm-actions { display: flex; gap: 8px; margin-top: 0.85rem; justify-content: flex-end; }
    .dnm-btn {
      background: rgba(255,255,255,0.07);
      border: 1px solid rgba(255,255,255,0.14); border-radius: 4px;
      color: rgba(255,255,255,0.7); font: 11px/1.5 monospace;
      padding: 5px 14px; cursor: pointer; transition: background 0.12s;
    }
    .dnm-btn:hover { background: rgba(255,255,255,0.14); color: #fff; }
    .dnm-btn-primary { color: #8ec8ff; border-color: rgba(142,200,255,0.30); }
    .dnm-btn-primary:hover { background: rgba(142,200,255,0.15); color: #b8dcff; }

    /* ── Orbital-shift fade overlay (Phase 3b) ───────────────────────────── */
    #orbit-fade {
      position: fixed; inset: 0;
      background: #000;
      opacity: 0; pointer-events: none;
      transition: opacity 0.45s ease;
      z-index: 90;
    }

    /* ── Viewer mode banner (Phase 2) ─────────────────────────────────────── */
    #viewer-banner {
      position: fixed; top: 12px; left: 50%; transform: translateX(-50%);
      display: none; align-items: center; gap: 12px;
      background: rgba(40,28,8,0.92);
      border: 1px solid rgba(255,200,140,0.35);
      border-radius: 10px;
      padding: 7px 14px;
      font: 12px/1.4 monospace;
      color: rgba(255,220,170,0.95);
      z-index: 60; pointer-events: auto;
      box-shadow: 0 2px 12px rgba(0,0,0,0.45);
    }
    #viewer-banner.visible { display: flex; }
    .vb-icon { width: 16px; height: 16px; display: inline-flex; }
    .vb-icon svg { width: 100%; height: 100%; }
    .vb-text { color: rgba(255,220,170,0.85); }
    .vb-name { color: #ffd590; font-weight: bold; }
    #vb-return-btn {
      background: rgba(255,200,140,0.12);
      border: 1px solid rgba(255,200,140,0.35);
      border-radius: 4px;
      color: #ffd590; font: 11px/1.4 monospace;
      padding: 4px 10px; cursor: pointer; transition: background 0.12s;
    }
    #vb-return-btn:hover { background: rgba(255,200,140,0.22); color: #fff; }