  :root {
    /* Airflow chrome palette — warm charcoal + ice-blue, shared with css/tokens.css
       (--app-* dark). Only the editor chrome re-skins; the drawing canvas and the
       semantic duct colours below stay as-is. */
    --bg-app: #0e0f12;
    --bg-sidebar: #15171c;
    --bg-card: #1b1e25;
    --bg-card-hover: #23272f;
    --bg-canvas: #f0f2f7;
    --bg-toolbar: #15171c;
    --bg-modal: #1b1e25;
    --bg-input: #0e0f12;

    --text-primary: #f2f4f8;
    --text-secondary: #aeb6c4;
    --text-muted: #8b95a7;

    --accent: #33b1ff;
    --accent-hover: #5cc0ff;
    --accent-fg: #04121d;   /* readable ink on the bright ice-blue accent */
    --accent-light: rgba(51,177,255,0.14);
    --accent-glow: rgba(51,177,255,0.28);

    /* THE COLOUR LAW, mirrored for CSS. These four exist so chrome that labels a
       duct type (the layer swatches, the legend, the heatmap key) can follow the
       drawing without keeping its own copy. They were still the RETIRED palette,
       so the Design panel showed an orange Return and a green Fresh beside a
       drawing that had moved to red and burnt orange. Keep byte-identical to
       physics.js DUCT_COLORS; ai.js applyDuctColors overwrites them inline when
       a user picks an accessibility preset, which is why swatches should read
       these rather than hard-code anything. */
    --supply: #1493e6;
    --return-color: #e23b3b;
    --fresh: #b45309;
    --exhaust: #6b7585;

    --border: rgba(255,255,255,0.07);
    --border-input: rgba(255,255,255,0.1);
    --border-focus: rgba(51,177,255,0.5);

    --radius-sm: 6px;
    --radius-md: 8px;
    --radius-lg: 12px;
    --radius-xl: 16px;

    /* Refined Graphite: layered depth with a crisp top-light edge */
    --edge-light: inset 0 1px 0 rgba(255,255,255,0.06);
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.45), var(--edge-light);
    --shadow-md: 0 8px 24px rgba(0,0,0,0.48), var(--edge-light);
    --shadow-lg: 0 18px 44px rgba(0,0,0,0.58), var(--edge-light);
    --border-strong: rgba(255,255,255,0.12);

    /* Signature accent extras (base hue tracks the Airflow ice-blue accent = #33b1ff) */
    --accent-soft:  rgba(51,177,255,0.14);
    --accent-edge:  rgba(51,177,255,0.45);
    --accent-line:  linear-gradient(90deg, #33b1ff, #5cc0ff);

    --brand-primary:   #33b1ff;
    --brand-secondary: #5cc0ff;
    --brand-accent:    #1493e6;

    --surface-hover: #23272f;

    --font: 'Sora', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, 'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji', sans-serif;
    --font-mono: 'JetBrains Mono','SF Mono','SFMono-Regular',ui-monospace,Menlo,Consolas,monospace;
    --spring: cubic-bezier(.2,.8,.2,1);
    --transition: 0.15s ease;
  }

  * { box-sizing: border-box; margin: 0; padding: 0; }
  /* Keyboard navigation focus ring — only fires on keyboard, not mouse */
  :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
  /* Elements with custom focus styles suppress the default ring */
  .prop-input:focus-visible, .duct-width-select:focus-visible,
  .api-key-input:focus-visible, .unit-search:focus-visible,
  .chat-input:focus-visible { outline: none; }
  body { font-family: var(--font); background: var(--bg-app); color: var(--text-primary); height: 100vh; overflow: hidden; }

  /* ── Shell ── */
  .app { display: flex; flex-direction: column; height: 100vh; }

  /* ── Topbar ── */
  .topbar {
    display: flex; align-items: center; gap: var(--sp-2_5);
    padding: 0 var(--sp-5); height: 52px;
    background: var(--bg-toolbar);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0; position: relative; z-index: 30;
  }
  .logo { display: flex; align-items: center; gap: 9px; font-size: var(--text-lg); font-weight: 600; color: var(--text-primary); letter-spacing: -0.01em; }
  .logo-mark {
    display: block; flex-shrink: 0; width: 26px; height: 26px;
    border-radius: 7px; box-shadow: 0 1px 4px rgba(0,0,0,0.28);
  }
  .logo-word {
    font-size: var(--text-xl); font-weight: 700; letter-spacing: -0.035em;
    color: var(--text-primary); white-space: nowrap;
  }
  .logo-word > span { color: var(--accent); }
  .logo-icon {
    width: 30px; height: 30px; border-radius: var(--radius-md);
    background: linear-gradient(135deg, var(--accent), var(--brand-secondary));
    display: flex; align-items: center; justify-content: center;
    font-size: var(--text-xl); color: #fff; box-shadow: 0 2px 8px var(--accent-glow);
  }
  .topbar-badge {
    font-size: var(--text-2xs); font-weight: 500;
    background: rgba(34,197,94,0.12); color: #22c55e;
    border: 1px solid rgba(34,197,94,0.2);
    padding: var(--sp-0_5) var(--sp-2); border-radius: 20px; letter-spacing: 0.02em;
    flex-shrink: 0; white-space: nowrap;
  }
  /* Live AI-credit chip (credits-chip.js) — a topbar-sized sibling of the Hub's
     full credits meter. Accent by default; red when the monthly allotment runs low. */
  .ai-credit-chip {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: var(--text-2xs); font-weight: 600; font-family: inherit;
    color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--accent) 24%, transparent);
    padding: var(--sp-0_5) var(--sp-2); border-radius: 20px; letter-spacing: 0.02em;
    flex-shrink: 0; white-space: nowrap; cursor: default;
    font-variant-numeric: tabular-nums;
    transition: background 0.15s ease, transform 0.15s ease;
  }
  .ai-credit-chip .ti { font-size: 1.05em; line-height: 1; flex-shrink: 0; }
  .ai-credit-chip .aicc-txt { font-weight: 500; }
  .ai-credit-chip .aicc-txt b { font-weight: 700; }
  /* Mini depletion bar — fills with the monthly allotment remaining. */
  .ai-credit-chip .aicc-bar {
    width: 30px; height: 4px; border-radius: 99px; overflow: hidden; flex-shrink: 0;
    background: color-mix(in srgb, currentColor 22%, transparent);
  }
  .ai-credit-chip .aicc-bar i { display: block; height: 100%; border-radius: 99px; background: currentColor; }
  .ai-credit-chip.is-buyable { cursor: pointer; }
  .ai-credit-chip.is-buyable:hover { background: color-mix(in srgb, var(--accent) 20%, transparent); transform: translateY(-1px); }
  .ai-credit-chip.is-low {
    color: #ef4444; background: rgba(239,68,68,0.12); border-color: rgba(239,68,68,0.25);
  }
  .ai-credit-chip.is-low:hover { background: rgba(239,68,68,0.2); }
  .topbar-spacer { flex: 1; }
  /* Project context chip: name + inline save-state read as a single unit. */
  .topbar-project-chip {
    display: inline-flex; align-items: center; gap: var(--sp-1);
    /* Shrinks, but never to nothing. flex-shrink:0 here (and on .topbar-project
       below) was how the name was kept from being crushed to a letter on an
       over-stuffed bar — but a rail where NOTHING gives is a rail that pushes
       its right-hand cluster (Share, Messages, Account) off the screen, with no
       overflow menu above 768px to reach them in. The chip gives instead, down
       to a floor that still reads as a name. */
    min-width: 0; flex: 0 1 auto;
  }
  .topbar-project {
    font-size: var(--text-xs); color: var(--text-muted); cursor: pointer;
    max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    padding: var(--sp-0_5) var(--sp-1_5); border-radius: 4px;
    /* A FLOOR, not a lock. The overflow:hidden otherwise lets this shrink to ~0
       on an over-stuffed bar and the name is crushed to a letter or two against
       the logo ("stacked on title"); flex-shrink:0 fixed that by making the bar
       overflow instead, which cost the account menu. 5.5rem still ellipsises to
       a readable stub, and the ladder in ui-next.css drops the chip outright
       before it ever gets there. */
    flex: 0 1 auto; min-width: 5.5rem;
  }
  .topbar-project:hover { color: var(--text-secondary); background: var(--surface-hover); }
  .topbar-save-status {
    font-size: var(--text-2xs); color: var(--text-muted); white-space: nowrap;
    display: inline-flex; align-items: center; gap: var(--sp-1); padding: var(--sp-0_5) var(--sp-1);
    user-select: none;
  }
  .topbar-save-status.is-dirty { color: #f59e0b; }
  .topbar-save-status.is-saved { color: var(--text-muted); }
  /* The action cluster is the LAST thing allowed to give — every option in it
     (AI, Project, Tools, Share, Messages, Account) is only reachable here above
     768px, so it neither shrinks nor gets pushed past the right edge. */
  .topbar-actions { display: flex; gap: var(--sp-1_5); flex: 0 0 auto; }

  /* ── Floor (storey) tabs ── */
  /* THE FLOOR TABS SCROLL AT EVERY WIDTH, not only on a phone. As a row of
     nowrap buttons that could neither shrink nor scroll, four storeys were
     enough to drive Share and the account menu off a 1400px window — the tabs
     took the space and the cluster took the overflow. The ≤768px block already
     did this; it belongs at every width, because a floor list has no maximum. */
  .floor-tabs {
    display: flex; align-items: center; gap: var(--sp-1); margin-left: var(--sp-2);
    flex: 0 1 auto; min-width: 0;
    overflow-x: auto; overflow-y: hidden;
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .floor-tabs::-webkit-scrollbar { display: none; }
  .floor-tab, .floor-tab-add { flex-shrink: 0; }
  .floor-tab {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: var(--text-xs); font-weight: 500; color: var(--text-muted);
    background: transparent; border: 1px solid var(--border);
    padding: 3px 9px; border-radius: 6px; cursor: pointer; white-space: nowrap;
    max-width: 140px; overflow: hidden; text-overflow: ellipsis;
  }
  .floor-tab:hover { color: var(--text-secondary); background: var(--surface-hover); }
  .floor-tab.active {
    color: var(--accent-fg); background: var(--accent, #33b1ff);
    border-color: var(--accent, #33b1ff);
  }
  .floor-peer-dot {
    width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;
    box-shadow: 0 0 0 1px rgba(0,0,0,0.25);
  }
  .floor-tab-add {
    display: inline-flex; align-items: center; justify-content: center;
    width: 24px; height: 24px; border-radius: 6px; cursor: pointer;
    color: var(--text-muted); background: transparent; border: 1px solid var(--border);
    font-size: var(--text-base);
  }
  .floor-tab-add:hover { color: var(--text-secondary); background: var(--surface-hover); }

  /* ── Toolbar ── */
  .toolbar {
    display: flex; flex-direction: column;
    background: var(--bg-sidebar);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
  }
  .toolbar-row {
    display: flex; align-items: center; gap: 3px;
    padding: 0 var(--sp-2_5); height: 42px; flex-shrink: 0;
  }
  .toolbar-row:first-child { border-bottom: 1px solid var(--border); }
  .toolbar-rows { display: contents; }
  .toolbar-mobile-trigger { display: none; }
  /* Two-class selector so it outranks the later `.btn-icon { display:inline-flex }`
     base rule (equal single-class specificity would lose on source order, leaking
     the kebab onto the desktop bar). The mobile show-rule is bumped to match. */
  .topbar .topbar-menu-trigger { display: none; }
  .tool-divider { width: 1px; height: 20px; background: var(--border); margin: 0 5px; flex-shrink: 0; }
  .tool-label { font-size: var(--text-2xs); font-weight: 500; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.06em; margin-right: var(--sp-1); flex-shrink: 0; }

  /* ── Buttons ── */
  .btn {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 5px var(--sp-2_5); font-size: var(--text-sm); font-weight: 500;
    border: 1px solid var(--border); border-radius: var(--radius-md);
    background: transparent; color: var(--text-secondary);
    cursor: pointer; transition: all var(--transition);
    white-space: nowrap; flex-shrink: 0;
  }
  .btn i { font-size: var(--text-md); }
  .btn:hover { background: rgba(255,255,255,0.06); color: var(--text-primary); border-color: rgba(255,255,255,0.14); }
  .btn.active { background: var(--accent-light); color: var(--accent); border-color: var(--border-focus); }
  /* THE DUCT TOOL COLOUR STRIPES ARE GONE, and their absence is the point.
     Four tool buttons wore their duct hue as an inset stripe and an active fill,
     with the fills hard-coded as rgba() copies of a palette that has since moved
     (rgba(249,115,22) was return-orange; return is now #e23b3b) — so they had
     already drifted out of agreement with the drawing they claimed to label.
     This was the twin of the #ndToolColors block in app.html, deleted with it.
     Under the colour law the chrome is monochrome and the four hues live only on
     the drawing, where they are the legend and therefore information. The armed
     tool is marked by ground and weight, like every other armed control. */
  .btn:disabled { opacity: 0.35; cursor: not-allowed; }
  .btn:disabled:hover { background: transparent; color: var(--text-secondary); border-color: var(--border); }
  .btn:active:not(:disabled), .btn-ghost:active { transform: scale(0.95); }
  .btn-primary {
    width: 100%; padding: var(--sp-2) var(--sp-3); font-size: var(--text-sm); font-weight: 600;
    background: var(--accent); color: var(--accent-fg); border: none; border-radius: var(--radius-md);
    cursor: pointer; display: flex; align-items: center; justify-content: center; gap: var(--sp-1_5);
    transition: all var(--transition); letter-spacing: 0.01em;
  }
  .btn-primary:hover { background: var(--accent-hover); box-shadow: 0 4px 12px var(--accent-glow); }
  .btn-primary:active { transform: scale(0.95); }
  .btn-secondary {
    width: 100%; padding: 7px var(--sp-3); font-size: var(--text-sm); font-weight: 500;
    background: rgba(255,255,255,0.05); color: var(--text-secondary);
    border: 1px solid var(--border); border-radius: var(--radius-md);
    cursor: pointer; margin-top: var(--sp-1_5);
    display: flex; align-items: center; justify-content: center; gap: var(--sp-1_5);
    transition: all var(--transition);
  }
  .btn-secondary:hover { background: rgba(255,255,255,0.09); color: var(--text-primary); }
  .btn-icon {
    width: 28px; height: 28px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--radius-md); background: transparent;
    border: 1px solid var(--border); color: var(--text-secondary);
    cursor: pointer; transition: all var(--transition); font-size: var(--text-md);
  }
  .btn-icon:hover { background: rgba(255,255,255,0.06); color: var(--text-primary); }
  .btn-icon:active:not(:disabled) { transform: scale(0.9); }
  .btn-icon:disabled { opacity: 0.3; cursor: not-allowed; }
  .btn-danger { border-color: rgba(239,68,68,0.3); color: #f87171; }
  .btn-danger:hover { background: rgba(239,68,68,0.1); border-color: rgba(239,68,68,0.5); color: #f87171; }
  .btn-ghost {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 5px var(--sp-2_5); font-size: var(--text-sm); font-weight: 500;
    border: none; border-radius: var(--radius-md);
    background: transparent; color: var(--text-secondary);
    cursor: pointer; transition: all var(--transition);
    white-space: nowrap;
  }
  .btn-ghost:hover { background: rgba(255,255,255,0.06); color: var(--text-primary); }
  .btn-ai {
    background: linear-gradient(135deg, rgba(139,92,246,0.15), rgba(51,177,255,0.15));
    border-color: rgba(139,92,246,0.3); color: #a78bfa;
  }
  .btn-ai:hover { background: linear-gradient(135deg, rgba(139,92,246,0.25), rgba(51,177,255,0.25)); border-color: rgba(139,92,246,0.5); color: #c4b5fd; }
  .btn-ai.loading { animation: pulse-ai 1.2s ease infinite; }
  @keyframes pulse-ai { 0%,100% { opacity: 1; } 50% { opacity: 0.5; } }

  /* ── Color Swatches ── */
  .color-swatch {
    width: 18px; height: 18px; border-radius: 4px;
    border: 2px solid transparent; cursor: pointer;
    transition: all var(--transition); flex-shrink: 0;
  }
  .color-swatch:hover { transform: scale(1.2); }
  .color-swatch.selected { border-color: #fff; box-shadow: 0 0 0 1px rgba(255,255,255,0.3); transform: scale(1.15); }

  /* ── Width Select ── */
  .duct-width-select {
    font-size: var(--text-xs); padding: var(--sp-1) var(--sp-1_5);
    background: var(--bg-input); color: var(--text-primary);
    border: 1px solid var(--border-input); border-radius: var(--radius-sm);
    cursor: pointer; width: 100px;
  }
  .duct-width-select:focus { outline: none; border-color: var(--border-focus); }

  /* ── Layout ── */
  .main { display: flex; flex: 1; overflow: hidden; }

  /* ── Sidebar ── */
  .sidebar {
    width: 288px; flex-shrink: 0;
    background: var(--bg-sidebar); border-right: 1px solid var(--border);
    display: flex; flex-direction: column; overflow: hidden;
    transition: width 0.22s ease;
  }
  .sidebar.collapsed { width: 52px; }
  .sidebar.collapsed .sidebar-tabs { flex-direction: column; border-bottom: none; padding: var(--sp-1); gap: 3px; }
  .sidebar.collapsed .s-tab-label { display: none; }
  .sidebar.collapsed .sidebar-pane { display: none !important; }
  .sidebar.collapsed .sidebar-hint { display: none; }
  .sidebar.collapsed .sidebar-tab { padding: 11px 0; border-bottom: none; margin-bottom: 0; border-radius: var(--radius-md); }
  .sidebar.collapsed .sidebar-tab.active { background: var(--accent-light); }
  .sidebar.collapsed .sidebar-tab i { font-size: 19px; }
  .sidebar.collapsed .sidebar-collapse-btn { width: auto; border-left: none; border-top: 1px solid var(--border); margin: var(--sp-1) var(--sp-1) 0; padding: 9px 0; border-radius: var(--radius-md); }
  .sidebar-section { padding: var(--sp-2) var(--sp-2_5); border-bottom: 1px solid var(--border); }
  .section-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 7px; }
  .section-title { font-size: var(--text-xs); font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; }

  /* ── Form utilities (extracted from repeated inline styles) ──
     .nd-field-label: the uppercase "eyebrow" label above a control.
     .nd-check: accent-coloured checkbox/radio at the standard 16px box. */
  .nd-field-label { display: block; font-size: var(--text-xs); font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: var(--sp-1_5); }
  .nd-check { accent-color: var(--accent); width: 16px; height: 16px; }

  /* ── Layers Panel ── */
  .layers-list { display:flex; flex-direction:column; gap:var(--sp-px); }
  .layer-row {
    display:flex; align-items:center; gap:var(--sp-1_5);
    padding:var(--sp-1_5) var(--sp-2); border-radius:var(--radius-md);
    cursor:pointer; border:1px solid transparent;
    transition:background var(--transition), border-color var(--transition);
    user-select:none;
  }
  .layer-row:hover { background:var(--bg-card-hover); }
  .layer-row.layer-active { background:rgba(51,177,255,0.1); border-color:rgba(51,177,255,0.25); }
  .layer-row.layer-hidden .layer-name { opacity:0.38; text-decoration:line-through; }
  .layer-row.layer-locked .layer-name { opacity:0.55; font-style:italic; }
  .layer-vis-btn, .layer-lock-btn {
    background:none; border:none; padding:0;
    width:24px; height:24px; display:flex; align-items:center; justify-content:center;
    cursor:pointer; border-radius:5px; color:var(--text-muted); font-size:var(--text-base); flex-shrink:0;
    transition:color var(--transition), background var(--transition);
  }
  .layer-vis-btn:hover, .layer-lock-btn:hover { color:var(--text-primary); background:rgba(255,255,255,0.07); }
  .layer-dot { width:10px; height:10px; border-radius:2px; flex-shrink:0; }
  .layer-name { font-size:var(--text-base); font-weight:500; color:var(--text-primary); flex:1; line-height:1.1; transition:opacity var(--transition); }
  /* Supply leg sub-rows */
  #legLayersList { margin-top:var(--sp-0_5); padding-top:var(--sp-0_5); border-top:1px solid var(--border); }
  #legLayersList:empty { display:none; }
  .leg-layer-row { cursor:default; padding-left:var(--sp-2_5); }
  .leg-layer-row:hover { background:var(--bg-card-hover); }
  .layer-active-pip { width:5px; height:5px; border-radius:50%; background:var(--accent); flex-shrink:0; }

  /* ── Duct List ── */
  .duct-list-empty {
    font-size: var(--text-xs); color: var(--text-muted); padding: var(--sp-2_5); text-align: center;
    background: rgba(255,255,255,0.02); border-radius: var(--radius-md);
    border: 1px dashed var(--border); line-height: 1.5;
  }
  .duct-item {
    display: flex; align-items: center; gap: var(--sp-2);
    padding: var(--sp-2) var(--sp-2_5); border-radius: var(--radius-md);
    border: 1px solid transparent; margin-bottom: var(--sp-1); font-size: var(--text-sm);
    cursor: pointer; transition: all var(--transition);
  }
  .duct-item:hover { background: rgba(255,255,255,0.04); border-color: var(--border); }
  .duct-item.selected { background: var(--accent-light); border-color: rgba(51,177,255,0.3); }
  .duct-dot { width: 8px; height: 8px; border-radius: 2px; flex-shrink: 0; }
  .duct-label { flex: 1; color: var(--text-primary); font-weight: 500; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .duct-type-tag { font-size: 9px; font-weight: 600; text-transform: uppercase; padding: var(--sp-px) 5px; border-radius: 3px; background: rgba(255,255,255,0.06); color: var(--text-muted); letter-spacing: 0.04em; flex-shrink: 0; }

  /* ── Legend ── */
  .legend { display: flex; flex-direction: column; gap: 5px; margin-top: var(--sp-2_5); }
  .legend-row { display: flex; align-items: center; gap: 7px; font-size: var(--text-xs); color: var(--text-secondary); }
  .legend-line { width: 20px; height: 3px; border-radius: 2px; flex-shrink: 0; }
  .legend-dashed { width: 20px; height: 3px; flex-shrink: 0; background: repeating-linear-gradient(90deg, var(--return-color) 0px, var(--return-color) 5px, transparent 5px, transparent 8px); }

  /* ── Form elements ── */
  .prop-row { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: 7px; }
  .prop-label { font-size: var(--text-sm); color: var(--text-secondary); width: 78px; flex-shrink: 0; }
  .prop-input {
    flex: 1; font-size: var(--text-sm); padding: var(--sp-1_5) 9px;
    background: var(--bg-input); color: var(--text-primary);
    border: 1px solid var(--border-input); border-radius: var(--radius-sm);
    transition: border-color var(--transition);
  }
  .prop-input:focus { outline: none; border-color: var(--border-focus); background: rgba(51,177,255,0.04); }
  select.prop-input { cursor: pointer; color-scheme: dark; }
  select.prop-input option { background: var(--bg-input); color: var(--text-primary); }
  .props-card { background: var(--bg-card); border-radius: var(--radius-md); padding: var(--sp-2_5); border: 1px solid var(--border); }

  /* ── Rooms panel ── */
  .room-chip {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: var(--text-2xs); padding: 3px var(--sp-2); border-radius: 12px;
    border: 1px solid var(--border); background: var(--bg-card);
    color: var(--text-secondary); margin: var(--sp-0_5); cursor: pointer;
  }
  .room-chip-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }

  /* ── Brand Cards ── */
  .brand-card { padding: 9px var(--sp-2_5); border-radius: var(--radius-md); border: 1px solid var(--border); margin-bottom: var(--sp-1_5); background: var(--bg-card); transition: all var(--transition); }
  .brand-card:hover { background: var(--bg-card-hover); border-color: rgba(255,255,255,0.12); }
  .brand-card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 3px; }
  .brand-name { font-size: var(--text-sm); font-weight: 600; color: var(--text-primary); }
  .brand-country { font-size: var(--text-2xs); color: var(--text-muted); }
  .brand-note { font-size: var(--text-2xs); color: var(--text-secondary); line-height: 1.4; }
  .brand-badge { font-size: 9px; font-weight: 600; padding: var(--sp-0_5) 7px; border-radius: 10px; text-transform: uppercase; letter-spacing: 0.05em; display: inline-block; margin-top: 5px; }
  .brand-badge.premium { background: rgba(168,85,247,0.15); color: #c084fc; border: 1px solid rgba(168,85,247,0.2); }
  .brand-badge.mid { background: rgba(51,177,255,0.12); color: #5cc0ff; border: 1px solid rgba(51,177,255,0.2); }
  .brand-badge.budget { background: rgba(34,197,94,0.1); color: #4ade80; border: 1px solid rgba(34,197,94,0.2); }

  /* ── Canvas ── */
  .canvas-area {
    flex: 1; position: relative; overflow: hidden;
    background: var(--bg-canvas);
    /* Grid is now drawn in world space on the canvas (drawGrid() in app.js) so it
       pans/zooms with content and stays aligned to the snap grid. The old static
       CSS background-grid only matched at zoom=1, pan=0 and has been removed. */
  }
  canvas { position: absolute; top: 0; left: 0; }

  /* ── Upload overlay ── */
  .upload-overlay {
    position: absolute; inset: 0; display: flex;
    flex-direction: column; align-items: center; justify-content: center; gap: var(--sp-4);
    background: rgba(240,242,247,0.94); backdrop-filter: blur(4px); z-index: 10;
  }
  .upload-box {
    border: 2px dashed rgba(100,116,139,0.4); border-radius: var(--radius-xl);
    padding: var(--sp-12) var(--sp-16); text-align: center; cursor: pointer;
    background: #fff; transition: all 0.2s; box-shadow: var(--shadow-md);
  }
  .upload-box:hover { border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-glow), var(--shadow-md); }
  .upload-box.dragging { border-color: var(--accent); background: #f0f7ff; }
  /* Two upload choices side by side — AI (primary) vs manual (secondary). */
  .upload-choice-row { display: flex; gap: var(--sp-4); align-items: stretch; justify-content: center; flex-wrap: wrap; width: min(680px, 90vw); }
  .upload-choice-row .upload-box { flex: 1 1 240px; padding: var(--sp-9) var(--sp-7); position: relative; display: flex; flex-direction: column; justify-content: center; }
  .upload-choice-row .upload-title { line-height: 1.3; }
  .upload-choice-row .upload-sub { line-height: 1.4; max-width: 26ch; margin: 0 auto; }
  .upload-choice-row .upload-hint { line-height: 1.4; }
  .upload-box--primary { border-style: solid; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow), var(--shadow-md); }
  .upload-box--secondary { background: #fbfcfe; }
  .upload-box--secondary .upload-icon { background: rgba(100,116,139,0.12); }
  .upload-box--secondary .upload-icon i { color: #64748b; }
  .upload-badge { position: absolute; top: -10px; left: 50%; transform: translateX(-50%); background: var(--accent); color: var(--accent-fg); font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; padding: 3px 9px; border-radius: 999px; white-space: nowrap; box-shadow: var(--shadow-sm); }
  .upload-icon { width: 56px; height: 56px; border-radius: var(--radius-lg); background: var(--accent-light); display: flex; align-items: center; justify-content: center; margin: 0 auto var(--sp-3_5); }
  .upload-icon i { font-size: 28px; color: var(--accent); }
  .upload-title { font-size: var(--text-xl); font-weight: 600; color: #1e293b; margin-bottom: var(--sp-1); }
  .upload-sub { font-size: var(--text-base); color: #64748b; }
  .upload-hint { font-size: var(--text-xs); color: #94a3b8; margin-top: var(--sp-2); }
  .upload-alt { display: flex; align-items: center; gap: var(--sp-2_5); color: #94a3b8; font-size: var(--text-sm); }
  .upload-alt::before, .upload-alt::after { content: ''; flex: 1; height: 1px; background: rgba(100,116,139,0.2); display: block; width: 60px; }

  /* ── AI Status Overlay ── */
  .ai-status-overlay {
    display: flex; position: absolute; inset: 0;
    align-items: center; justify-content: center;
    background: rgba(10,13,20,0.38);
    backdrop-filter: blur(2px);
    z-index: 20;
    opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity 0.2s ease, visibility 0.2s ease;
  }
  .ai-status-overlay.active { opacity: 1; visibility: visible; pointer-events: auto; }
  .ai-status-card {
    background: var(--bg-card);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-xl);
    padding: var(--sp-8) var(--sp-12);
    display: flex; flex-direction: column; align-items: center; gap: var(--sp-2_5);
    box-shadow: var(--shadow-lg);
    min-width: 300px; text-align: center;
    animation: ai-card-in 0.18s ease-out;
  }
  @keyframes ai-card-in {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
  }
  .ai-status-icon {
    width: 48px; height: 48px; border-radius: 50%;
    background: var(--accent-soft);
    border: 1px solid var(--accent-edge);
    display: flex; align-items: center; justify-content: center;
    margin-bottom: var(--sp-1);
  }
  .ai-status-icon i { font-size: 24px; color: var(--accent); }
  .ai-status-context {
    font-size: var(--text-xs); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--accent); padding: 3px var(--sp-2_5); border-radius: 999px;
    background: var(--accent-soft); border: 1px solid var(--accent-edge);
    margin-bottom: var(--sp-1);
  }
  .ai-status-title { font-size: var(--text-lg); font-weight: 700; color: var(--text-primary); letter-spacing: -0.01em; }
  .ai-status-sub   { font-size: var(--text-sm); color: var(--text-muted); line-height: 1.5; }
  .ai-status-steps {
    display: flex; flex-direction: column; gap: 5px; width: 100%;
    margin-top: var(--sp-1_5); padding-top: var(--sp-3); border-top: 1px solid var(--border);
  }
  @keyframes stepIn { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }
  .ai-step {
    display: flex; align-items: center; gap: var(--sp-2);
    font-size: var(--text-xs); color: var(--text-muted); padding: 3px 0;
    animation: stepIn 0.2s ease backwards;
  }
  .ai-step:nth-child(1) { animation-delay: 0.04s; }
  .ai-step:nth-child(2) { animation-delay: 0.10s; }
  .ai-step:nth-child(3) { animation-delay: 0.16s; }
  .ai-step:nth-child(4) { animation-delay: 0.22s; }
  .ai-step:nth-child(5) { animation-delay: 0.28s; }
  .ai-step:nth-child(6) { animation-delay: 0.34s; }
  .ai-step:nth-child(7) { animation-delay: 0.40s; }
  .ai-step i { font-size: var(--text-base); width: 14px; flex-shrink: 0; }
  .ai-step.done    { color: #22c55e; }
  .ai-step.active  { color: var(--text-primary); font-weight: 500; }
  .ai-step.pending { color: var(--text-muted); opacity: 0.5; }
  .ai-status-progress {
    display: flex; align-items: center;
    width: 100%; margin-top: var(--sp-2);
  }
  .ai-status-bar-track {
    flex: 1; height: 3px; border-radius: 999px;
    background: var(--border); overflow: hidden;
  }
  /* Honest indeterminate bar — Gemini calls have no streaming progress, so a
     slice slides across rather than implying a known percentage. */
  .ai-status-bar-track.is-indeterminate .ai-status-bar-fill {
    width: 35%; border-radius: 999px; height: 100%;
    background: var(--accent);
    animation: ai-bar-slide 1.1s ease-in-out infinite;
  }
  @keyframes ai-bar-slide {
    0%   { transform: translateX(-120%); }
    100% { transform: translateX(385%); }
  }

  /* Upload loading state */
  .upload-loading { display: none; flex-direction: column; align-items: center; gap: var(--sp-3_5); padding: 52px 72px; background: #fff; border-radius: var(--radius-xl); box-shadow: var(--shadow-md); border: 1px solid var(--border); }
  .upload-loading-icon i { font-size: 36px; color: var(--accent); }
  .upload-loading-title { font-size: var(--text-lg); font-weight: 600; color: var(--text-primary); }
  .upload-loading-track { width: 240px; height: 6px; background: var(--border); border-radius: 3px; overflow: hidden; }
  .upload-loading-fill { height: 100%; width: 0%; background: var(--accent); border-radius: 3px; transition: width 0.12s ease; }
  .upload-loading-pct { font-size: var(--text-sm); color: var(--text-muted); font-weight: 500; }
  #uploadOverlay.loading .upload-choice-row,
  #uploadOverlay.loading .upload-box,
  #uploadOverlay.loading .upload-alt,
  #uploadOverlay.loading .btn-demo { display: none; }
  #uploadOverlay.loading .upload-loading { display: flex; }
  .btn-demo { display: inline-flex; align-items: center; gap: var(--sp-1_5); padding: 9px 18px; font-size: var(--text-base); font-weight: 500; background: #fff; color: #475569; border: 1px solid rgba(100,116,139,0.2); border-radius: var(--radius-md); cursor: pointer; transition: all 0.2s; box-shadow: var(--shadow-sm); }
  .btn-demo:hover { background: #f8fafc; border-color: var(--accent); color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }

  /* ── Status bar ── */
  .status-bar { display: flex; align-items: center; height: 28px; padding: 0 var(--sp-4); background: var(--bg-sidebar); border-top: 1px solid var(--border); flex-shrink: 0; }
  .status-item { display: flex; align-items: center; gap: 5px; font-size: var(--text-xs); color: var(--text-muted); padding: 0 var(--sp-3); border-right: 1px solid var(--border); }
  .status-item:first-child { padding-left: 0; }
  .status-item i { font-size: var(--text-sm); }
  .status-value { color: var(--text-secondary); font-weight: 500; }
  .status-spacer { flex: 1; }
  .status-right { display: flex; gap: 0; }
  .status-zoom-group { gap: 3px; padding: 0 var(--sp-2); }
  .status-zoom-label { min-width: 34px; text-align: center; font-weight: 500; color: var(--text-secondary); font-size: var(--text-xs); }
  .status-zoom-btn {
    background: none; border: none; padding: 0;
    width: 18px; height: 18px; display: flex; align-items: center; justify-content: center;
    cursor: pointer; border-radius: 3px; color: var(--text-muted); font-size: var(--text-xs);
    transition: color var(--transition), background var(--transition);
  }
  .status-zoom-btn:hover { color: var(--text-primary); background: rgba(255,255,255,0.07); }

  /* ── Modals ── */
  .modal-bg { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.6); backdrop-filter: blur(4px); z-index: 100; align-items: center; justify-content: center; }
  .modal-bg.open { display: flex; }
  .modal { background: var(--bg-modal); border-radius: var(--radius-xl); border: 1px solid var(--border); padding: var(--sp-7); max-width: 520px; width: 90%; max-height: 82vh; overflow-y: auto; box-shadow: var(--shadow-lg); }
  .modal::-webkit-scrollbar { width: 4px; }
  .modal::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 2px; }
  .modal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--sp-5); }
  .modal-title { display: flex; align-items: center; gap: var(--sp-2_5); font-size: 17px; font-weight: 600; color: var(--text-primary); }
  .modal-title-icon { width: 34px; height: 34px; border-radius: var(--radius-md); display: flex; align-items: center; justify-content: center; font-size: var(--text-2xl); }
  .modal-title-icon.yellow { background: rgba(251,191,36,0.12); border: 1px solid rgba(251,191,36,0.2); color: #fbbf24; }
  .modal-title-icon.purple { background: rgba(139,92,246,0.12); border: 1px solid rgba(139,92,246,0.2); color: #a78bfa; }
  .modal-title-icon.blue { background: rgba(51,177,255,0.12); border: 1px solid rgba(51,177,255,0.2); color: #5cc0ff; }
  .modal-desc { font-size: var(--text-base); color: var(--text-secondary); margin-bottom: var(--sp-4); line-height: 1.6; }
  .reco-item { padding: var(--sp-3) var(--sp-3_5); border: 1px solid var(--border); border-radius: var(--radius-md); margin-bottom: var(--sp-2); background: var(--bg-card); transition: all var(--transition); }
  .reco-item:hover { border-color: rgba(255,255,255,0.12); }
  .reco-item h4 { font-size: var(--text-sm); font-weight: 600; color: var(--text-primary); margin-bottom: var(--sp-1); }
  .reco-item p { font-size: var(--text-xs); color: var(--text-secondary); line-height: 1.5; }
  .reco-footer { margin-top: var(--sp-3_5); padding: var(--sp-3) var(--sp-3_5); background: rgba(51,177,255,0.06); border: 1px solid rgba(51,177,255,0.15); border-radius: var(--radius-md); }
  .reco-footer p { font-size: var(--text-xs); color: var(--text-secondary); line-height: 1.5; }

  /* ── API Key input ── */
  .api-key-input-wrap { position: relative; margin-bottom: var(--sp-3); }
  .api-key-input { width: 100%; padding: 9px 38px 9px var(--sp-2_5); font-size: var(--text-sm); background: var(--bg-input); color: var(--text-primary); border: 1px solid var(--border-input); border-radius: var(--radius-md); letter-spacing: 0.04em; }
  .api-key-input:focus { outline: none; border-color: var(--border-focus); }
  .api-key-toggle { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); background: none; border: none; color: var(--text-muted); cursor: pointer; font-size: var(--text-lg); padding: var(--sp-0_5); }
  .api-key-hint { font-size: var(--text-2xs); color: var(--text-muted); margin-top: var(--sp-1_5); }

  /* ── Toasts ── */
  .toast-container { position: fixed; bottom: 40px; right: 20px; z-index: 4000; display: flex; flex-direction: column; gap: var(--sp-2); pointer-events: none; transition: right 0.22s ease; }
  /* While the 320px chat panel is open (desktop only), slide toasts left of it
     so they don't overlay the chat. Mobile panel is full-width — left as-is. */
  @media (min-width: 769px) {
    body:has(.chat-panel.open) .toast-container { right: 340px; }
  }
  .toast {
    display: flex; align-items: center; gap: 9px;
    padding: var(--sp-2_5) var(--sp-3_5); border-radius: var(--radius-md);
    background: var(--bg-modal); border: 1px solid var(--border);
    box-shadow: var(--shadow-lg); font-size: var(--text-sm); color: var(--text-primary);
    opacity: 0; transform: translateY(8px) scale(0.97);
    transition: all 0.22s ease; pointer-events: auto; max-width: 320px;
  }
  .toast.visible { opacity: 1; transform: none; }
  .toast.exiting { opacity: 0; transform: translateX(24px) scale(0.96); }
  .toast i { font-size: var(--text-lg); flex-shrink: 0; }
  .toast-success { border-color: rgba(34,197,94,0.3); }
  .toast-success i { color: #22c55e; }
  .toast-error { border-color: rgba(239,68,68,0.3); }
  .toast-error i { color: #f87171; }
  .toast-info i { color: #5cc0ff; }
  .toast-warning i { color: #fbbf24; }
  .toast { pointer-events: auto; cursor: pointer; }
  .toast:hover { border-color: rgba(255,255,255,0.14); }
  .toast-msg { flex: 1; }
  .toast-actions { display: flex; gap: var(--sp-1); margin-left: var(--sp-1); }
  .toast-action { padding: 3px 9px; font-size: var(--text-xs); font-weight: 600; border-radius: var(--radius-sm); border: 1px solid rgba(255,255,255,0.18); background: rgba(255,255,255,0.08); color: var(--text-primary); cursor: pointer; white-space: nowrap; }
  .toast-action:hover { background: rgba(255,255,255,0.16); }

  /* ── Current tool pill ── */
  .canvas-tool-pill {
    position: absolute; top: 14px; left: 50%; transform: translateX(-50%); z-index: 100;
    display: flex; align-items: center; gap: 7px;
    padding: var(--sp-1_5) var(--sp-3); border-radius: 999px;
    background: var(--bg-modal); border: 1px solid var(--border);
    box-shadow: var(--shadow-lg); font-size: var(--text-sm); font-weight: 600;
    color: var(--text-primary); pointer-events: none; white-space: nowrap;
  }
  .canvas-tool-pill i { font-size: var(--text-lg); flex-shrink: 0; }

  /* ── "Did you know" canvas hint pill ── */
  .canvas-hint {
    position: absolute; top: 14px; left: 14px; transform: translateY(-6px);
    z-index: 100; display: flex; align-items: center; gap: 9px;
    max-width: min(420px, calc(50% - 120px));
    padding: var(--sp-2) var(--sp-2_5) var(--sp-2) 13px; border-radius: 999px;
    background: var(--bg-modal); border: 1px solid var(--border);
    box-shadow: var(--shadow-lg); font-size: var(--text-sm); color: var(--text-secondary);
    opacity: 0; transition: opacity 0.25s ease, transform 0.25s ease; pointer-events: auto;
  }
  .canvas-hint[hidden] { display: none; }
  .canvas-hint.visible { opacity: 1; transform: translateY(0); }
  .canvas-hint-icon { font-size: var(--text-lg); flex-shrink: 0; color: #fbbf24; }
  .canvas-hint-text { flex: 1; min-width: 0; line-height: 1.45; }
  .canvas-hint-text b { color: var(--text-primary); font-weight: 600; }
  .canvas-hint-close {
    flex-shrink: 0; width: 22px; height: 22px; padding: 0; display: inline-flex;
    align-items: center; justify-content: center; border-radius: 50%;
    background: transparent; border: none; color: var(--text-muted); cursor: pointer;
    font-size: var(--text-base); transition: background 0.15s, color 0.15s;
  }
  .canvas-hint-close:hover { background: rgba(255,255,255,0.08); color: var(--text-primary); }
  /* Unsaved design indicator dot on Versions button */
  #btnVersions.has-unsaved::after { content: ''; display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); margin-left: var(--sp-1); vertical-align: middle; }

  /* ── Shortcut hint tooltip ── */
  .shortcut-hint { font-size: 9px; color: var(--text-muted); background: rgba(255,255,255,0.05); padding: var(--sp-px) 5px; border-radius: 3px; border: 1px solid var(--border); font-family: monospace; }

  /* ── Keyboard Shortcut Modal ── */
  .shortcut-list { display: flex; flex-direction: column; gap: var(--sp-1); }
  .shortcut-row { display: flex; align-items: center; gap: 5px; font-size: var(--text-sm); color: var(--text-secondary); padding: 3px 0; }
  .shortcut-row span { margin-left: var(--sp-1); }
  kbd { display: inline-flex; align-items: center; justify-content: center; min-width: 22px; padding: var(--sp-px) 5px; font-size: var(--text-2xs); font-family: monospace; font-weight: 600; color: var(--text-primary); background: rgba(255,255,255,0.06); border: 1px solid var(--border); border-bottom-width: 2px; border-radius: 4px; white-space: nowrap; }
  .btn kbd { font-size: 9px; min-width: 14px; padding: 0 3px; opacity: 0.55; margin-left: var(--sp-px); border-bottom-width: 1px; }
  body.hide-kbd kbd { display: none; }
  .modal-title-icon { background: rgba(51,177,255,0.1); border: 1px solid rgba(51,177,255,0.2); color: #5cc0ff; }

  /* ── Unit Picker ── */
  .unit-category-label { font-size: 9px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.08em; margin: var(--sp-2) 0 var(--sp-1); }
  .unit-category-label:first-child { margin-top: 0; }
  .unit-card {
    display: flex; align-items: center; gap: var(--sp-2);
    padding: 7px 9px; border-radius: var(--radius-md);
    border: 1px solid var(--border); cursor: pointer;
    background: transparent; margin-bottom: 3px;
    transition: all var(--transition);
  }
  .unit-card:hover { background: rgba(255,255,255,0.04); border-color: rgba(255,255,255,0.12); }
  .unit-card.active { background: var(--accent-light); border-color: var(--border-focus); }
  .unit-card-icon {
    width: 30px; height: 30px; border-radius: var(--radius-sm); flex-shrink: 0;
    background: rgba(255,255,255,0.05); border: 1px solid var(--border);
    display: flex; align-items: center; justify-content: center; font-size: var(--text-md);
  }
  .unit-card.active .unit-card-icon { background: var(--accent-light); border-color: rgba(51,177,255,0.4); }
  .unit-card-body { flex: 1; min-width: 0; }
  .unit-card-name { font-size: var(--text-xs); font-weight: 600; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .unit-card-meta { font-size: var(--text-2xs); color: var(--text-muted); margin-top: var(--sp-px); }
  .unit-card-kw { font-size: var(--text-2xs); font-weight: 600; color: var(--accent); flex-shrink: 0; }
  .unit-search {
    width: 100%; padding: 5px var(--sp-2); margin-bottom: var(--sp-1_5); box-sizing: border-box;
    background: var(--bg-input); color: var(--text-primary);
    border: 1px solid var(--border-input); border-radius: var(--radius-sm);
    font-size: var(--text-xs); font-family: var(--font); outline: none;
  }
  .unit-search:focus { border-color: var(--border-focus); }
  .unit-search::placeholder { color: var(--text-muted); }
  .unit-no-match { font-size: var(--text-xs); color: var(--text-muted); padding: var(--sp-2) 0; }
  .unit-specs-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-1); margin-top: var(--sp-2); }
  .unit-spec-box { background: rgba(255,255,255,0.03); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 5px 7px; }
  .unit-spec-label { font-size: 9px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; }
  .unit-spec-val { font-size: var(--text-sm); font-weight: 600; color: var(--text-primary); margin-top: var(--sp-px); }

  /* ── Scrollbar ── */
  ::-webkit-scrollbar { width: 6px; height: 6px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 3px; }

  /* ── Animations ── */
  @keyframes fadeIn { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: scale(1); } }
  .modal-bg.open .modal { animation: fadeIn 0.18s ease; }
  @keyframes spin { to { transform: rotate(360deg); } }
  .spin { animation: spin 0.8s linear infinite; }

  /* ── Settings Modal ── */
  .settings-modal { max-width: 600px; padding-bottom: var(--sp-5); }
  .settings-tab-bar { display: flex; border-bottom: 1px solid var(--border); margin: 0 -28px var(--sp-5); padding: 0 var(--sp-5); gap: var(--sp-0_5); overflow-x: auto; scrollbar-width: none; }
  .settings-tab-bar::-webkit-scrollbar { display: none; }
  .settings-tab { flex: none; display: flex; align-items: center; gap: var(--sp-1_5); padding: var(--sp-2) var(--sp-3_5) 7px; background: none; border: none; border-bottom: 2px solid transparent; margin-bottom: -1px; cursor: pointer; font-size: var(--text-sm); font-weight: 600; color: var(--text-muted); transition: color var(--transition); white-space: nowrap; }
  .settings-tab i { font-size: var(--text-md); }
  .settings-tab:hover { color: var(--text-secondary); }
  .settings-tab.active { color: var(--accent); border-bottom-color: var(--accent); }
  .settings-pane { display: none; }
  .settings-pane.active { display: block; }
  .settings-section { margin-bottom: 22px; }
  .settings-section:last-child { margin-bottom: 0; }
  .settings-section-title { font-size: var(--text-2xs); font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: var(--sp-2_5); }
  .settings-row { display: flex; align-items: center; justify-content: space-between; padding: 7px 0; border-bottom: 1px solid var(--border); gap: var(--sp-3); }
  .settings-row:last-child { border-bottom: none; }
  .settings-row-wrap { flex-direction: column; align-items: stretch; gap: 0; }
  .settings-row-wrap:last-child { border-bottom: none; }
  .settings-row-label { font-size: var(--text-sm); color: var(--text-secondary); }
  .settings-row-desc { font-size: var(--text-2xs); color: var(--text-muted); padding: 3px 0 5px; }
  .btn-link { background: none; border: none; color: var(--text-muted); font-size: var(--text-xs); cursor: pointer; padding: 0; text-decoration: underline; }
  .btn-link:hover { color: var(--text-secondary); }
  .no-grid { background-image: none !important; }

  .theme-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--sp-2); }
  .theme-card { border: 2px solid var(--border); border-radius: var(--radius-md); cursor: pointer; overflow: hidden; transition: all var(--transition); }
  .theme-card:hover { border-color: rgba(255,255,255,0.2); transform: translateY(-1px); }
  .theme-card.active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
  .theme-preview { height: 52px; display: flex; gap: 3px; padding: 5px; }
  .theme-preview-sidebar { width: 30%; border-radius: 3px 0 0 3px; }
  .theme-preview-canvas { flex: 1; border-radius: 0 3px 3px 0; position: relative; }
  .theme-preview-dot { width: 8px; height: 8px; border-radius: 50%; position: absolute; bottom: 5px; right: 5px; }
  .theme-name { font-size: var(--text-2xs); font-weight: 500; text-align: center; padding: 5px var(--sp-0_5); color: var(--text-secondary); }
  .theme-card.active .theme-name { color: var(--accent); font-weight: 600; }

  .accent-swatch-row { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
  .accent-dot { width: 28px; height: 28px; border-radius: 50%; border: 3px solid transparent; cursor: pointer; transition: all var(--transition); }
  .accent-dot:hover { transform: scale(1.18); }
  .accent-dot.active { border-color: rgba(255,255,255,0.85); box-shadow: 0 0 0 2px currentColor; }

  .icon-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: var(--sp-1_5); }
  .icon-option {
    aspect-ratio: 1; display: flex; align-items: center; justify-content: center;
    border: 1px solid var(--border); border-radius: var(--radius-md);
    background: transparent; color: var(--text-secondary); font-size: var(--text-2xl);
    cursor: pointer; transition: all var(--transition);
  }
  .icon-option:hover { background: rgba(255,255,255,0.06); color: var(--text-primary); border-color: rgba(255,255,255,0.14); }
  .icon-option.active { background: var(--accent-light); color: var(--accent); border-color: var(--border-focus); }

  .settings-name-preview {
    display: flex; align-items: center; gap: var(--sp-2);
    padding: 9px var(--sp-3); background: var(--bg-card); border-radius: var(--radius-md);
    border: 1px solid var(--border); margin-top: var(--sp-2);
  }
  .logo-icon-preview {
    width: 24px; height: 24px; border-radius: 6px;
    display: flex; align-items: center; justify-content: center;
    font-size: var(--text-base); color: #fff;
  }
  .logo-name { font-size: var(--text-base); font-weight: 600; color: var(--text-primary); }

  /* ── Duct colour swatches ── */
  .duct-colour-row { display: flex; gap: 18px; margin-top: var(--sp-1); flex-wrap: wrap; }
  .duct-swatch-item { display: flex; flex-direction: column; align-items: center; gap: 5px; }
  .duct-swatch {
    width: 34px; height: 34px; border-radius: var(--radius-md); position: relative;
    border: 2px solid rgba(255,255,255,0.15); cursor: pointer;
    transition: transform var(--transition), border-color var(--transition);
    display: flex; align-items: center; justify-content: center;
  }
  .duct-swatch:hover { transform: scale(1.1); border-color: rgba(255,255,255,0.35); }
  .duct-swatch input[type="color"] { opacity: 0; position: absolute; inset: 0; width: 100%; height: 100%; cursor: pointer; border: none; padding: 0; }
  .duct-swatch-label { font-size: var(--text-2xs); color: var(--text-muted); font-weight: 500; }
  .duct-colour-presets { display: flex; gap: var(--sp-1_5); margin-top: var(--sp-2_5); }
  .duct-preset-btn {
    flex: 1; padding: 5px var(--sp-2); font-size: var(--text-xs); font-weight: 500;
    background: var(--bg-card); color: var(--text-secondary);
    border: 1px solid var(--border); border-radius: var(--radius-md);
    cursor: pointer; transition: all var(--transition);
  }
  .duct-preset-btn:hover { background: var(--bg-card-hover); color: var(--text-primary); }
  .duct-preset-btn.active { background: var(--accent-light); color: var(--accent); border-color: var(--border-focus); }

  /* ── UI Density toggle ── */
  .density-toggle { display: flex; border: 1px solid var(--border); border-radius: var(--radius-md); overflow: hidden; }
  .density-btn {
    flex: 1; padding: var(--sp-1_5) var(--sp-1); font-size: var(--text-xs); font-weight: 500;
    background: none; border: none; border-right: 1px solid var(--border);
    color: var(--text-muted); cursor: pointer; transition: all var(--transition);
  }
  .density-btn:last-child { border-right: none; }
  .density-btn:hover { background: rgba(255,255,255,0.05); color: var(--text-secondary); }
  .density-btn.active { background: var(--accent-light); color: var(--accent); }

  /* ── Density body classes ── */
  body.density-compact .sidebar-section { padding: 5px var(--sp-2_5); }
  body.density-compact .section-header { margin-bottom: var(--sp-1); }
  body.density-compact .settings-row { padding: var(--sp-1) 0; }
  body.density-comfortable .sidebar-section { padding: var(--sp-3) var(--sp-2_5); }
  body.density-comfortable .section-header { margin-bottom: var(--sp-2_5); }
  body.density-comfortable .settings-row { padding: var(--sp-2_5) 0; }

/* ── Library Modal ─────────────────────────────────────────── */
.library-modal { max-width: 560px; }
.library-tabs {
  display: flex; gap: var(--sp-1); margin-bottom: 18px;
  border-bottom: 1px solid var(--border); padding-bottom: var(--sp-1);
}
.lib-tab {
  display: flex; align-items: center; gap: var(--sp-1_5);
  padding: var(--sp-1_5) var(--sp-3_5); border-radius: var(--radius-md) var(--radius-md) 0 0;
  border: 1px solid transparent; border-bottom: none;
  font-size: var(--text-sm); font-weight: 500; cursor: pointer;
  color: var(--text-secondary); background: transparent;
  transition: all var(--transition);
}
.lib-tab:hover { color: var(--text-primary); background: var(--bg-card); }
.lib-tab.active { color: var(--accent); background: var(--bg-card); border-color: var(--border); }
.lib-section-title {
  font-size: var(--text-2xs); font-weight: 600; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: var(--sp-2_5);
}
.lib-form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-2); }
.lib-form-row { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0; }
.lib-form-row .prop-input { width: 100%; box-sizing: border-box; }
.lib-form-label { font-size: var(--text-2xs); color: var(--text-muted); font-weight: 500; }
.lib-item {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-2_5); background: var(--bg-card);
  border: 1px solid var(--border); border-radius: var(--radius-md);
  margin-bottom: var(--sp-1);
}
.lib-item-body { flex: 1; min-width: 0; }
.lib-item-name { font-size: var(--text-sm); font-weight: 600; color: var(--text-primary); }
.lib-item-meta { font-size: var(--text-2xs); color: var(--text-muted); margin-top: var(--sp-px); }
.lib-item-badge {
  font-size: 9px; font-weight: 600; letter-spacing: 0.06em;
  padding: var(--sp-0_5) var(--sp-1_5); border-radius: 10px; white-space: nowrap;
  background: var(--accent-light); color: var(--accent);
  border: 1px solid rgba(var(--accent-rgb,59,130,246),0.2);
}

/* ── Generate Layout topbar button ── */
.btn-gen {
  background: linear-gradient(135deg, rgba(34,197,94,0.12), rgba(16,185,129,0.12));
  border-color: rgba(34,197,94,0.3); color: #4ade80;
}
.btn-gen:hover { background: linear-gradient(135deg, rgba(34,197,94,0.22), rgba(16,185,129,0.22)); border-color: rgba(34,197,94,0.5); color: #86efac; }

/* ── Topbar separator ── */
.topbar-sep { width: 1px; height: 20px; background: var(--border); margin: 0 var(--sp-1_5); flex-shrink: 0; }

/* Text labels for the icon-only topbar actions (Messages, Account). Hidden by
   default so those buttons stay icon-only on desktop; the mobile kebab menu
   (where actions become full-width rows) reveals them so they don't read as
   blank rows. See the ≤768px .topbar-actions block. */
.topbar-action-label { display: none; }

/* ── Toolbar spacer & tool group ── */
.toolbar-spacer { flex: 1; }
.tool-group { display: flex; align-items: center; gap: var(--sp-0_5); }

/* ── Sidebar mobile drawer header (hidden on desktop) ── */
.sidebar-mobile-header { display: none; }

/* ── Sidebar tab nav ── */
.sidebar-tabs {
  display: flex; flex-shrink: 0;
  border-bottom: 1px solid var(--border);
  background: var(--bg-sidebar);
}
.sidebar-tab {
  flex: 1; display: flex; flex-direction: row; align-items: center; justify-content: center;
  gap: var(--sp-1_5); padding: 11px var(--sp-1);
  background: none; border: none; cursor: pointer;
  color: var(--text-muted); font-size: var(--text-sm); font-weight: 600;
  letter-spacing: 0.01em; position: relative;
  transition: color var(--transition), background var(--transition);
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.sidebar-tab i { font-size: var(--text-xl); }
.sidebar-tab:hover { color: var(--text-secondary); background: rgba(255,255,255,0.04); }
.sidebar-tab.active { color: var(--accent); border-bottom-color: var(--accent); background: var(--accent-light); }

/* ── Active-tab hint row ── */
.sidebar-hint {
  flex-shrink: 0; display: flex; align-items: center; gap: var(--sp-1_5);
  padding: 7px var(--sp-3); font-size: var(--text-xs); line-height: 1.3;
  color: var(--text-muted); background: var(--bg-sidebar);
  border-bottom: 1px solid var(--border);
}
.sidebar-hint i { font-size: var(--text-base); flex-shrink: 0; opacity: 0.8; }

.sidebar-collapse-btn {
  flex-shrink: 0; width: 30px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; cursor: pointer;
  color: var(--text-muted); font-size: var(--text-lg);
  border-left: 1px solid var(--border);
  transition: color var(--transition), background var(--transition);
}
.sidebar-collapse-btn:hover { color: var(--text-secondary); background: rgba(255,255,255,0.04); }

.s-tab-badge {
  flex-shrink: 0;
  min-width: 16px; height: 16px; padding: 0 var(--sp-1);
  background: var(--accent); color: var(--accent-fg);
  font-size: 9px; font-weight: 700; border-radius: 8px;
  display: none; align-items: center; justify-content: center;
}
.s-tab-badge.visible { display: inline-flex; }
.s-tab-badge-warn { background: #ef4444; color: #fff; }
/* In the collapsed rail there's no label, so float the single badge onto the icon. */
.sidebar.collapsed .s-tab-badge { position: absolute; top: 3px; right: 5px; }

/* ── Sidebar panes ── */
.sidebar-pane {
  display: none; flex: 1; overflow-y: auto; overflow-x: hidden; flex-direction: column;
}
.sidebar-pane.active { display: flex; }
.sidebar-pane::-webkit-scrollbar { width: 4px; }
.sidebar-pane::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 2px; }

/* ── Properties no-selection hint ── */
.props-no-sel {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-2_5); padding: var(--sp-10) var(--sp-5); text-align: center;
  color: var(--text-muted); font-size: var(--text-xs); line-height: 1.5;
}
.props-no-sel i { font-size: 28px; opacity: 0.4; }

/* ── Accordion sidebar sections ── */
.acc-section { padding: 0; }
.acc-section:first-child .acc-header { border-top: none; }

.acc-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-2_5) var(--sp-3); cursor: pointer; user-select: none;
  background: rgba(255,255,255,0.018);
  transition: background var(--transition);
}
.acc-header:hover { background: rgba(255,255,255,0.06); }
.acc-section:not(.collapsed) > .acc-header { background: rgba(255,255,255,0.035); }

.acc-title-wrap {
  display: flex; align-items: center; gap: 7px; flex: 1; min-width: 0;
}
.acc-icon { font-size: var(--text-md); color: var(--accent); flex-shrink: 0; opacity: 0.85; }
.acc-chevron {
  font-size: var(--text-md); color: var(--text-secondary); flex-shrink: 0;
  transition: transform 0.22s ease;
}
.acc-section.collapsed .acc-chevron { transform: rotate(-90deg); }
.acc-header:hover .acc-chevron { color: var(--text-primary); }

.acc-body-grid {
  display: grid; grid-template-rows: 1fr;
  transition: grid-template-rows 0.22s ease;
}
.acc-section.collapsed .acc-body-grid { grid-template-rows: 0fr; }

.acc-body-inner {
  overflow: hidden; min-height: 0;
  padding: var(--sp-2) var(--sp-2_5) var(--sp-3);
}

/* ── Section header improvements ── */
.section-header {
  display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--sp-2_5);
}
.section-header-left { display: flex; align-items: center; gap: 7px; flex: 1; min-width: 0; }

/* ── Section badge (element count etc.) ── */
.section-badge {
  font-size: var(--text-xs); font-weight: 600;
  background: rgba(255,255,255,0.08); color: var(--text-secondary);
  padding: var(--sp-px) 7px; border-radius: 10px; min-width: 20px; text-align: center;
  flex-shrink: 0;
}

/* ── Properties hint ── */
.props-hint { font-size: var(--text-2xs); color: var(--text-muted); margin-top: var(--sp-2); line-height: 1.5; }

/* ── Auth gate ── */
.auth-gate {
  position: fixed; inset: 0; background: rgba(0,0,0,0.7); backdrop-filter: blur(8px);
  z-index: 500; display: flex; align-items: center; justify-content: center;
}
.auth-gate-card {
  background: var(--bg-modal); border: 1px solid var(--border); border-radius: var(--radius-xl);
  padding: var(--sp-10) 36px; max-width: 380px; width: 90%; text-align: center;
  box-shadow: var(--shadow-lg);
}
.auth-gate-logo { margin-bottom: var(--sp-7); }
.auth-gate-icon {
  width: 56px; height: 56px; border-radius: 14px; margin: 0 auto var(--sp-3);
  background: linear-gradient(135deg, var(--accent), var(--brand-secondary));
  display: flex; align-items: center; justify-content: center;
  font-size: 28px; color: #fff; box-shadow: 0 4px 20px var(--accent-glow);
}
.auth-gate-name { font-size: 20px; font-weight: 700; }
.auth-gate-btn {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-2);
  width: 100%; padding: var(--sp-3); font-size: var(--text-md); font-weight: 600;
  background: var(--accent); color: var(--accent-fg); border: none; border-radius: var(--radius-md);
  cursor: pointer; text-decoration: none; margin-bottom: var(--sp-2_5);
  transition: background var(--transition);
}
.auth-gate-btn:hover { background: var(--accent-hover); }
.auth-gate-guest-btn {
  width: 100%; padding: var(--sp-2_5); font-size: var(--text-base); color: var(--text-muted);
  background: transparent; border: 1px solid var(--border); border-radius: var(--radius-md);
  cursor: pointer; font-family: var(--font); transition: all var(--transition);
  display: flex; align-items: center; justify-content: center; gap: var(--sp-2);
}
.auth-gate-guest-btn:hover { border-color: rgba(255,255,255,0.18); color: var(--text-primary); }
.auth-gate-home-link {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-1);
  margin-top: var(--sp-3); font-size: var(--text-base); color: var(--text-muted);
  text-decoration: none; transition: color var(--transition);
}
.auth-gate-home-link:hover { color: var(--text-primary); }

/* ── User avatar + dropdown ── */
.user-menu-wrap { position: relative; }
.user-avatar-btn {
  display: flex; align-items: center; gap: var(--sp-1); padding: var(--sp-1) var(--sp-2) var(--sp-1) var(--sp-1);
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 99px;
  cursor: pointer; transition: all var(--transition);
}
.user-avatar-btn:hover { border-color: rgba(255,255,255,0.18); background: var(--bg-card-hover); }
.user-avatar-initials {
  width: 26px; height: 26px; border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--brand-secondary));
  color: #fff; font-size: var(--text-sm); font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.user-dropdown {
  display: none; position: absolute; top: calc(100% + 6px); right: 0;
  background: var(--bg-modal); border: 1px solid var(--border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-md);
  min-width: 200px; z-index: 50; overflow: hidden;
  animation: fadeIn 0.12s ease;
}
.user-dropdown.open { display: block; }
.user-dropdown-header { padding: var(--sp-3) var(--sp-3_5); border-bottom: 1px solid var(--border); }
.user-dropdown-name { font-size: var(--text-base); font-weight: 600; color: var(--text-primary); }
.user-dropdown-email { font-size: var(--text-xs); color: var(--text-muted); margin-top: var(--sp-0_5); }
.user-dropdown-item {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: var(--sp-2_5) var(--sp-3_5); background: none; border: none;
  color: var(--text-secondary); font-size: var(--text-base); font-family: var(--font);
  cursor: pointer; text-align: left; transition: background var(--transition);
}
.user-dropdown-item i { font-size: var(--text-lg); color: var(--text-muted); }
.user-dropdown-item:hover { background: var(--bg-card-hover); color: var(--text-primary); }
.user-dropdown-divider { height: 1px; background: var(--border); margin: var(--sp-1) 0; }
.user-dropdown-signout { color: #f87171; }
.user-dropdown-signout i { color: #f87171; }
.user-dropdown-signout:hover { background: rgba(239,68,68,0.08); }

/* ── Cloud project list (in Projects modal) ── */
.cloud-project-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-2_5) var(--sp-3); border: 1px solid var(--border); border-radius: var(--radius-md);
  margin-bottom: var(--sp-2); background: var(--bg-card); gap: var(--sp-3);
  transition: border-color var(--transition);
}
.cloud-project-row:hover { border-color: rgba(255,255,255,0.14); }
.cloud-project-name { font-size: var(--text-base); font-weight: 600; color: var(--text-primary); }
.cloud-project-meta { font-size: var(--text-xs); color: var(--text-muted); margin-top: var(--sp-0_5); }

/* ── Export dropdown ── */
.export-dropdown-wrap { position: relative; }
.export-dropdown {
  display: none; position: absolute; top: calc(100% + 6px); right: 0;
  background: var(--bg-modal); border: 1px solid var(--border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-md);
  min-width: 210px; z-index: 50; overflow: hidden;
}
.export-dropdown.open { display: block; animation: fadeIn 0.12s ease; }
.export-dropdown-item {
  display: flex; align-items: center; gap: 9px;
  width: 100%; padding: 9px var(--sp-3_5); background: none; border: none;
  color: var(--text-secondary); font-size: var(--text-sm); font-family: var(--font);
  cursor: pointer; text-align: left; transition: background var(--transition);
}
.export-dropdown-item i { font-size: var(--text-lg); color: var(--text-muted); }
.export-dropdown-item:hover { background: var(--bg-card-hover); color: var(--text-primary); }
.export-dropdown-item:hover i { color: var(--accent); }
.export-dropdown-item + .export-dropdown-item { border-top: 1px solid var(--border); }
/* Per-action AI-credit cost hint (credit-cost.js), right-aligned in the item. */
.ai-cost-badge {
  margin-left: auto; display: inline-flex; align-items: center; gap: 3px;
  font-size: var(--text-2xs); font-weight: 600; font-variant-numeric: tabular-nums;
  color: var(--text-muted); background: var(--bg-card-hover);
  padding: var(--sp-0_5) var(--sp-1_5); border-radius: 99px; white-space: nowrap; flex-shrink: 0;
}
.ai-cost-badge .ti { font-size: 1em; line-height: 1; color: inherit; }
.export-dropdown-item:hover .ai-cost-badge,
.export-dropdown-item:hover .ai-cost-badge .ti { color: var(--text-secondary); }

/* Grouped AI menu: section captions + prerequisite-gated (disabled) items */
.dropdown-section-label {
  padding: 7px var(--sp-3_5) 3px;
  font-size: 9px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-muted); opacity: .7; user-select: none;
}
.dropdown-section-label + .export-dropdown-item { border-top: none; }
.dropdown-section-label.done { color: var(--success, #22c55e); opacity: .85; }
.dropdown-section-label .ti-circle-check { color: var(--success, #22c55e); font-size: var(--text-sm); }
.export-dropdown-item:disabled { opacity: .4; cursor: not-allowed; }
.export-dropdown-item:disabled:hover { background: none; color: var(--text-secondary); }
.export-dropdown-item:disabled:hover i { color: var(--text-muted); }

/* Step-of-4 progress header at the top of the AI menu */
.ai-progress-header {
  position: relative;
  padding: 8px var(--sp-3_5) 9px;
  font-size: 10.5px; font-weight: 600; color: var(--text-secondary);
  background: var(--bg-card-hover);
  border-bottom: 1px solid var(--border);
}
.ai-progress-header i { color: var(--accent); margin-right: var(--sp-1); }
.ai-progress-header::after {
  content: ''; position: absolute; left: 0; bottom: -1px; height: 2px;
  width: var(--ai-progress-pct, 0%); background: var(--accent);
  transition: width var(--transition);
}

/* ── Design Health Score pill + breakdown popover (topbar) ── */
.health-pill-wrap { position: relative; display: inline-flex; align-items: center; }
.health-breakdown {
  display: none; position: absolute; top: calc(100% + 6px); left: 0;
  background: var(--bg-modal); border: 1px solid var(--border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-md);
  min-width: 240px; z-index: 50; padding: var(--sp-3) var(--sp-3_5); font-size: 12px;
}
.health-breakdown.is-open { display: block; animation: fadeIn 0.12s ease; }
.health-breakdown-row { display: flex; justify-content: space-between; gap: var(--sp-2_5); padding: 3px 0; color: var(--text-secondary); }
.health-breakdown-issue { display: flex; align-items: flex-start; gap: var(--sp-1_5); padding: var(--sp-1) 0; font-size: 11px; color: var(--text-muted); border-top: 1px solid var(--border); }
.health-breakdown-issue:first-of-type { border-top: none; margin-top: var(--sp-1); }

/* ── Zone setup inline (merged into Getting Started) ── */
.zone-setup-inline { margin-top: var(--sp-2_5); padding-top: var(--sp-2_5); border-top: 1px solid var(--border); }

/* ── AI Chat Panel ── */
.chat-panel {
  position: absolute; right: 0; top: 0; bottom: 0; width: 320px;
  background: var(--bg-sidebar); border-left: 1px solid var(--border);
  display: flex; flex-direction: column;
  transform: translateX(100%); transition: transform 0.22s ease;
  z-index: 360; box-shadow: -4px 0 20px rgba(0,0,0,0.3);
}
.chat-panel.open { transform: translateX(0); }
.chat-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 11px var(--sp-3_5); border-bottom: 1px solid var(--border); flex-shrink: 0;
  background: var(--bg-card);
}
.chat-messages {
  flex: 1; overflow-y: auto; padding: var(--sp-3); display: flex;
  flex-direction: column; gap: var(--sp-2);
}
.chat-messages::-webkit-scrollbar { width: 4px; }
.chat-messages::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 2px; }
@keyframes msgIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.chat-msg { display: flex; animation: msgIn 0.22s ease backwards; }
.chat-msg-user { justify-content: flex-end; animation-duration: 0.18s; }
.chat-msg-ai   { justify-content: flex-start; animation-duration: 0.25s; }
.chat-bubble {
  max-width: 85%; padding: var(--sp-2) var(--sp-3); border-radius: 10px;
  font-size: var(--text-sm); line-height: 1.55; word-break: break-word;
}
.chat-msg-user .chat-bubble { background: var(--accent); color: var(--accent-fg); border-radius: 10px 10px 2px 10px; }
.chat-msg-ai   .chat-bubble { background: var(--bg-card); color: var(--text-primary); border-radius: 10px 10px 10px 2px; border: 1px solid var(--border); }
/* Lightweight Markdown rendered inside AI bubbles (see mdToSafeHtml in app.js).
   Kept compact on purpose — full `prose` rhythm is too tall for chat bubbles. */
.chat-msg-ai .chat-bubble strong { font-weight: 600; }
.chat-msg-ai .chat-bubble .cb-head { display: block; margin: var(--sp-1_5) 0 var(--sp-0_5); font-weight: 600; color: var(--text-primary); }
.chat-msg-ai .chat-bubble .cb-head:first-child { margin-top: 0; }
.chat-msg-ai .chat-bubble ul { margin: var(--sp-1) 0; padding-left: 18px; }
.chat-msg-ai .chat-bubble li { margin: var(--sp-px) 0; }
.chat-msg-ai .chat-bubble li::marker { color: var(--accent); }
.chat-msg-ai .chat-bubble code {
  font-family: var(--font-mono); font-size: 0.92em;
  background: rgba(255,255,255,0.07); border: 1px solid var(--border);
  border-radius: 4px; padding: 0 var(--sp-1);
}
/* Animated thinking dots */
.chat-thinking { display: flex; align-items: center; gap: var(--sp-1); padding: var(--sp-2_5) var(--sp-3_5); }
.chat-thinking span {
  width: 6px; height: 6px; border-radius: 50%; background: var(--text-muted);
  animation: chatDot 1.2s infinite ease-in-out;
}
.chat-thinking span:nth-child(2) { animation-delay: 0.2s; }
.chat-thinking span:nth-child(3) { animation-delay: 0.4s; }
@keyframes chatDot { 0%,80%,100% { transform: scale(0.7); opacity:0.4; } 40% { transform: scale(1); opacity:1; } }
.chat-input-row {
  display: flex; gap: var(--sp-1_5); padding: var(--sp-2_5) var(--sp-3);
  border-top: 1px solid var(--border); flex-shrink: 0; align-items: flex-end;
}
.chat-input {
  flex: 1; padding: 7px var(--sp-2_5); background: var(--bg-input);
  border: 1px solid var(--border-input); border-radius: var(--radius-md);
  color: var(--text-primary); font-size: var(--text-sm); font-family: var(--font);
  resize: none; line-height: 1.4;
}
.chat-input:focus { outline: none; border-color: var(--border-focus); }

/* ── Team Chat Panel ── */
.team-chat-panel {
  position: absolute; right: 0; top: 0; bottom: 0; width: 300px;
  background: var(--bg-sidebar); border-left: 1px solid var(--border);
  display: flex; flex-direction: column;
  transform: translateX(100%); transition: transform 0.22s ease;
  z-index: 24; box-shadow: -4px 0 20px rgba(0,0,0,0.3);
}
.team-chat-panel.open { transform: translateX(0); }
.tc-msg {
  display: flex; gap: var(--sp-2); align-items: flex-start; padding: var(--sp-1) 0;
  animation: msgIn 0.22s ease backwards;
}
.tc-msg-own { flex-direction: row-reverse; }
.tc-avatar {
  width: 26px; height: 26px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--text-xs); font-weight: 700; color: #fff;
}
.tc-bubble-wrap { max-width: 80%; display: flex; flex-direction: column; gap: var(--sp-0_5); }
.tc-msg-own .tc-bubble-wrap { align-items: flex-end; }
.tc-meta { display: flex; gap: var(--sp-1_5); align-items: baseline; }
.tc-name { font-size: var(--text-xs); font-weight: 600; color: var(--text-secondary); }
.tc-time { font-size: var(--text-2xs); color: var(--text-muted); }
.tc-bubble {
  font-size: var(--text-sm); line-height: 1.5; padding: 7px var(--sp-2_5);
  border-radius: 10px; word-break: break-word;
}
.tc-msg:not(.tc-msg-own) .tc-bubble {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: 2px 10px 10px 10px; color: var(--text-primary);
}
.tc-msg-own .tc-bubble {
  background: #059669; color: #fff; border-radius: 10px 2px 10px 10px;
}
.tc-activity {
  font-size: var(--text-xs); color: var(--text-muted); text-align: center;
  padding: 3px 0; display: flex; align-items: center; justify-content: center; gap: var(--sp-1);
}
.tc-activity .ti { font-size: var(--text-xs); }
.team-chat-tabs {
  display: flex; flex-shrink: 0; border-bottom: 1px solid var(--border);
  background: var(--bg-card);
}
.team-chat-tab {
  flex: 1; padding: var(--sp-2) var(--sp-1); font-size: var(--text-xs); font-weight: 600;
  color: var(--text-muted); background: transparent; border: none;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  cursor: pointer; font-family: var(--font);
  display: flex; align-items: center; justify-content: center; gap: 5px;
  transition: color 0.15s, border-color 0.15s;
}
.team-chat-tab:hover { color: var(--text-secondary); }
.team-chat-tab.active { color: var(--text-primary); border-bottom-color: var(--accent); }
.team-chat-pane {
  display: flex; flex-direction: column; flex: 1; min-height: 0; overflow: hidden;
}
.btn-active { background: rgba(245,158,11,0.15) !important; }

/* ── Improved empty state ── */
.duct-list-empty {
  font-size: var(--text-xs); color: var(--text-muted); padding: var(--sp-4) var(--sp-2_5); text-align: center;
  background: rgba(255,255,255,0.02); border-radius: var(--radius-md);
  border: 1px dashed var(--border); line-height: 1.5;
}
.duct-empty-icon { font-size: 22px; display: block; margin-bottom: var(--sp-2); opacity: 0.5; }
.duct-empty-title { font-size: var(--text-sm); font-weight: 600; color: var(--text-secondary); margin-bottom: var(--sp-1); }
.duct-empty-sub { font-size: var(--text-2xs); line-height: 1.6; }

/* ── Equipment tabs ── */
.equip-tabs {
  display: flex; gap: 3px; margin-bottom: var(--sp-2);
  background: rgba(255,255,255,0.04); border-radius: var(--radius-md); padding: 3px;
}
.equip-tab {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: var(--sp-1_5);
  padding: 7px var(--sp-2); border-radius: var(--radius-sm);
  font-size: var(--text-sm); font-weight: 500; cursor: pointer;
  background: transparent; color: var(--text-muted);
  border: none; transition: all var(--transition); font-family: var(--font);
}
.equip-tab i { font-size: var(--text-base); }
.equip-tab:hover { color: var(--text-primary); }
.equip-tab.active { background: var(--bg-card); color: var(--text-primary); box-shadow: 0 1px 3px rgba(0,0,0,0.25); }
.equip-panel-header { display: flex; gap: var(--sp-1_5); margin-bottom: 7px; align-items: center; }
.equip-panel-header .unit-search { flex: 1; margin-bottom: 0; }
.library-content { padding: var(--sp-2_5); display: flex; flex-direction: column; gap: 0; }

/* ── Workflow guide steps ── */
#workflowGuide { display: flex; flex-direction: column; }
.wf-step {
  display: flex; align-items: flex-start; gap: var(--sp-2_5);
  padding: var(--sp-2_5) 0; border-top: 1px solid var(--border);
}
.wf-step:first-child { border-top: none; padding-top: var(--sp-0_5); }
.wf-icon {
  width: 24px; height: 24px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; font-size: var(--text-sm); margin-top: var(--sp-px);
}
.wf-step.done   .wf-icon { background: rgba(34,197,94,0.14);  color: #22c55e; }
.wf-step.active .wf-icon { background: var(--accent-light);   color: var(--accent); }
.wf-step.pending .wf-icon { background: rgba(255,255,255,0.05); color: var(--text-muted); }
.wf-body { flex: 1; }
.wf-label { font-size: var(--text-sm); font-weight: 600; color: var(--text-primary); line-height: 1.3; }
.wf-step.pending .wf-label { color: var(--text-muted); }
.wf-sub { font-size: var(--text-2xs); color: var(--text-muted); margin-top: var(--sp-0_5); line-height: 1.4; }
.wf-step.done .wf-sub { color: rgba(34,197,94,0.75); }
.wf-btn {
  display: inline-flex; align-items: center; gap: 5px; margin-top: 7px;
  padding: 5px 11px; border-radius: var(--radius-sm);
  font-size: var(--text-xs); font-weight: 500; cursor: pointer;
  background: var(--accent-light); color: var(--accent);
  border: 1px solid rgba(51,177,255,0.3);
  transition: all var(--transition); font-family: var(--font);
}
.wf-btn:hover { background: rgba(51,177,255,0.2); box-shadow: 0 2px 8px rgba(51,177,255,0.15); }

/* ── Room chip tweak ── */
.room-chip { gap: var(--sp-1_5); padding: var(--sp-1) var(--sp-2_5); cursor: pointer; transition: background var(--transition), border-color var(--transition); }
.room-chip:hover { background: var(--bg-card-hover); border-color: var(--accent); color: var(--text-primary); }

/* ══════════════════════════════════════════════════════════
   MOBILE RESPONSIVE  (≤ 768 px)
   ══════════════════════════════════════════════════════════ */

/* Sidebar overlay backdrop — hidden by default */
#sidebarOverlay {
  display: none; position: fixed; inset: 0;
  background: rgba(0,0,0,0.55); z-index: 39;
}
#sidebarOverlay.active { display: block; }

/* Mobile sidebar toggle — hidden on desktop */
#mobileSidebarBtn { display: none; }

/* ── Mid-width: collapse topbar action buttons to icon-only ──────────────────
   Above the 768px mobile-kebab breakpoint but below full desktop, drop the
   button text labels and chevrons so the right cluster stays on one row and
   doesn't crowd the floor tabs / Search pill. The .btn-label / .btn-chevron
   wrappers exist precisely for this; tooltips (title=) carry the meaning. ── */
@media (min-width: 769px) and (max-width: 1180px) {
  .topbar-actions .btn-label,
  .topbar-actions .btn-chevron { display: none; }
  .topbar-actions .btn {
    padding: 5px var(--sp-2); gap: 0;
  }
}

@media (max-width: 768px) {

  /* ── Sidebar → off-canvas drawer ── */
  .sidebar {
    position: fixed; left: -100%; top: 0; bottom: 0;
    width: 86vw; max-width: 340px;
    z-index: 40; transition: left 0.25s ease;
    box-shadow: 4px 0 24px rgba(0,0,0,0.4);
  }
  .sidebar.mobile-open { left: 0; }
  /* A drawer should never be collapsed to a rail on mobile */
  .sidebar.collapsed { width: 86vw; max-width: 340px; }
  .sidebar.collapsed .sidebar-pane { display: flex !important; }
  .sidebar.collapsed .sidebar-tabs { flex-direction: row; }
  .sidebar.collapsed .sidebar-hint { display: flex; }
  .sidebar.collapsed .s-tab-label { display: inline; }

  /* Drawer header with close button */
  .sidebar-mobile-header {
    display: flex; align-items: center; justify-content: space-between;
    flex-shrink: 0; padding: var(--sp-2_5) var(--sp-3);
    border-bottom: 1px solid var(--border); background: var(--bg-sidebar);
  }
  .sidebar-mobile-title {
    display: flex; align-items: center; gap: 7px;
    font-size: var(--text-base); font-weight: 600; color: var(--text-secondary);
  }
  .sidebar-mobile-close {
    width: 36px; height: 36px; display: flex; align-items: center; justify-content: center;
    background: none; border: none; cursor: pointer;
    color: var(--text-muted); font-size: var(--text-2xl); border-radius: var(--radius-md);
  }
  .sidebar-mobile-close:active { background: rgba(255,255,255,0.08); color: var(--text-primary); }

  /* Collapse control is meaningless inside a drawer */
  .sidebar-collapse-btn { display: none; }

  /* Touch-friendly tabs */
  .sidebar-tab { padding: var(--sp-3_5) var(--sp-1); font-size: var(--text-base); }
  .sidebar-tab i { font-size: var(--text-2xl); }

  /* Show hamburger button */
  #mobileSidebarBtn { display: inline-flex; }

  /* ── Toolbar shell — anchor point for the dropdown sheet ── */
  .toolbar { position: relative; }

  /* ── Topbar — slim down ── */
  .topbar { padding: 0 var(--sp-2_5); gap: var(--sp-1_5); height: 48px; }
  /* While the actions menu is open, lift the whole topbar stacking context above
     the bottom toolbar dock + its sheet (55/56) so the dropdown — which extends
     down the screen — paints over the floating "Tools" pill instead of being
     covered by it. Scoped to the open state so the off-canvas sidebar drawer
     (z-index 40) still covers the resting topbar as before. */
  .topbar:has(#btnMobileMenu[aria-expanded="true"]) { z-index: 70; }
  .logo { font-size: var(--text-base); }
  .logo-word { font-size: var(--text-md); }
  .logo-mark { width: 24px; height: 24px; }
  .topbar-project-chip { display: none; }

  /* ── Floor tabs — kept (floor switching has no other mobile entry point), but
     constrained so 3+ tabs scroll horizontally inside the 46px bar instead of
     colliding with the kebab. Tabs don't shrink; scrollbar is hidden. ── */
  .floor-tabs {
    flex: 1 1 auto; min-width: 0; margin-left: var(--sp-1);
    overflow-x: auto; overflow-y: hidden;
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .floor-tabs::-webkit-scrollbar { display: none; }
  .floor-tab, .floor-tab-add { flex-shrink: 0; }

  /* ── Topbar actions — collapsed behind a kebab "⋯" trigger, opened as a
     dropdown menu instead of overflowing / scrolling off the right edge.
     Wired by ui-next.js + disclosure.js (same pattern as the tools sheet);
     ui-next.css adds the glass skin. ── */
  .topbar .topbar-menu-trigger { display: inline-flex; margin-left: auto; }
  .topbar-actions {
    flex-direction: column; gap: var(--sp-0_5);
    position: absolute; right: var(--sp-2_5); top: 100%;
    margin-top: var(--sp-1_5); width: 244px; max-height: 72vh; overflow-y: auto;
    background: var(--bg-modal); border: 1px solid var(--border);
    border-radius: var(--radius-md); box-shadow: var(--shadow-md);
    padding: var(--sp-1_5); z-index: 56;
  }
  .topbar-actions[hidden] { display: none; }

  /* The floating canvas overlays (active-tool pill, "did you know" hint) sit at
     z-index 100 — above the dropdown menus — and the tool pill is
     pointer-events:none, so it visibly punches through an open menu. Hide them
     while either mobile menu is open. */
  body:has(#btnMobileMenu[aria-expanded="true"]) .canvas-tool-pill,
  body:has(#btnMobileMenu[aria-expanded="true"]) .canvas-hint,
  body:has(#btnMobileTools[aria-expanded="true"]) .canvas-tool-pill,
  body:has(#btnMobileTools[aria-expanded="true"]) .canvas-hint { display: none; }

  /* Each top-level action fills the row; the dropdown wrappers must not clip. */
  .topbar-actions > .btn,
  .topbar-actions > .btn-icon,
  .topbar-actions .export-dropdown-wrap,
  .topbar-actions .user-menu-wrap { width: 100%; }
  .topbar-actions .btn,
  .topbar-actions .user-avatar-btn {
    width: 100%; justify-content: flex-start; min-height: 42px;
  }
  .topbar-actions .btn-icon { width: 100%; justify-content: flex-start; height: 42px; gap: 9px; }
  .topbar-actions .topbar-sep { display: none; }
  /* Reveal the text labels for the otherwise icon-only rows (Messages, Account)
     so every row in the dropdown reads as a labelled action, not a bare icon. */
  .topbar-actions .topbar-action-label { display: inline; }
  .topbar-actions .user-avatar-btn { gap: 9px; }

  /* Sub-menus (File/AI/Export/account…) flow inline as an accordion instead of
     absolute-positioning out of the scrolling sheet. */
  .topbar-actions .export-dropdown,
  .topbar-actions .user-dropdown {
    position: static; min-width: 0; width: 100%;
    margin: var(--sp-0_5) 0 var(--sp-1_5); box-shadow: none;
    background: var(--bg-card); border-radius: var(--radius-sm);
  }

  /* ── Toolbar — collapsed behind a "Tools" trigger, opened as a dropdown
     sheet (#toolbarRows) instead of horizontally-scrolling rows. Wired by
     ui-next.js + disclosure.js; this block is the layout, ui-next.css adds
     the glass skin. ── */
  .toolbar-mobile-trigger { display: flex; align-items: center; justify-content: center; height: 44px; }
  .toolbar-rows {
    display: flex; flex-direction: column; gap: var(--sp-1);
    position: absolute; left: var(--sp-2); right: var(--sp-2); top: 100%;
    margin-top: var(--sp-1_5); max-height: 60vh; overflow-y: auto;
    background: var(--bg-modal); border: 1px solid var(--border);
    border-radius: var(--radius-md); box-shadow: var(--shadow-md);
    padding: var(--sp-2); z-index: 56;
  }
  .toolbar-rows[hidden] { display: none; }

  /* Rows become uniform 3-column grids so tools line up instead of ragged
     wrapping. Structural separators (dividers, spacer) and the desktop mode
     caption are noise here — hide them. Groups/palette span the full width. */
  .toolbar-row {
    display: grid; grid-template-columns: repeat(3, 1fr);
    gap: var(--sp-1_5); align-items: stretch;
    height: auto; padding: var(--sp-1) 0; overflow-x: visible;
  }
  .toolbar-row:nth-child(2) { margin-top: var(--sp-1); padding-top: var(--sp-2_5); border-top: 1px solid var(--border); }
  .toolbar-rows .tool-divider,
  .toolbar-rows .toolbar-spacer,
  .toolbar-rows #modeIndicatorLabel,
  .toolbar-rows .tool-label { display: none !important; }
  .toolbar-rows .btn { justify-content: flex-start; min-height: 42px; width: 100%; }
  .toolbar-rows #btn-select { grid-column: 1 / -1; justify-content: center; }
  .toolbar-rows .btn-group { grid-column: 1 / -1; display: grid !important; grid-template-columns: 1fr 1fr; gap: var(--sp-px); }
  .toolbar-rows .btn-group .btn { justify-content: center; }
  /* The plan/duct tool groups are inline-flex wrappers toggled show/hide via
     inline display:flex|none. Span them full width and lay their buttons out as
     a nested 3-col grid — matched only while shown so the hidden group stays
     hidden (its inline display:none has no "flex" to match). */
  .toolbar-rows #toolbar-plan-tools,
  .toolbar-rows #toolbar-duct-tools {
    grid-column: 1 / -1; grid-template-columns: repeat(3, 1fr); gap: var(--sp-1_5);
  }
  .toolbar-rows #toolbar-plan-tools[style*="flex"],
  .toolbar-rows #toolbar-duct-tools[style*="flex"] { display: grid !important; }
  .toolbar-rows #colorPalette { grid-column: 1 / -1; justify-content: center; gap: var(--sp-1_5); }
  .toolbar-rows .duct-width-select { grid-column: 1 / -1; width: 100% !important; min-height: 42px; }
  .btn { padding: 7px 9px; font-size: var(--text-sm); min-height: 44px; }
  .shortcut-hint { display: none; }
  /* Keyboard shortcut badges are dead weight on touch — no physical keyboard
     means they're not actionable, and they widen every button in the already
     horizontally-scrolling toolbar rows. */
  .btn kbd { display: none; }
  .btn-icon { width: 44px; height: 44px; font-size: var(--text-lg); }
  .tool-divider { height: 16px; margin: 0 3px; }
  .tool-label { display: none; }
  .duct-width-select { width: 82px; font-size: var(--text-xs); }

  /* ── Status bar — hide noisy items, keep Elements + zoom ── */
  .status-bar { height: 32px; padding: 0 var(--sp-2_5); }
  #statusSnap { display: none; }

  /* ── Touch targets — bump tiny in-panel controls to a ~44px hit area on touch
     (iOS HIG / Material minimum). Visual size of swatches is kept small via an
     inner box; the element box (and its padding) carries the larger tap region
     so layouts don't bloat. ── */
  .layer-vis-btn, .layer-lock-btn,
  .status-zoom-btn { min-width: 44px; min-height: 44px; }
  .color-swatch {
    width: 44px; height: 44px; padding: 13px;
    background-clip: content-box; box-sizing: border-box;
  }
  .duct-swatch { width: 44px; height: 44px; }

  /* ── Modals — full-width on small screens ── */
  .modal { padding: var(--sp-5) var(--sp-4); }
  .modal-title { font-size: var(--text-lg); }
  .settings-modal, .library-modal { max-width: 100%; }
  .theme-grid { grid-template-columns: repeat(3, 1fr); }
  .icon-grid  { grid-template-columns: repeat(6, 1fr); }

  /* ── Auth gate card ── */
  .auth-gate-card { padding: var(--sp-7) var(--sp-5); }

  /* ── Upload overlay box ── */
  .upload-box { padding: var(--sp-8) var(--sp-6); }

  /* ── Chat panel — full-width on mobile ── */
  .chat-panel { width: 100%; }

  /* ── Team chat panel — full-width on mobile (mirror .chat-panel) ── */
  .team-chat-panel { width: 100%; right: 0; left: 0; }

  /* ── iOS focus-zoom guard ──
     iOS Safari force-zooms the page whenever a focused text-entry field has a
     font-size below 16px. Every small editor input (.prop-input 12px,
     .unit-search 11px, .chat-input 12px, .api-key-input 12px, .duct-width-select
     11px …) trips this. Pin them all to 16px on touch widths only — desktop
     sizes (set elsewhere) are untouched. */
  input, select, textarea,
  .prop-input, .unit-search, .chat-input, .api-key-input,
  .duct-width-select, .cmd-input {
    font-size: 16px !important;
  }

  /* ── Toast — full-width at bottom ── */
  .toast-container { bottom: 60px; right: 10px; left: 10px; }
  .toast { max-width: 100%; }

  /* ── Canvas hint — span width below the centred tool pill ── */
  .canvas-hint { top: 54px; left: 10px; right: 10px; transform: translateY(-6px); max-width: none; font-size: var(--text-xs); }
  .canvas-hint.visible { transform: translateY(0); }

  /* ── Dropdowns — prevent clipping off right edge ── */
  .export-dropdown { right: auto; left: 0; }

  /* ── Collab "changes saved" banner — wrap-safe so long names don't overflow a
     narrow phone (was position:fixed + white-space:nowrap). Stays centred. ── */
  .collab-changes-banner {
    max-width: calc(100vw - 24px);
    white-space: normal;
  }
}

/* ── Context Menu ── */
.context-menu {
  position: fixed; z-index: 500; display: none;
  background: var(--bg-modal); border: 1px solid var(--border);
  border-radius: var(--radius-md); padding: var(--sp-1);
  box-shadow: var(--shadow-lg); min-width: 180px;
  animation: fadeIn 0.12s ease;
  user-select: none;
  max-height: calc(100vh - 16px); overflow-y: auto;
}
.context-menu.open { display: block; }
.context-menu-item {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: 7px var(--sp-2_5); font-size: var(--text-sm); font-weight: 500;
  color: var(--text-secondary); border-radius: var(--radius-sm);
  cursor: pointer; transition: all 0.1s ease;
  border: 1px solid transparent;
}
.context-menu-item i { font-size: var(--text-md); width: 16px; text-align: center; flex-shrink: 0; }
.context-menu-item .ctx-shortcut { margin-left: auto; font-size: var(--text-2xs); color: var(--text-muted); }
.context-menu-item:hover { background: rgba(255,255,255,0.06); color: var(--text-primary); border-color: var(--border); }
.context-menu-item.danger { color: #f87171; }
.context-menu-item.danger:hover { background: rgba(239,68,68,0.08); border-color: rgba(239,68,68,0.2); }
.context-menu-separator { height: 1px; background: var(--border); margin: var(--sp-1) 0; }

/* ── Command Palette ── */
.cmd-palette-bg {
  position: fixed; inset: 0; z-index: 600;
  background: rgba(0,0,0,0.55); backdrop-filter: blur(4px);
  display: none; align-items: flex-start; justify-content: center;
  padding-top: 80px;
}
.cmd-palette-bg.open { display: flex; animation: fadeIn 0.15s ease; }
.cmd-palette {
  width: 100%; max-width: 520px; margin: 0 var(--sp-4);
  background: var(--bg-modal); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.cmd-input-wrap {
  display: flex; align-items: center; gap: var(--sp-2_5);
  padding: var(--sp-3) var(--sp-3_5); border-bottom: 1px solid var(--border);
}
.cmd-input-wrap i { font-size: var(--text-xl); color: var(--text-muted); flex-shrink: 0; }
.cmd-input {
  flex: 1; background: transparent; border: none; outline: none;
  font-size: var(--text-md); color: var(--text-primary); font-family: var(--font);
}
.cmd-input::placeholder { color: var(--text-muted); }
.cmd-input-wrap .cmd-esc {
  font-size: var(--text-2xs); color: var(--text-muted); background: rgba(255,255,255,0.06);
  border: 1px solid var(--border); border-radius: 4px; padding: var(--sp-0_5) 5px; flex-shrink: 0;
}
.cmd-results { max-height: 340px; overflow-y: auto; padding: var(--sp-1); }
.cmd-result-item {
  display: flex; align-items: center; gap: var(--sp-2_5);
  padding: 9px var(--sp-2_5); border-radius: var(--radius-sm);
  cursor: pointer; font-size: var(--text-base); color: var(--text-secondary);
  border: 1px solid transparent; transition: all 0.1s ease;
}
.cmd-result-item i { font-size: var(--text-lg); width: 18px; text-align: center; flex-shrink: 0; }
.cmd-result-item .cmd-label { flex: 1; }
.cmd-result-item .cmd-shortcut { font-size: var(--text-2xs); color: var(--text-muted); flex-shrink: 0; }
.cmd-result-item:hover, .cmd-result-item.active {
  background: var(--accent-light); color: var(--text-primary); border-color: rgba(51,177,255,0.2);
}
.cmd-result-item.active i, .cmd-result-item:hover i { color: var(--accent); }
.cmd-group-label {
  font-size: var(--text-2xs); font-weight: 600; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.07em;
  padding: var(--sp-2) var(--sp-2_5) var(--sp-1);
}
.cmd-empty { padding: var(--sp-6); text-align: center; font-size: var(--text-base); color: var(--text-muted); }

/* ── Floating Properties Panel ── */
.floating-props-panel {
  position: fixed; z-index: 350;
  right: 16px; top: 108px;
  width: 252px;
  background: var(--bg-modal); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  overflow: hidden; max-height: calc(100vh - 130px); overflow-y: auto;
  animation: fadeIn 0.15s ease;
  transition: right 0.22s ease;
}
/* Shift props panel left when team chat is open (300px panel + 16px gap) */
body.team-chat-open .floating-props-panel { right: 316px; }
.floating-props-handle {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-2) var(--sp-2_5); cursor: move;
  background: rgba(255,255,255,0.03);
  border-bottom: 1px solid var(--border);
  user-select: none;
}
.floating-props-handle:hover { background: rgba(255,255,255,0.05); }

/* ── Dashboard team management rows ─────────────────────────────────────── */
.dash-team-row {
  display: flex; align-items: center; gap: var(--sp-2_5);
  padding: 9px 0; border-bottom: 1px solid rgba(255,255,255,0.06);
}
.dash-team-row:last-child { border-bottom: none; }
.dash-team-avatar {
  width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--text-base); font-weight: 700; color: #fff;
}
.dash-team-info { flex: 1; min-width: 0; }
.dash-team-name { font-size: var(--text-base); color: var(--text-primary, #f8fafc); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dash-team-role { font-size: var(--text-xs); color: var(--text-muted, #64748b); margin-top: var(--sp-px); }

/* ── Real-time Collaboration ─────────────────────────────────────────────── */
/* Floats just under the topbar, top-right of the canvas (rendered into
   #canvasArea, which is the absolute-positioning context like .canvas-hint). */
.collab-presence-bar {
  /* Floats top-right of the canvas, dropped well below the topbar so it clears
     the account avatar / user menu and reads as a canvas overlay rather than
     hugging the menu. z-index also stays below the topbar's stacking context
     (z-index 30) so an open dropdown still paints over the avatars. */
  position: absolute; top: 84px; right: 48px; z-index: 25;
  display: flex; align-items: center; gap: var(--sp-1);
  /* No pill chrome — a bg-modal pill blends into the topbar. The colored avatar
     circles float directly on the canvas, each with its own ring + shadow. */
  background: none; border: none; padding: 0; box-shadow: none;
  pointer-events: auto;
}
.collab-avatar {
  width: 34px; height: 34px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--text-sm); font-weight: 700; color: #fff;
  border: 2px solid rgba(255,255,255,0.9); cursor: default;
  box-shadow: 0 2px 8px rgba(0,0,0,0.45);
  transition: transform 0.15s;
}
.collab-avatar:hover { transform: scale(1.12); }
.collab-avatar-active {
  border-color: #a78bfa;
  /* purple presence ring + a drop shadow so it lifts off the canvas */
  box-shadow: 0 0 0 2px rgba(167,139,250,0.3), 0 2px 8px rgba(0,0,0,0.45);
}
.collab-avatar-typing {
  animation: collab-pulse 1s ease-in-out infinite;
}
@keyframes collab-pulse {
  0%, 100% { box-shadow: 0 0 0 2px rgba(99,102,241,0.3); }
  50%       { box-shadow: 0 0 0 4px rgba(99,102,241,0.6); }
}

/* Changes-available banner */
.collab-changes-banner {
  position: fixed; top: 52px; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: var(--sp-2_5);
  background: #1e1b4b; border: 1px solid #6366f1;
  border-radius: 10px; padding: var(--sp-2_5) var(--sp-4);
  font-size: var(--text-base); color: #e0e7ff;
  box-shadow: 0 4px 20px rgba(99,102,241,0.4);
  z-index: 4000; white-space: nowrap;
  animation: slideDown 0.25s ease;
}
.collab-changes-btn {
  padding: var(--sp-1) var(--sp-3); background: #6366f1; color: #fff;
  border: none; border-radius: 6px; font-size: var(--text-sm); font-weight: 600;
  cursor: pointer; transition: background 0.15s;
}
.collab-changes-btn:hover { background: #4f46e5; }
.collab-changes-close {
  background: none; border: none; color: #94a3b8;
  cursor: pointer; padding: var(--sp-0_5) var(--sp-1); font-size: var(--text-md);
  display: flex; align-items: center;
}
.collab-changes-close:hover { color: #e2e8f0; }

@keyframes slideDown {
  from { transform: translateX(-50%) translateY(-12px); opacity: 0; }
  to   { transform: translateX(-50%) translateY(0);     opacity: 1; }
}

/* Touch gestures belong to the canvas (in-app pan/pinch-zoom), not the page.
   touch-action:none must sit on the elements that actually receive the touch —
   the canvasArea and the Konva-generated canvases inside the stage div. */
#canvasArea,
#konvaStageDiv,
#konvaStageDiv canvas { touch-action: none; }

/* Read-only mode for viewer role */
body.nd-readonly #mainCanvas,
body.nd-readonly #konvaStageDiv { cursor: default !important; }
body.nd-readonly .toolbar .btn:not(#btnUndo):not(#btnRedo):not(#btnSnap):not(#btnRooms) {
  opacity: 0.4; pointer-events: none;
}
body.nd-readonly .toolbar .btn-icon:not(#btnUndo):not(#btnRedo) {
  opacity: 0.4; pointer-events: none;
}
body.nd-readonly #btnSelect { opacity: 1 !important; pointer-events: auto !important; }

/* Team modal collaborator list */
.team-collab-row {
  display: flex; align-items: center; gap: var(--sp-2_5);
  padding: var(--sp-2) 0; border-bottom: 1px solid rgba(255,255,255,0.06);
}
.team-collab-row:last-child { border-bottom: none; }
.team-collab-avatar {
  width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--text-sm); font-weight: 700; color: #fff;
}
.team-collab-info { flex: 1; min-width: 0; }
.team-collab-name { font-size: var(--text-base); color: var(--text-primary, #f8fafc); font-weight: 500; }
.team-collab-role { font-size: var(--text-xs); color: var(--text-muted, #64748b); margin-top: var(--sp-px); }
.team-collab-pending {
  display: inline-block; font-size: var(--text-2xs); font-weight: 600;
  color: #f59e0b; background: rgba(245,158,11,0.1);
  border: 1px solid rgba(245,158,11,0.3);
  border-radius: 4px; padding: var(--sp-px) 5px; margin-left: var(--sp-1_5);
  vertical-align: middle;
}

/* ══════════════════════════════════════════════════════════════
   REFINED GRAPHITE — app shell: layered chrome, instrument type, motion
   (loaded last so it layers over the base component styles above)
   ══════════════════════════════════════════════════════════════ */

/* Chrome surfaces float on the L0 canvas shell with a crisp top-light edge */
.topbar { box-shadow: var(--edge-light), 0 1px 0 rgba(0,0,0,0.4); }
.toolbar { box-shadow: var(--edge-light); }

/* Side/library/property panels and modals read as raised material */
.sidebar { box-shadow: var(--edge-light); }
.floating-props-panel, .chat-panel { box-shadow: var(--shadow-lg); }
.modal { box-shadow: var(--shadow-lg); }

/* Instrument numerics — mono + tabular figures on data readouts.
   Numeric property inputs, status counters and zoom readout read like gauges. */
.prop-input[type="number"], .duct-width-select,
.status-value, .status-zoom-label {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  letter-spacing: -0.01em;
}

/* One decisive accent: gradient underline on the active sidebar tab */
.sidebar-tab.active {
  border-bottom-color: transparent;
  background-image: var(--accent-line);
  background-repeat: no-repeat;
  background-position: bottom;
  background-size: 100% 2px;
}

/* Primary action buttons carry the milled top-light edge */
.btn.active, .btn-primary { box-shadow: var(--edge-light); }

/* Focus rings keyed to the signature accent */
.prop-input:focus, .duct-width-select:focus,
.api-key-input:focus, .unit-search:focus, .chat-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Respect reduced-motion */
@media (prefers-reduced-motion: reduce) {
  .collab-avatar, .collab-avatar-typing { animation: none; transition: none; }
  .modal-bg.open .modal { animation: none; }
}

