﻿/* ============================================================
   DigitalClay3D — Application Styles
   Aesthetic: Industrial-precision tooling UI with warm clay accents
   ============================================================ */

:root {
    /* Base palette — dark workshop */
    --bg-primary: #1a1a1e;
    --bg-secondary: #222226;
    --bg-panel: #2a2a2f;
    --bg-input: #1e1e22;
    --bg-hover: #333338;
    --bg-active: #3a3a40;

    /* Clay accent tones */
    --accent: #c47a4a;
    --accent-light: #d9956b;
    --accent-dim: #8b5a3a;
    --accent-glow: rgba(196, 122, 74, 0.15);

    /* Text */
    --text-primary: #e8e4e0;
    --text-secondary: #9e9a95;
    --text-muted: #6b6762;
    --text-accent: #d9956b;

    /* Borders */
    --border: #3a3a3f;
    --border-light: #4a4a50;
    --border-accent: #c47a4a;

    /* Status */
    --success: #5fa86b;
    --warning: #d4a84b;
    --danger: #c45454;
    --info: #5a8ac4;

    /* Sizing */
    --sidebar-width: 280px;
    --toolbar-height: 60px;
    --panel-radius: 6px;
    --input-radius: 4px;

    /* Typography scale — three tiers used across the whole app.
       Phase 1 of the UI refresh sized these for comfortable reading at
       a normal sitting distance on a 1080p monitor.
       --ui-scale lets a future Settings pane multiply everything (90/100/110/125%). */
    --ui-scale:    1.0;
    --font-micro:  calc(11px * var(--ui-scale));   /* captions, hints */
    --font-small:  calc(12px * var(--ui-scale));   /* form labels, slim controls */
    --font-base:   calc(14px * var(--ui-scale));   /* body, primary controls */
    --font-large:  calc(16px * var(--ui-scale));   /* panel section titles */
    --font-emph:   calc(18px * var(--ui-scale));   /* dialog / modal titles */

    /* Fonts */
    --font-ui: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    --font-mono: 'JetBrains Mono', 'Cascadia Code', monospace;
}

/* ---- Reset & Base ---- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html, body, #app {
    height: 100%; width: 100%;
    overflow: hidden;
    background: var(--bg-primary);
    color: var(--text-primary);
    font-family: var(--font-ui);
    font-size: var(--font-base);
    line-height: 1.45;
    -webkit-font-smoothing: antialiased;
}

/* ---- Loading Screen ---- */
.loading-screen {
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    height: 100%; gap: 18px; color: var(--text-secondary);
}
.loading-logo {
    width: 96px; height: auto;
    filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.45));
    animation: logo-rise 0.6s ease-out;
}
@keyframes logo-rise {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}
.loading-spinner {
    width: 32px; height: 32px; border-radius: 50%;
    border: 3px solid var(--border);
    border-top-color: var(--accent);
    animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---- Error UI ---- */
#blazor-error-ui {
    display: none; position: fixed; bottom: 0; width: 100%;
    padding: 10px; background: var(--danger); color: white;
    text-align: center; z-index: 9999;
}
#blazor-error-ui .reload { color: white; text-decoration: underline; margin-left: 8px; }
#blazor-error-ui .dismiss { cursor: pointer; margin-left: 12px; }

/* ============================================================
   Layout Shell
   ============================================================ */
.app-shell {
    display: grid;
    grid-template-columns: var(--sidebar-width) 1fr;
    /* Toolbar row uses min-content so it can grow when buttons wrap (narrow windows). */
    grid-template-rows: minmax(var(--toolbar-height), max-content) 1fr auto;
    grid-template-areas:
        "toolbar toolbar"
        "sidebar viewport"
        "sidebar statusbar";
    height: 100vh;
}

/* Profile-docked layout: three columns. The profile editor is "popped out" of the
   sidebar and lives in its own column between the sidebar and the 3D viewport so
   you can edit the silhouette while still seeing the model. The grid handles
   resizing automatically; viewport3d.js listens for window.resize so the canvas
   re-fits when this column appears/disappears (we dispatch one on toggle). */
.app-shell.profile-docked {
    grid-template-columns: var(--sidebar-width) minmax(360px, 38vw) 1fr;
    grid-template-areas:
        "toolbar toolbar  toolbar"
        "sidebar profile  viewport"
        "sidebar profile  statusbar";
}

/* Settings dock: docked column anchored just right of the left sidebar so the
   3D viewport stays visible and live-previews every Defaults / Rendering /
   Experimental change. position:fixed (vs. grid-area) lets us keep the existing
   modal markup in place and avoid a 400+-line relocation; we instead push the
   viewport-area's padding-left so the canvas isn't hidden behind the dock. */
:root { --settings-dock-width: min(420px, 32vw); }

.settings-dock {
    position: fixed;
    top: var(--toolbar-height);
    left: var(--sidebar-width);
    bottom: 0;
    width: var(--settings-dock-width);
    z-index: 60;
    background: var(--bg-panel);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    min-height: 0;
    box-shadow: 4px 0 12px rgba(0, 0, 0, 0.3);
}

/* When the profile dock is open at the same time, slide the settings dock past
   it so they don't visually overlap. The profile dock occupies the next grid
   column whose width is the same minmax(360px, 38vw) used in app.css:127. */
.app-shell.profile-docked .settings-dock {
    left: calc(var(--sidebar-width) + min(38vw, max(360px, 38vw)));
}

/* Push viewport content over so the model isn't hidden behind the dock. */
.app-shell.settings-docked .viewport-area {
    padding-left: var(--settings-dock-width);
}
.app-shell.profile-docked.settings-docked .viewport-area {
    padding-left: 0; /* profile-docked already has its own column; dock floats over the profile */
}

/* When the settings dock is open the dimensions panel hides entirely.
   Even with viewport-area's padding-left already shifting the canvas right,
   the dimensions panel + Settings header end up visually competing for the
   same horizontal slot, and there's no useful info on Dimensions while the
   user is mid-edit in Settings. Cleanest outcome: hide it until Settings
   closes (the dimensions toggle state is preserved, so it reappears
   automatically when the user dismisses the dock). */
.app-shell.settings-docked .dimensions-panel {
    display: none;
}

/* Graph editor split-mode: the editor is fixed-positioned along the right edge
   with a dynamic --graph-editor-pct width set inline by the parent. Shrink the
   viewport-area (and any docked profile column) by the same amount so the 3D
   canvas isn't hidden behind the editor. */
.app-shell.graph-editor-docked .viewport-area {
    padding-right: var(--graph-editor-pct, 55vw);
}

/* Pottery wheel mode: the pottery-panel is a fixed-width left-docked column
   inside the viewport-area. Push the 3D canvas right by the panel's width so
   it isn't covered (the panel was overlaying the canvas before this rule was
   added — the spinning pot ended up centred under the tools, making manual
   rotation awkward). The 360 / 560 px figures must match the .pottery-panel
   widths declared above. */
.app-shell.pottery-docked .viewport-area {
    padding-left: 360px;
}
.app-shell.pottery-docked.pottery-expanded .viewport-area {
    padding-left: min(560px, calc(100vw - 320px));
}

.settings-dock-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 14px;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border);
    color: var(--accent-light);
    font: 700 var(--font-large) var(--font-ui);
}
.settings-dock-header .spacer { flex: 1; }
.settings-dock .settings-tab-strip { padding: 8px 14px 0 14px; }
.settings-dock .settings-tab-content {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 14px 16px;
}
.settings-dock-footer {
    padding: 10px 14px;
    border-top: 1px solid var(--border);
    background: var(--bg-secondary);
    display: flex;
    align-items: center;
    gap: 8px;
}
.settings-dock-footer .save-status {
    flex: 1;
    font-size: var(--font-micro);
}
.profile-dock {
    grid-area: profile;
    background: var(--bg-secondary);
    border-right: 1px solid var(--border);
    padding: 12px 14px;
    overflow: auto;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.profile-dock-header {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: var(--font-small);
    font-weight: 600;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--border);
}
.profile-dock-header .spacer { flex: 1; }
.profile-dock .profile-editor {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.profile-dock .profile-canvas {
    flex: 1;
    width: 100%;
    height: auto;
    min-height: 0;
}
.sidebar-profile-placeholder {
    padding: 16px 12px;
    text-align: center;
    font-size: var(--font-micro);
    color: var(--text-muted);
    background: var(--bg-input);
    border: 1px dashed var(--border);
    border-radius: 5px;
}

/* ---- Top Toolbar ---- */
.toolbar {
    grid-area: toolbar;
    display: flex; align-items: center; gap: 2px;
    padding: 6px 8px;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border);
    /* position:relative + an explicit z-index higher than every floating panel
       in the app (settings dock = 60, pottery panel = 100, expanded profile
       editor = 950) so dropdown menus from File/Edit/View/Tools/Help are never
       covered by any popout. Grid items with z-index ≠ auto create a stacking
       context, so the children's own z-index (.view-menu at 200) is *capped*
       by this value at the root level — the toolbar's z-index must therefore
       beat anything that floats below it. Stays under the splash/error overlays
       (9999) which intentionally cover everything. */
    position: relative;
    z-index: 1000;

    /* Wrap to additional rows instead of clipping when the window is narrower than the
       total content width. min-width: 0 is REQUIRED — grid items default to min-width:auto
       which prevents them from shrinking below their content's intrinsic size. Without this
       override, flex-wrap never gets a chance to trigger because the toolbar stays as wide
       as its content. */
    flex-wrap: wrap;
    row-gap: 4px;
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
    min-height: var(--toolbar-height);
}

.toolbar-group {
    display: flex; align-items: center; gap: 2px;
    padding: 0 6px;
    flex-shrink: 0;            /* keep buttons within a group together as a unit */
}

.toolbar-group + .toolbar-group {
    border-left: 1px solid var(--border);
}

/* Force the spacer to take the full row width so subsequent groups (View / Reset) wrap to a
   new line on narrow windows instead of being pushed off the right edge. On a wide enough
   window the spacer simply behaves like flex:1. */
.toolbar-spacer {
    flex: 1 0 auto;
    min-width: 0;
}

.toolbar-brand {
    display: flex;
    flex-direction: column;
    justify-content: center;
    /* Fill the column above the sidebar — toolbar has 8px left padding, so the brand's
       right edge lands exactly at the sidebar's right edge (var(--sidebar-width)). */
    width: calc(var(--sidebar-width) - 8px);
    box-sizing: border-box;
    margin-right: 0;
    padding: 2px 10px 2px 0;
    user-select: none;
    flex-shrink: 0;          /* never let the brand collapse below its intrinsic width */
}

/* Modal shown while STL/OBJ export is running. Backdrop dims the app, card holds a
   spinner + status. Centred via flex on the backdrop. */
.export-modal-backdrop {
    position: fixed; inset: 0;
    background: rgba(0, 0, 0, 0.55);
    z-index: 6000;
    display: flex; align-items: center; justify-content: center;
}
.export-modal-card {
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 28px 36px;
    min-width: 280px;
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.55);
    text-align: center;
    color: var(--text-primary);
    font-family: 'DM Sans', Inter, 'Segoe UI', sans-serif;
}
.export-modal-spinner {
    width: 36px; height: 36px;
    margin: 0 auto 14px;
    border: 4px solid rgba(255, 255, 255, 0.18);
    border-top-color: var(--accent-light);
    border-radius: 50%;
    animation: export-spin 0.9s linear infinite;
}
@keyframes export-spin {
    to { transform: rotate(360deg); }
}
.export-modal-title {
    font-size: calc(18px * var(--ui-scale));
    font-weight: 700;
    margin-bottom: 6px;
}
.export-modal-status {
    font-size: calc(13px * var(--ui-scale));
    color: var(--text-muted);
}

/* Toolbar brand: vase image on the LEFT (horizontal), wordmark + "By CosmicBlue..." stacked
   vertically to its right. Need to override the earlier .toolbar-brand rule above which sets
   flex-direction: column and a fixed width — both wrong for this layout. */
.toolbar-brand {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 10px;
    width: auto;
}
.toolbar-logo-icon {
    height: 56px;
    width: auto;
    display: block;
    flex-shrink: 0;
    background: transparent;
}
.toolbar-brand-text {
    display: flex;
    flex-direction: column;
    justify-content: center;
    line-height: 1;
}
.toolbar-logo-text {
    color: var(--text-primary);
    font-family: 'DM Sans', Inter, 'Segoe UI', sans-serif;
    font-size: calc(28px * var(--ui-scale));
    font-weight: 800;
    letter-spacing: -0.5px;
    line-height: 1.05;
}
.toolbar-logo-text strong {
    color: var(--accent-light);
    font-weight: 700;
}
.toolbar-brand .toolbar-subtitle {
    margin-top: 4px;
    margin-left: 0;
}

.toolbar-subtitle {
    font-size: var(--font-micro);
    font-weight: 500;
    color: var(--text-muted);
    letter-spacing: 0.3px;
    margin-top: 4px;
    line-height: 1;
    white-space: nowrap;
    /* Align with the wordmark's "D" — the inline logo's <text> sits at viewBox x=296 of
       width 1200 (24.67%), and the SVG fills 100% of the brand box, so this percentage
       maps to the same screen x as the wordmark's first glyph. */
    margin-left: 24.67%;
}

/* ---- Sidebar ---- */
.sidebar {
    grid-area: sidebar;
    background: var(--bg-panel);
    border-right: 1px solid var(--border);
    overflow-y: auto;
    overflow-x: hidden;
    display: flex; flex-direction: column;
}

.sidebar::-webkit-scrollbar { width: 5px; }
.sidebar::-webkit-scrollbar-track { background: transparent; }
.sidebar::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }

/* ---- Viewport ---- */
.viewport-area {
    grid-area: viewport;
    position: relative;
    background: var(--bg-primary);
    overflow: hidden;
}

.viewport-canvas {
    width: 100%; height: 100%;
    display: block;
}

.viewport-overlay {
    position: absolute; top: 10px; right: 10px;
    display: flex; flex-direction: column; gap: 4px;
    z-index: 5;
}

/* ---- Status Bar ---- */
.statusbar {
    grid-area: statusbar;
    display: flex; align-items: center; gap: 18px;
    padding: 0 14px;
    height: 28px;
    background: var(--bg-secondary);
    border-top: 1px solid var(--border);
    font-size: var(--font-micro);
    color: var(--text-muted);
    font-family: var(--font-mono);
}

.statusbar-item { display: flex; align-items: center; gap: 4px; }
.statusbar-dot {
    width: 6px; height: 6px; border-radius: 50%;
    background: var(--success);
}

/* ============================================================
   Sidebar Panels
   ============================================================ */
.panel {
    border-bottom: 1px solid var(--border);
}

.panel-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 10px 14px;
    cursor: pointer;
    user-select: none;
    font-weight: 700;
    font-size: var(--font-small);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-primary);
    transition: color 0.15s;
}

.panel-header:hover { color: var(--text-primary); }

.panel-header .chevron {
    transition: transform 0.2s;
    font-size: var(--font-micro);
    color: var(--text-muted);
}

.panel-header.collapsed .chevron { transform: rotate(-90deg); }

.panel-body {
    padding: 4px 14px 14px;
    display: flex; flex-direction: column; gap: 8px;
}

.panel-body.collapsed { display: none; }

/* ---- Nav Menu ---- */
.nav-menu {
    display: flex; flex-direction: column; gap: 1px;
    padding: 8px;
}

.nav-item {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 12px;
    border-radius: var(--input-radius);
    cursor: pointer;
    color: var(--text-secondary);
    font-weight: 500; font-size: calc(13px * var(--ui-scale));
    transition: all 0.15s;
    text-decoration: none;
    border: none; background: none; width: 100%; text-align: left;
}

.nav-item:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}

.nav-item.active {
    background: var(--accent-glow);
    color: var(--accent-light);
    border-left: 2px solid var(--accent);
}

.nav-icon {
    width: 18px; height: 18px;
    display: flex; align-items: center; justify-content: center;
    font-size: calc(15px * var(--ui-scale));
}

/* ============================================================
   Form Controls
   ============================================================ */
.form-group {
    display: flex; flex-direction: column; gap: 4px;
}

.form-label {
    font-size: var(--font-small);
    font-weight: 600;
    color: var(--text-secondary);
    /* Sentence-case is more readable than UPPERCASE for label-length text.
       Reserve UPPERCASE for panel-header section dividers only. */
    letter-spacing: 0;
}

.form-row {
    display: grid; grid-template-columns: 1fr 1fr;
    gap: 8px;
}

input[type="text"],
input[type="number"],
select,
textarea {
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--input-radius);
    color: var(--text-primary);
    padding: 7px 10px;
    font-family: var(--font-mono);
    font-size: var(--font-small);
    outline: none;
    transition: border-color 0.15s;
    width: 100%;
    min-height: 30px;
}

input:focus, select:focus, textarea:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--accent-glow);
}

input[type="range"] {
    -webkit-appearance: none;
    width: 100%; height: 4px;
    border-radius: 2px;
    background: var(--border);
    outline: none;
}

input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 14px; height: 14px;
    border-radius: 50%;
    background: var(--accent);
    cursor: pointer;
    border: 2px solid var(--bg-panel);
}

/* ---- Buttons ---- */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    padding: 7px 14px;
    border-radius: var(--input-radius);
    border: 1px solid var(--border);
    background: var(--bg-hover);
    color: var(--text-primary);
    font-family: var(--font-ui);
    font-size: var(--font-small);
    font-weight: 500;
    cursor: pointer;
    transition: all 0.15s;
    text-decoration: none;
    user-select: none;
}

.btn:hover {
    background: var(--bg-active);
    border-color: var(--border-light);
}

.btn-primary {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}
.btn-primary:hover {
    background: var(--accent-light);
    border-color: var(--accent-light);
}

.btn-sm { padding: 5px 10px; font-size: var(--font-small); }

.btn-icon {
    width: 30px; height: 30px;
    padding: 0; border: none;
    background: transparent;
    color: var(--text-secondary);
    border-radius: var(--input-radius);
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    font-size: calc(16px * var(--ui-scale));
    transition: all 0.15s;
}

.btn-icon:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}

.btn-icon.active {
    background: var(--accent-glow);
    color: var(--accent-light);
}

/* ---- Toolbar Buttons ---- */
.toolbar-btn {
    height: 32px; min-width: 32px;
    padding: 0 10px;
    border: none; border-radius: 4px;
    background: transparent;
    color: var(--text-secondary);
    font-family: var(--font-ui);
    font-size: var(--font-small);
    font-weight: 500;
    cursor: pointer;
    display: flex; align-items: center; justify-content: center; gap: 6px;
    transition: all 0.12s;
}

/* Menu-style toolbar button (File / Edit / View / Tools / Help). Looks more like
   a desktop-app menu label than a toggle button. */
.toolbar-btn.menu-btn {
    color: var(--text-primary);
    font-weight: 600;
    padding: 0 14px;
}
.toolbar-btn.menu-btn.active {
    background: var(--bg-hover);
    color: var(--accent-light);
}

.toolbar-btn:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}

.toolbar-btn.active {
    background: var(--accent-glow);
    color: var(--accent-light);
}

/* ============================================================
   Texture Grid
   ============================================================ */
.texture-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 6px;
}

/* ============================================================
   Dimensions overlay (top-left of viewport)
   ============================================================ */
.dimensions-panel {
    position: absolute;
    top: 16px;
    left: 16px;
    min-width: 200px;
    background: rgba(20, 20, 24, 0.92);
    border: 1px solid var(--border);
    border-radius: 8px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
    backdrop-filter: blur(6px);
    z-index: 100;
    overflow: hidden;
    user-select: none;
}
.dimensions-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border);
    font: 600 12px var(--font-ui);
    color: var(--accent-light);
}
.dim-unit-toggle {
    display: inline-flex;
    margin-left: auto;
    border: 1px solid var(--border);
    border-radius: 4px;
    overflow: hidden;
}
.dim-unit-toggle button {
    padding: 2px 8px;
    background: var(--bg-input);
    color: var(--text-secondary);
    border: none;
    font: 500 11px var(--font-ui);
    cursor: pointer;
}
.dim-unit-toggle button:not(:last-child) { border-right: 1px solid var(--border); }
.dim-unit-toggle button.active {
    background: var(--accent);
    color: #1a1a1e;
    font-weight: 700;
}
.dim-unit-toggle button:hover:not(.active) { background: var(--bg-hover); }
.dim-close {
    width: 22px; height: 22px;
    padding: 0;
    line-height: 1;
}
.dimensions-body {
    padding: 8px 10px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.dim-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    font: 12px var(--font-ui);
    padding: 2px 0;
}
.dim-row-emph {
    margin-top: 4px;
    padding-top: 6px;
    border-top: 1px solid var(--border);
}
.dim-label {
    color: var(--text-muted);
    text-transform: uppercase;
    font-size: var(--font-micro);
    letter-spacing: 0.05em;
    font-weight: 600;
}
.dim-sub {
    color: var(--text-muted);
    text-transform: none;
    font-size: var(--font-micro);
    margin-left: 2px;
    letter-spacing: 0;
    font-weight: 400;
}
.dim-value {
    font-family: var(--font-mono);
    font-size: calc(12px * var(--ui-scale));
    color: var(--accent-light);
    font-weight: 500;
    text-align: right;
}

/* HTML labels that overlay the 3D viewport, tracking world-space dimension anchors.
   Three variants: axis-x / axis-y / axis-z carry the cage's overall dimensions and
   inherit the matching axis colour; .anatomy is for the per-cross-section ring labels. */
.dim-3d-label {
    position: absolute;
    transform: translate(-50%, -50%);
    background: rgba(20, 20, 24, 0.88);
    color: var(--text-primary);
    border: 1px solid rgba(255, 255, 255, 0.12);
    padding: 3px 9px;
    border-radius: 3px;
    font: 600 var(--font-small) var(--font-mono);
    /* Outline keeps the label readable when it floats over the model surface
       regardless of the colour beneath. */
    text-shadow:
        0 0 2px rgba(0, 0, 0, 0.9),
        0 0 4px rgba(0, 0, 0, 0.6);
    pointer-events: none;
    user-select: none;
    white-space: nowrap;
    z-index: 50;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
    backdrop-filter: blur(2px);
}
.dim-3d-label.axis-x { color: #ff5566; border-color: rgba(255, 85, 102, 0.55); }
.dim-3d-label.axis-y { color: #66dd66; border-color: rgba(102, 221, 102, 0.55); }
.dim-3d-label.axis-z { color: #6699ff; border-color: rgba(102, 153, 255, 0.55); }
.dim-3d-label.anatomy {
    color: #ffbe7a;
    border-color: rgba(255, 156, 74, 0.55);
    font-weight: 500;
    font-size: var(--font-micro);
    letter-spacing: 0.02em;
}

/* ============================================================
   Range slider with ± stepper buttons for precision adjustment
   ============================================================ */
.range-stepper {
    display: flex;
    align-items: center;
    gap: 4px;
    width: 100%;
}
.range-stepper input[type="range"] {
    flex: 1;
    min-width: 0;
    margin: 0;
    accent-color: var(--accent);
}
.range-stepper-btn {
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-input);
    color: var(--text-primary);
    border: 1px solid var(--border);
    border-radius: 4px;
    cursor: pointer;
    font: 600 14px/1 var(--font-ui);
    user-select: none;
    transition: all 0.1s;
}
.range-stepper-btn:hover {
    background: var(--accent);
    color: #1a1a1e;
    border-color: var(--accent);
}
.range-stepper-btn:active {
    transform: scale(0.92);
}

.texture-card {
    /* Fixed min-height accommodates 56px preview canvas + up to 2 lines of label text
       without bleeding into the next panel. aspect-ratio:1 was too short for long names
       like "DRAGON SCALE" / "CUSTOM GRAPH" and caused content overflow into siblings. */
    min-height: 110px;
    padding: 8px 4px 6px;
    border-radius: var(--input-radius);
    border: 2px solid var(--border);
    background: var(--bg-input);
    cursor: pointer;
    display: flex; flex-direction: column;
    align-items: center; justify-content: flex-start;
    gap: 5px;
    overflow: hidden;
    text-align: center;
    line-height: 1.2;
    word-break: break-word;
    font-size: var(--font-micro);
    color: var(--text-secondary);
    font-weight: 500;
    transition: all 0.15s;
    position: relative;
}

/* Editable graph-driven cards: distinct dashed border + small pencil badge in corner. */
.texture-card.editable {
    border-style: dashed;
    border-color: var(--accent-dim);
}
.texture-card.editable:hover {
    border-color: var(--accent);
}
.texture-card.editable.active {
    border-style: solid;
    border-color: var(--accent);
}
.texture-edit-badge {
    position: absolute;
    top: 3px; right: 3px;
    width: 18px; height: 18px;
    display: flex; align-items: center; justify-content: center;
    background: var(--accent);
    color: #1a1a1e;
    border-radius: 4px;
    font-size: calc(11px * var(--ui-scale));
    font-weight: 700;
    line-height: 1;
    pointer-events: none;
    text-transform: none;
    letter-spacing: 0;
    box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}

.texture-card:hover {
    border-color: var(--border-light);
    background: var(--bg-hover);
}

.texture-card.active {
    border-color: var(--accent);
    background: var(--accent-glow);
    color: var(--accent-light);
}

.texture-icon {
    font-size: calc(22px * var(--ui-scale));
}

.pattern-preview-canvas {
    display: block;
    border-radius: 4px;
    image-rendering: -webkit-optimize-contrast;
    image-rendering: crisp-edges;
    background: #1a1a1a;
}

.texture-card .pattern-preview-canvas {
    width: 56px;
    height: 56px;
}

/* ============================================================
   Analysis Panel
   ============================================================ */
.analysis-score {
    display: flex; flex-direction: column; align-items: center;
    padding: 12px; gap: 6px;
}

.score-ring {
    width: 80px; height: 80px;
    border-radius: 50%;
    border: 4px solid var(--border);
    display: flex; align-items: center; justify-content: center;
    font-size: calc(24px * var(--ui-scale)); font-weight: 700;
    font-family: var(--font-mono);
}

.score-ring.good { border-color: var(--success); color: var(--success); }
.score-ring.warning { border-color: var(--warning); color: var(--warning); }
.score-ring.danger { border-color: var(--danger); color: var(--danger); }

.score-label { font-size: calc(11px * var(--ui-scale)); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; }

.warning-list {
    display: flex; flex-direction: column; gap: 6px;
}

.warning-item {
    padding: 8px 10px;
    border-radius: var(--input-radius);
    font-size: calc(11px * var(--ui-scale));
    line-height: 1.4;
    display: flex; gap: 8px; align-items: flex-start;
}

.warning-item.critical { background: rgba(196, 84, 84, 0.1); color: var(--danger); }
.warning-item.warning { background: rgba(212, 168, 75, 0.1); color: var(--warning); }
.warning-item.info { background: rgba(90, 138, 196, 0.1); color: var(--info); }

.warning-icon { font-size: calc(14px * var(--ui-scale)); flex-shrink: 0; margin-top: 1px; }

/* ============================================================
   Per-family analysis sections — one block per print modality
   (FDM / Clay LDM / Resin / General). Each section has a header
   with severity-count badges and the warnings underneath.
   ============================================================ */
.analysis-section {
    margin: 12px 0 0;
    padding: 10px 12px;
    background: rgba(255, 255, 255, 0.02);
    border: 1px solid var(--border, rgba(255, 255, 255, 0.06));
    border-radius: var(--radius, 6px);
}
.analysis-section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 8px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--border, rgba(255, 255, 255, 0.05));
}
.analysis-section-title {
    font-size: calc(12px * var(--ui-scale));
    font-weight: 600;
    color: var(--text-primary, #fff);
    letter-spacing: 0.005em;
}
.analysis-section-counts {
    display: flex;
    gap: 4px;
    flex-shrink: 0;
}
.badge-crit, .badge-warn, .badge-info {
    font-size: calc(10px * var(--ui-scale));
    font-weight: 600;
    padding: 2px 6px;
    border-radius: 999px;
    line-height: 1.4;
    white-space: nowrap;
}
.badge-crit { background: rgba(196, 84, 84, 0.18); color: var(--danger, #c45454); }
.badge-warn { background: rgba(212, 168, 75, 0.18); color: var(--warning, #d4a84b); }
.badge-info { background: rgba(90, 138, 196, 0.18); color: var(--info, #5a8ac4); }

/* ============================================================
   Misc
   ============================================================ */
.empty-state {
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    padding: 40px 20px; gap: 10px;
    color: var(--text-muted); text-align: center;
}

.empty-state-icon { font-size: calc(40px * var(--ui-scale)); opacity: 0.4; }

.badge {
    display: inline-flex; align-items: center; justify-content: center;
    padding: 2px 6px;
    border-radius: 10px;
    font-size: var(--font-micro); font-weight: 600;
    background: var(--accent-glow);
    color: var(--accent-light);
}

.divider {
    height: 1px;
    background: var(--border);
    margin: 4px 0;
}

/* Scrollbar global */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--border-light); }

/* ============================================================
   Profile editor
   ============================================================ */

.profile-editor {
    display: flex;
    flex-direction: column;
    gap: 8px;
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 8px;
}

.profile-toolbar {
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
}

.profile-hint {
    flex: 1;
    font-size: var(--font-micro);
    color: var(--text-muted);
}

.profile-canvas {
    width: 100%;
    height: auto;
    aspect-ratio: 1 / 1;
    background: linear-gradient(180deg, #1c1c20 0%, #16161a 100%);
    border: 1px solid var(--border);
    border-radius: 4px;
    cursor: crosshair;
    touch-action: none;
    user-select: none;
}

.profile-canvas .grid-major {
    stroke: rgba(255,255,255,0.04);
    stroke-width: 1;
}

.profile-canvas .mirror-axis {
    stroke: rgba(196,122,74,0.35);
    stroke-width: 1;
    stroke-dasharray: 3 3;
}

.profile-canvas .silhouette {
    fill: rgba(196,122,74,0.12);
    stroke: none;
}

.profile-canvas .curve {
    fill: none;
    stroke: var(--accent);
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.profile-canvas .curve.mirror {
    stroke: var(--accent-dim);
}

.profile-canvas .edge {
    stroke: var(--accent-dim);
    stroke-width: 1.5;
    stroke-dasharray: 2 3;
}

.profile-canvas .handle {
    fill: var(--bg-panel);
    stroke: var(--accent-light);
    stroke-width: 2;
    cursor: grab;
    transition: r 120ms ease, fill 120ms ease;
}

.profile-canvas .handle:hover {
    fill: var(--accent-glow);
}

.profile-canvas .handle.selected {
    fill: var(--accent);
    stroke: var(--text-primary);
    cursor: grabbing;
}

.profile-canvas .handle-label {
    fill: var(--text-muted);
    font-size: var(--font-micro);
    font-family: var(--font-mono, monospace);
    pointer-events: none;
    user-select: none;
}

.profile-canvas .axis-label {
    fill: var(--text-muted);
    font-size: var(--font-micro);
    font-family: var(--font-mono, monospace);
    pointer-events: none;
    user-select: none;
}

.point-detail {
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 6px 8px;
}

.point-detail .point-row {
    display: grid;
    grid-template-columns: auto auto 1fr auto 1fr auto;
    gap: 6px;
    align-items: center;
    font-size: calc(11px * var(--ui-scale));
}

.point-detail .point-tag {
    background: var(--accent);
    color: #1a1a1e;
    padding: 2px 6px;
    border-radius: 3px;
    font-weight: 600;
    font-size: var(--font-micro);
}

.point-detail label {
    color: var(--text-muted);
    font-size: var(--font-micro);
}

.point-detail input[type="number"],
.point-detail select {
    background: var(--bg-input);
    border: 1px solid var(--border);
    color: var(--text-primary);
    padding: 3px 5px;
    border-radius: 3px;
    font-size: calc(11px * var(--ui-scale));
    min-width: 0;
    width: 100%;
}

/* ============================================================
   View menu / picker
   ============================================================ */

.view-menu-anchor { position: relative; }

.view-menu {
    position: absolute;
    top: calc(100% + 4px);
    /* Anchor to the LEFT edge of the View button so the menu opens rightward into the
       free area below the toolbar. Anchoring right:0 caused the menu to overflow off
       the left side of the window when the View button wrapped to the start of a row. */
    left: 0;
    min-width: 160px;
    max-width: calc(100vw - 16px);
    background: var(--bg-panel);
    border: 1px solid var(--border-light);
    border-radius: 6px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.45);
    padding: 4px;
    z-index: 200;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.view-menu-item {
    background: transparent;
    border: 0;
    color: var(--text-primary);
    padding: 6px 10px;
    text-align: left;
    border-radius: 4px;
    font-size: calc(12px * var(--ui-scale));
    cursor: pointer;
}

.view-menu-item:hover {
    background: var(--bg-hover);
    color: var(--text-accent);
}

.view-menu-divider {
    height: 1px;
    background: var(--border);
    margin: 4px 6px;
}

.view-menu-section {
    font-size: var(--font-micro);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-muted);
    font-weight: 600;
    padding: 4px 10px 2px;
    margin-top: 2px;
}

/* ---- Info modal (Help menu placeholders, About, etc.) ---- */
.info-modal-backdrop {
    position: fixed; inset: 0;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(2px);
    z-index: 2000;
    display: flex; align-items: center; justify-content: center;
}
.info-modal {
    background: var(--bg-panel);
    border: 1px solid var(--border-light);
    border-radius: 10px;
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.7);
    width: min(560px, calc(100vw - 60px));
    max-height: calc(100vh - 80px);
    display: flex; flex-direction: column;
    overflow: hidden;
}
.info-modal-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 14px 18px;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border);
    color: var(--accent-light);
    font: 700 var(--font-large) var(--font-ui);
}
.info-modal-body {
    padding: 18px;
    overflow-y: auto;
    color: var(--text-primary);
    font-size: var(--font-small);
    line-height: 1.55;
    white-space: pre-line;     /* honor \n in C# strings without needing <br> */
}

/* ============================================================
   Settings modal — wider than the info modal because it hosts
   real interactive controls (number inputs, dropdowns, ranges,
   color pickers, sliders) instead of a single block of text.
   Reuses the info-modal-backdrop / info-modal-header / -footer
   structure for consistency.
   ============================================================ */
.settings-modal {
    background: var(--bg-panel);
    border: 1px solid var(--border-light);
    border-radius: 10px;
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.7);
    width: min(820px, calc(100vw - 60px));
    height: min(720px, calc(100vh - 80px));
    display: flex; flex-direction: column;
    overflow: hidden;
}
.settings-modal-body {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.settings-tab-strip {
    display: flex;
    gap: 2px;
    padding: 8px 14px 0 14px;
    border-bottom: 1px solid var(--border);
    background: var(--bg-secondary);
}
.settings-tab {
    background: transparent;
    border: 1px solid transparent;
    border-bottom: none;
    border-radius: 6px 6px 0 0;
    padding: 8px 14px;
    font: 600 var(--font-small) var(--font-ui);
    color: var(--text-muted);
    cursor: pointer;
    transition: background 0.12s, color 0.12s;
}
.settings-tab:hover {
    color: var(--text-primary);
    background: var(--bg-input);
}
.settings-tab.active {
    color: var(--accent-light);
    background: var(--bg-panel);
    border-color: var(--border);
    border-bottom: 1px solid var(--bg-panel);
    margin-bottom: -1px;
}
.settings-tab-content {
    flex: 1;
    overflow-y: auto;
    padding: 14px 18px;
}
.settings-tab-content .panel { margin-bottom: 14px; }
.settings-tab-content .panel:last-child { margin-bottom: 0; }
/* Wordmark fill for inline brand SVGs. The canonical logo.svg hardcodes a dark navy fill
   that's invisible on dark surfaces; inline copies use this class so they read on the
   dark splash overlay and About-modal panel. Reused by anywhere that inlines the brand. */
.brand-wordmark {
    fill: var(--text-primary);
}
.brand-wordmark tspan {
    fill: var(--accent-light);
}

/* Optional logo banner shown above the body for the About modal. */
.info-modal-logo {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    padding: 22px 18px 10px;
    background: var(--bg-panel);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.info-modal-logo-icon {
    height: 96px;
    width: auto;
    filter: drop-shadow(0 4px 14px rgba(0, 0, 0, 0.35));
    background: transparent;
}
.info-modal-logo-text {
    font-family: 'DM Sans', Inter, 'Segoe UI', sans-serif;
    font-size: calc(56px * var(--ui-scale));
    font-weight: 800;
    letter-spacing: -1px;
    line-height: 1;
    color: var(--text-primary);
}
.info-modal-logo-text strong {
    color: var(--accent-light);
    font-weight: 700;
}

/* ---- Splash overlay (first-launch presentation) ----
   Covers the entire app while the brand mark + version + tagline are presented to the user.
   Auto-fades out after a minimum on-screen time controlled from MainLayout.
   The splash uses a fixed-width content column (--splash-w) so the logo and the text below
   share the same horizontal extent — that's what makes everything line up cleanly under the
   wordmark instead of drifting around the SVG's geometric center. */
.splash-overlay {
    position: fixed; inset: 0;
    background: var(--bg-primary);
    z-index: 5000;
    display: flex; align-items: center; justify-content: center;
    transition: opacity 600ms ease-out;
    opacity: 1;
    --splash-w: min(640px, 86vw);
}
.splash-overlay.splash-fading {
    opacity: 0;
    pointer-events: none;
}
.splash-content {
    display: flex; flex-direction: column;
    align-items: stretch;
    width: var(--splash-w);
    padding: 32px 0;
    animation: splash-rise 0.55s ease-out;
    text-align: center;
}
.splash-logo {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 18px;
    width: 100%;
    filter: drop-shadow(0 12px 32px rgba(0, 0, 0, 0.55));
}
.splash-logo-icon {
    height: 180px;
    width: auto;
    background: transparent;
}
.splash-logo-text {
    font-family: 'DM Sans', Inter, 'Segoe UI', sans-serif;
    font-size: calc(80px * var(--ui-scale));
    font-weight: 800;
    letter-spacing: -2px;
    line-height: 1;
    color: var(--text-primary);
}
.splash-logo-text strong {
    color: var(--accent-light);
    font-weight: 700;
}
/* Text block below the wordmark. The .splash-text/.splash-copyright share the same width
   as the SVG, so center-aligning them produces a visually balanced column. */
.splash-text {
    display: flex; flex-direction: column;
    align-items: center;
    gap: 6px;
    margin-top: 14px;
}
.splash-version {
    font: 700 calc(20px * var(--ui-scale)) var(--font-ui);
    color: var(--accent-light);
    letter-spacing: 1.6px;
    text-transform: uppercase;
}
.splash-tagline {
    color: var(--text-secondary);
    font-size: var(--font-base);
    max-width: 480px;
    line-height: 1.4;
}
.splash-spinner {
    width: 26px; height: 26px; border-radius: 50%;
    border: 3px solid var(--border);
    border-top-color: var(--accent);
    animation: spin 0.8s linear infinite;
    margin: 18px auto 0;
}
.splash-copyright {
    margin-top: 22px;
    font-size: var(--font-micro);
    color: var(--text-muted);
    letter-spacing: 0.4px;
}
@keyframes splash-rise {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: translateY(0); }
}
.info-modal-footer {
    padding: 12px 18px;
    border-top: 1px solid var(--border);
    display: flex; justify-content: flex-end;
    background: var(--bg-secondary);
}

/* ============================================================
   On-canvas view picker (3x3 cube-face widget)
   ============================================================ */

.view-picker {
    position: relative;
    display: inline-block;
}

.view-picker-grid {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    background: rgba(34, 34, 38, 0.95);
    border: 1px solid var(--border-light);
    border-radius: 6px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.5);
    padding: 4px;
    z-index: 200;
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 132px;
}

.view-picker-row {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 2px;
}

.vp-cell {
    background: var(--bg-input);
    border: 1px solid var(--border);
    color: var(--text-primary);
    padding: 8px 0;
    font-size: calc(13px * var(--ui-scale));
    border-radius: 3px;
    cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease;
}

.vp-cell:hover {
    background: var(--accent);
    color: #1a1a1e;
    border-color: var(--accent);
}

.vp-cell.vp-back {
    font-size: calc(11px * var(--ui-scale));
}

/* ============================================================
   Template / Reference panel — controls for an imported mesh
   ============================================================ */
.template-panel {
    position: absolute;
    bottom: 12px;
    right: 12px;
    width: 320px;
    max-height: calc(100vh - 200px);
    overflow-y: auto;
    background: rgba(34,34,38,0.94);
    border: 1px solid var(--border-light);
    border-radius: 6px;
    padding: 8px 10px;
    z-index: 100;
    box-shadow: 0 6px 18px rgba(0,0,0,0.45);
    backdrop-filter: blur(4px);
}
.template-panel-header {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: calc(12px * var(--ui-scale));
    color: var(--accent-light);
    font-weight: 600;
    border-bottom: 1px solid var(--border);
    padding-bottom: 6px;
    margin-bottom: 6px;
}
.template-name {
    font-size: var(--font-micro);
    color: var(--text-muted);
    font-family: var(--font-mono);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 130px;
}
.template-section-title {
    font-size: var(--font-micro);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin: 6px 0 2px;
    font-weight: 600;
}
.template-row {
    display: grid;
    grid-template-columns: 22px 1fr 56px;
    gap: 6px;
    align-items: center;
    margin: 2px 0;
    font-size: calc(11px * var(--ui-scale));
}
.template-row label {
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-weight: 700;
    text-align: center;
}
.template-row .template-value {
    font-family: var(--font-mono);
    color: var(--accent-light);
    text-align: right;
    font-size: calc(11px * var(--ui-scale));
}
.template-actions {
    display: flex;
    gap: 6px;
    margin-top: 8px;
    padding-top: 6px;
    border-top: 1px solid var(--border);
}
.template-actions .btn { flex: 1; font-size: var(--font-small); padding: 6px 8px; }

/* ============================================================
   Imported-mesh rotation panel (legacy)
   ============================================================ */

.rotation-panel {
    position: absolute;
    bottom: 12px;
    right: 12px;
    width: 280px;
    background: rgba(34,34,38,0.92);
    border: 1px solid var(--border-light);
    border-radius: 6px;
    padding: 8px 10px;
    z-index: 100;
    box-shadow: 0 6px 18px rgba(0,0,0,0.45);
    backdrop-filter: blur(4px);
}

.rotation-panel-header {
    display: flex;
    align-items: center;
    font-size: calc(11px * var(--ui-scale));
    color: var(--text-accent);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 6px;
    border-bottom: 1px solid var(--border);
    padding-bottom: 4px;
}

.rotation-row {
    display: grid;
    grid-template-columns: 16px 1fr 44px auto auto;
    gap: 6px;
    align-items: center;
    margin-top: 4px;
    font-size: calc(11px * var(--ui-scale));
}

.rotation-row label {
    color: var(--text-muted);
    font-family: var(--font-mono, monospace);
    font-weight: 700;
    text-align: center;
}

.rotation-row input[type="range"] {
    width: 100%;
    accent-color: var(--accent);
}

.rotation-row .rotation-value {
    color: var(--text-primary);
    font-family: var(--font-mono, monospace);
    text-align: right;
}

.rotation-row .btn-sm-rot {
    background: var(--bg-input);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    border-radius: 3px;
    padding: 2px 6px;
    font-size: var(--font-micro);
    cursor: pointer;
}

.rotation-row .btn-sm-rot:hover {
    background: var(--accent);
    color: #1a1a1e;
    border-color: var(--accent);
}

/* Inline select styled to live in the top toolbar next to buttons. */
.toolbar-select {
    background: var(--bg-input);
    color: var(--text-primary);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 6px 10px;
    font-size: var(--font-small);
    font-family: inherit;
    margin: 0 2px;
    cursor: pointer;
}
.toolbar-select:hover { border-color: var(--accent); }

/* Cross-section drawing editor + layer stack */
.cross-section-editor .symmetry-guide {
    stroke: rgba(196,122,74,0.35);
    stroke-width: 1;
    stroke-dasharray: 2 4;
}
.cross-section-editor .handle.mirror {
    fill: rgba(217,149,107,0.5);
    stroke: rgba(196,122,74,0.6);
    stroke-width: 1;
}

.cs-mode-row {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 4px;
    margin-bottom: 6px;
}
.cs-mode {
    background: var(--bg-input);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    padding: 6px 4px;
    border-radius: 4px;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    font-size: var(--font-micro);
}
.cs-mode-icon { font-size: calc(16px * var(--ui-scale)); color: var(--text-primary); }
.cs-mode:hover { border-color: var(--accent); }
.cs-mode.active {
    background: var(--accent);
    color: #1a1a1e;
    border-color: var(--accent);
}
.cs-mode.active .cs-mode-icon { color: #1a1a1e; }

.layer-stack {
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 240px;
    overflow-y: auto;
}
.layer-row {
    display: grid;
    grid-template-columns: 40px 1fr 50px auto;
    gap: 6px;
    align-items: center;
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 4px 6px;
    font-size: calc(11px * var(--ui-scale));
    cursor: pointer;
}
.layer-row:hover { border-color: var(--accent-dim); }
.layer-row.active {
    border-color: var(--accent);
    background: var(--accent-glow);
}
.layer-row .layer-h {
    font-family: var(--font-mono, monospace);
    color: var(--text-accent);
    font-weight: 600;
}
.layer-row .layer-pts {
    color: var(--text-muted);
    font-size: var(--font-micro);
    text-align: right;
}

.btn.btn-sm.active {
    background: var(--accent);
    color: #1a1a1e;
    border-color: var(--accent);
}

/* Pottery wheel floating panel */
.pottery-panel {
    /* Docks against the LEFT edge of the viewport area (immediately right of the
       main sidebar) and fills the full viewport height. This treats Pottery Wheel
       as a primary work mode rather than a transient floating overlay. */
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 360px;
    max-width: calc(100vw - 320px);
    overflow-y: auto;
    background: rgba(30,30,34,0.97);
    border-right: 1px solid var(--accent-dim);
    border-radius: 0;          /* flush docked panel — no rounded corners */
    padding: 14px 16px;
    z-index: 100;
    backdrop-filter: blur(6px);
    box-shadow: 4px 0 18px rgba(0,0,0,0.45);
    transition: width 0.18s ease;
}
.pottery-panel.expanded {
    /* Wider when popped open, but still docked left + full height. */
    width: min(560px, calc(100vw - 320px));
    padding: 18px 22px;
    box-shadow: 4px 0 28px rgba(0,0,0,0.6);
}
.pottery-panel-header {
    display: flex;
    align-items: center;
    gap: 6px;
    font-weight: 700;
    font-size: calc(15px * var(--ui-scale));
    color: var(--accent-light);
    margin-bottom: 10px;
    border-bottom: 1px solid var(--border);
    padding-bottom: 8px;
}
.pottery-section-title {
    font-size: calc(11px * var(--ui-scale));
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-muted);
    margin: 10px 0 6px;
    font-weight: 600;
}
.pottery-tools {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 6px;
    margin-bottom: 8px;
}
.pottery-panel.expanded .pottery-tools {
    grid-template-columns: repeat(6, 1fr);
}
.pottery-tool {
    background: var(--bg-input);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    border-radius: 5px;
    padding: 8px 4px;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    font-size: calc(11px * var(--ui-scale));
}
.pottery-tool:hover { border-color: var(--accent); color: var(--text-primary); }
.pottery-tool.active {
    background: var(--accent);
    color: #1a1a1e;
    border-color: var(--accent);
}
.pottery-tool-icon { font-size: calc(20px * var(--ui-scale)); line-height: 1; }
.pottery-panel.expanded .pottery-tool-icon { font-size: calc(24px * var(--ui-scale)); }
.pottery-row {
    display: grid;
    grid-template-columns: 90px 1fr 70px;
    gap: 8px;
    align-items: center;
    margin: 6px 0;
    font-size: calc(12px * var(--ui-scale));
}
.pottery-row label { color: var(--text-muted); }
.pottery-row .pottery-val {
    font-family: var(--font-mono, monospace);
    color: var(--text-primary);
    text-align: right;
    font-size: calc(11px * var(--ui-scale));
}
.pottery-stats {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 10px;
    padding: 8px 10px;
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: 5px;
    font-size: calc(12px * var(--ui-scale));
}
.pottery-stats > span:first-child {
    flex: 1;
    color: var(--text-muted);
}
.pottery-stats > span:first-child b {
    color: var(--accent-light);
    font-weight: 600;
}
.pottery-hint {
    font-size: calc(11px * var(--ui-scale));
    color: var(--text-muted);
    margin-top: 10px;
    border-top: 1px solid var(--border);
    padding-top: 8px;
    line-height: 1.5;
}

/* ============================================================
   Pattern Graph Editor (Phase 2 — Grasshopper-style node canvas)
   ============================================================ */
.graph-editor-overlay {
    position: fixed; inset: 0; z-index: 1000;
    background: rgba(10,10,12,0.85);
    backdrop-filter: blur(4px);
    display: flex; flex-direction: column;
}
.graph-editor-header {
    display: flex; align-items: center; gap: 12px;
    padding: 12px 18px;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border);
}
.graph-editor-title { font-weight: 700; font-size: calc(16px * var(--ui-scale)); color: var(--accent-light); }
.graph-editor-spacer { flex: 1; }
.graph-editor-body { flex: 1; display: grid; grid-template-columns: 220px 1fr 360px; min-height: 0; }
.graph-palette {
    background: var(--bg-panel);
    border-right: 1px solid var(--border);
    padding: 12px; overflow-y: auto;
}
.graph-palette-section { font-size: var(--font-micro); text-transform: uppercase; color: var(--text-muted);
    letter-spacing: 0.5px; margin: 12px 0 6px; font-weight: 600; }
.graph-palette-item {
    display: block; width: 100%; text-align: left; padding: 6px 10px; margin: 3px 0;
    background: var(--bg-input); color: var(--text-primary);
    border: 1px solid var(--border); border-radius: 4px; cursor: pointer; font-size: calc(12px * var(--ui-scale));
}
.graph-palette-item:hover { border-color: var(--accent); background: var(--bg-hover); }
.graph-canvas-wrap {
    background: #15151a;
    background-image: radial-gradient(rgba(255,255,255,0.04) 1px, transparent 1px);
    background-size: 20px 20px;
    overflow: hidden; position: relative;
}
/* touch-action: none stops Android's WebView from handling pan / pinch
   gestures on top of the @onmousemove handler — without it the two paths
   fight and the WebView aborts (same crash class as the 3D viewport's pan).
   user-select: none keeps long-press from popping the system text-selection
   menu mid-pan. webkit-tap-highlight-color: transparent removes the iOS /
   Android tap flash on every node click. */
.graph-canvas {
    width: 100%;
    height: 100%;
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
    -webkit-tap-highlight-color: transparent;
    cursor: grab;
}
.graph-canvas.panning { cursor: grabbing; }
.graph-node {
    fill: #2a2a30;
    stroke: var(--border);
    stroke-width: 1;
    rx: 8; ry: 8;
}
.graph-node.root { stroke: var(--accent); stroke-width: 2; }
.graph-node-header { fill: #1f1f24; }
.graph-node-title { fill: var(--accent-light); font: 600 14px var(--font-ui); }
.graph-node-id    { fill: var(--text-muted); font: 11px var(--font-mono); }
.graph-socket { stroke: var(--border); stroke-width: 1.5; cursor: crosshair; }
.graph-socket.input  { fill: #1f1f24; }
.graph-socket.input:hover  { fill: var(--accent-dim); stroke: var(--accent-light); }
.graph-socket.output { fill: var(--accent); }
.graph-socket.output:hover { stroke: var(--accent-light); stroke-width: 2; }
.graph-socket.connected { fill: var(--accent-light); }
.graph-socket-label { font: 12px var(--font-ui); fill: var(--text-secondary); pointer-events: none; }
.graph-wire { fill: none; stroke: var(--accent-dim); stroke-width: 2.5; pointer-events: none; }
.graph-wire.pending { stroke: var(--accent-light); stroke-dasharray: 4 4; }
/* Invisible thick stroke that overlays each visible wire to make wires easy to click. */
.graph-wire-hit {
    fill: none;
    stroke: transparent;
    stroke-width: 16;
    cursor: pointer;
    pointer-events: stroke;
}
.graph-wire-hit:hover ~ .graph-wire,
.graph-wire-hit:hover { stroke: #ff6b6b !important; }
.graph-inspector {
    background: var(--bg-panel); border-left: 1px solid var(--border);
    padding: 14px; overflow-y: auto;
}
.graph-inspector-title { font-weight: 700; color: var(--accent-light); margin-bottom: 8px; font-size: calc(14px * var(--ui-scale)); }
.graph-param {
    display: grid;
    grid-template-columns: 1fr auto;
    column-gap: 8px; row-gap: 2px;
    align-items: center;
    margin: 10px 0; font-size: calc(12px * var(--ui-scale));
}
.graph-param label { color: var(--text-secondary); font-weight: 500; }
.graph-param .val { font-family: var(--font-mono); font-size: calc(11px * var(--ui-scale)); color: var(--accent-light); text-align: right; }
.graph-param input[type="range"] {
    grid-column: 1 / -1;
    width: 100%;
    height: 22px;
    padding: 0;
    margin: 2px 0 0 0;
    accent-color: var(--accent);
}
.graph-param select {
    grid-column: 1 / -1;
    width: 100%;
    font-size: calc(12px * var(--ui-scale)); padding: 6px 8px;
}
/* Help-hint banner along the bottom of the canvas. */
.graph-canvas-hint {
    position: absolute;
    left: 12px; right: 12px; bottom: 8px;
    padding: 6px 12px;
    font-size: calc(11px * var(--ui-scale));
    color: var(--text-secondary);
    background: rgba(20,20,24,0.78);
    border: 1px solid var(--border);
    border-radius: 4px;
    backdrop-filter: blur(2px);
    pointer-events: none;
    text-align: center;
    line-height: 1.6;
}
.graph-canvas-hint b { color: var(--accent-light); font-weight: 600; }
.graph-empty {
    color: var(--text-muted); font-style: italic; font-size: calc(12px * var(--ui-scale));
    text-align: center; padding: 20px 8px;
}

/* Split-mode docking & resize handle */
.graph-editor-overlay.mode-split {
    /* Anchor BELOW the top toolbar so the toolbar's right-side buttons aren't covered.
       The toolbar height is dynamic (it can wrap to multiple rows on narrow windows),
       so use a top offset that matches its current min-height. */
    top: var(--toolbar-height);
    right: 0;
    bottom: 0;
    left: auto;
    height: auto;
    background: var(--bg-secondary);
    box-shadow: -8px 0 32px rgba(0,0,0,0.6);
    border-left: 1px solid var(--accent-dim);
    backdrop-filter: none;
}
.graph-editor-overlay.mode-split .graph-editor-body {
    grid-template-columns: 180px 1fr 320px;  /* tighter palette, generous inspector */
}
.graph-editor-overlay.mode-fullscreen .graph-editor-body {
    grid-template-columns: 220px 1fr 360px;
}
.graph-editor-resizer {
    position: absolute;
    top: 0; left: -3px; bottom: 0;
    width: 6px;
    cursor: ew-resize;
    background: transparent;
    z-index: 1001;
}
.graph-editor-resizer:hover {
    background: var(--accent-dim);
}
.graph-mode-toggle { display: inline-flex; gap: 2px; }
.graph-mode-toggle .btn { border-radius: 4px; }
.graph-mode-toggle .btn.active {
    background: var(--accent);
    color: #1a1a1e;
    border-color: var(--accent);
}

/* ============================================================
   Profile Editor — expand / history / undo
   ============================================================ */
.profile-editor.expanded {
    position: fixed;
    inset: var(--toolbar-height) 0 0 0;
    z-index: 950;
    background: var(--bg-secondary);
    border: none;
    padding: 16px 20px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    box-shadow: 0 0 32px rgba(0,0,0,0.7);
}
.profile-editor.expanded .profile-canvas {
    flex: 1;
    width: 100%;
    height: auto;
    min-height: 0;
    max-height: calc(100vh - var(--toolbar-height) - 200px);
}
.profile-history {
    margin-top: 8px;
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: 5px;
    padding: 8px 10px;
    max-height: 180px;
    overflow-y: auto;
    font-size: calc(11px * var(--ui-scale));
}
.profile-history-header {
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-size: var(--font-micro);
    margin-bottom: 4px;
    font-weight: 600;
}
.profile-history-row {
    display: flex; align-items: center;
    padding: 2px 0;
    border-bottom: 1px solid rgba(255,255,255,0.04);
}
.profile-history-label {
    flex: 1;
    color: var(--text-secondary);
}
.profile-history-tag {
    font-size: var(--font-micro);
    color: var(--accent-light);
    background: var(--accent-glow);
    padding: 1px 6px;
    border-radius: 3px;
    margin-left: 6px;
}
.profile-history-empty {
    color: var(--text-muted);
    font-style: italic;
    text-align: center;
    padding: 6px 0;
}

/* ============================================================
   Sidebar resize handle
   ============================================================ */
.sidebar { position: relative; }
.sidebar-resizer {
    position: absolute;
    top: 0; right: -3px; bottom: 0;
    width: 6px;
    cursor: ew-resize;
    z-index: 50;
    background: transparent;
}
.sidebar-resizer:hover { background: var(--accent-dim); }

/* Profile editor — dimension annotations */
.profile-canvas .dim-line {
    stroke: var(--accent-light);
    stroke-width: 1;
    fill: none;
    opacity: 0.7;
}
.profile-canvas .dim-label {
    fill: var(--accent-light);
    font-size: var(--font-micro);
    font-family: var(--font-mono, monospace);
    user-select: none;
    pointer-events: none;
    opacity: 0.95;
}
.profile-editor.expanded .profile-canvas .dim-label {
    font-size: var(--font-micro);
}

/* Graph editor zoom HUD (overlays the canvas top-left corner) */
.graph-zoom-hud {
    position: absolute;
    top: 10px;
    left: 10px;
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 4px 8px;
    background: rgba(34,34,38,0.92);
    border: 1px solid var(--border);
    border-radius: 6px;
    z-index: 10;
    font-size: calc(11px * var(--ui-scale));
    user-select: none;
}
.graph-zoom-hud .btn { min-width: 24px; padding: 2px 8px; }
.graph-zoom-readout {
    margin-left: 4px;
    color: var(--text-secondary);
    font-family: var(--font-mono);
    font-size: calc(11px * var(--ui-scale));
    min-width: 38px;
    text-align: right;
}
.graph-canvas-wrap { cursor: default; }

/* ============================================================
   In-app User Manual viewer
   Full-screen overlay with chapter sidebar + scrollable content.
   Dark-theme styling tuned to match the rest of the app surfaces.
   ============================================================ */
.help-overlay {
    position: fixed; inset: 0; z-index: 1100;
    background: rgba(8, 9, 12, 0.78);
    backdrop-filter: blur(6px);
    display: flex; align-items: stretch; justify-content: center;
    padding: 24px;
}
.help-shell {
    width: 100%; max-width: 1400px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
    display: flex; flex-direction: column; min-height: 0;
    overflow: hidden;
}
.help-header {
    display: flex; align-items: center; gap: 14px;
    padding: 14px 22px;
    background: linear-gradient(180deg, #1f2330 0%, #1a1d28 100%);
    border-bottom: 1px solid var(--border);
}
.help-brand {
    display: flex; align-items: center; gap: 10px;
    font-size: calc(16px * var(--ui-scale)); color: var(--text-primary);
}
.help-brand-icon { font-size: calc(22px * var(--ui-scale)); }
.help-brand-text strong { color: var(--accent-light); }
.help-header-spacer { flex: 1; }
.help-close-btn {
    background: transparent;
    border: 1px solid transparent;
    color: var(--text-secondary);
    font-size: calc(26px * var(--ui-scale)); line-height: 1;
    width: 36px; height: 36px;
    border-radius: 6px;
    cursor: pointer;
}
.help-close-btn:hover { background: var(--bg-hover); color: var(--text-primary); border-color: var(--border); }
.help-body {
    flex: 1; min-height: 0;
    display: grid;
    grid-template-columns: 240px 1fr;
}
.help-sidebar {
    background: var(--bg-panel);
    border-right: 1px solid var(--border);
    padding: 14px 8px;
    overflow-y: auto;
}
.help-nav-item {
    display: block; width: 100%; text-align: left;
    padding: 9px 14px;
    margin: 1px 0;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 6px;
    color: var(--text-secondary);
    font: 500 13px var(--font-ui);
    cursor: pointer;
}
.help-nav-item:hover { background: var(--bg-hover); color: var(--text-primary); }
.help-nav-item.active {
    background: var(--bg-input);
    color: var(--accent-light);
    border-left: 3px solid var(--accent);
    padding-left: 11px;
}
.help-content {
    overflow-y: auto;
    padding: 32px 48px;
    background: var(--bg-primary);
}
.help-loading {
    color: var(--text-muted);
    font-style: italic;
    padding: 20px 0;
}

/* ----- Doc article (rendered markdown) ----- */
.doc-article {
    max-width: 820px;
    margin: 0 auto;
    color: var(--text-primary);
    font: 15px/1.65 var(--font-ui);
}
.doc-article h1 {
    font: 700 28px/1.25 var(--font-ui);
    color: var(--accent-light);
    margin: 0 0 18px 0;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--border);
}
.doc-article h2 {
    font: 600 21px/1.3 var(--font-ui);
    color: var(--text-primary);
    margin: 32px 0 12px 0;
}
.doc-article h3 {
    font: 600 17px/1.35 var(--font-ui);
    color: var(--accent-light);
    margin: 24px 0 8px 0;
}
.doc-article p { margin: 12px 0; }
.doc-article a {
    color: var(--accent-light);
    text-decoration: none;
    border-bottom: 1px dashed var(--accent-dim);
}
.doc-article a:hover { border-bottom-style: solid; }
.doc-article ul, .doc-article ol { padding-left: 24px; margin: 10px 0; }
.doc-article li { margin: 4px 0; }
.doc-article code {
    background: var(--bg-input);
    color: var(--accent-light);
    padding: 2px 6px;
    border-radius: 4px;
    font: 13px var(--font-mono);
}
.doc-article pre {
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 14px 18px;
    overflow-x: auto;
    font: 13px/1.5 var(--font-mono);
    color: var(--text-primary);
}
.doc-article pre code { background: transparent; padding: 0; }
.doc-article blockquote {
    border-left: 3px solid var(--accent);
    margin: 14px 0;
    padding: 8px 16px;
    background: rgba(255, 158, 64, 0.05);
    color: var(--text-secondary);
    border-radius: 0 4px 4px 0;
}
.doc-article table {
    border-collapse: collapse;
    margin: 16px 0;
    width: 100%;
    font-size: calc(14px * var(--ui-scale));
}
.doc-article th, .doc-article td {
    border: 1px solid var(--border);
    padding: 8px 12px;
    text-align: left;
    vertical-align: top;
}
.doc-article th {
    background: var(--bg-panel);
    color: var(--accent-light);
    font-weight: 600;
}
.doc-article tr:nth-child(even) td { background: rgba(255, 255, 255, 0.015); }
.doc-article img {
    max-width: 100%;
    height: auto;
    border-radius: 6px;
    margin: 12px 0;
    border: 1px solid var(--border);
    background: var(--bg-elevated);
}
.doc-article hr {
    border: none;
    border-top: 1px solid var(--border);
    margin: 28px 0;
}
.doc-article .doc-extlink-stub {
    color: var(--text-muted);
    font-style: italic;
}

/* Narrow window: stack the sidebar above the content */
@media (max-width: 800px) {
    .help-body { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
    .help-sidebar {
        max-height: 35vh;
        border-right: none;
        border-bottom: 1px solid var(--border);
    }
    .help-content { padding: 20px; }
    .doc-article { font-size: calc(14px * var(--ui-scale)); }
}
