﻿/* ============================================================
   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 */
}

.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: 18px;
    font-weight: 700;
    margin-bottom: 6px;
}
.export-modal-status {
    font-size: 13px;
    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: 28px;
    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: 13px;
    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: 15px;
}

/* ============================================================
   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: 16px;
    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: 12px;
    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: 11px;
    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: 22px;
}

.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: 24px; 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: 11px; 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: 11px;
    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: 14px; flex-shrink: 0; margin-top: 1px; }

/* ============================================================
   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: 40px; 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: 11px;
}

.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: 11px;
    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: 12px;
    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: 56px;
    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: 80px;
    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: 13px;
    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: 11px;
}

/* ============================================================
   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: 12px;
    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: 11px;
}
.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: 11px;
}
.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: 11px;
    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: 11px;
}

.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: 16px; 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: 11px;
    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: 15px;
    color: var(--accent-light);
    margin-bottom: 10px;
    border-bottom: 1px solid var(--border);
    padding-bottom: 8px;
}
.pottery-section-title {
    font-size: 11px;
    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: 11px;
}
.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: 20px; line-height: 1; }
.pottery-panel.expanded .pottery-tool-icon { font-size: 24px; }
.pottery-row {
    display: grid;
    grid-template-columns: 90px 1fr 70px;
    gap: 8px;
    align-items: center;
    margin: 6px 0;
    font-size: 12px;
}
.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: 11px;
}
.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: 12px;
}
.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: 11px;
    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: 16px; 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: 12px;
}
.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: 14px; }
.graph-param {
    display: grid;
    grid-template-columns: 1fr auto;
    column-gap: 8px; row-gap: 2px;
    align-items: center;
    margin: 10px 0; font-size: 12px;
}
.graph-param label { color: var(--text-secondary); font-weight: 500; }
.graph-param .val { font-family: var(--font-mono); font-size: 11px; 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: 12px; 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: 11px;
    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: 12px;
    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: 11px;
}
.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: 11px;
    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: 11px;
    min-width: 38px;
    text-align: right;
}
.graph-canvas-wrap { cursor: default; }
