/* =========================================================================
   layout-app.css — Bare-element grid layout
   Loaded only by pages using the bare `.app` / `aside` / `#previewArea` /
   `#resizer` grid layout (b-spline-gen index.html, b-spline-gen
   bspline_gen_palette.html, frame-builder index.html).
   Contains:
   - .app grid container + responsive variants
   - header grid placement
   - aside, #previewArea, #resizer, #bottomStatusBar grid placement
   - .sticky-actions (sidebar pinned action block)
   - Color-coded panel border-left accents (.panel-stock etc.)
   - Sub-panel system (.panel-sub)
   - .panel-filter-tweaks + .tweak-row + .ck-toggle (b-spline-gen-specific)
   - Header button positioning overrides (#btnDownload, #theme-btn etc.)
   - Mobile/vertical responsive @media blocks (max-width: 700px / 400px)
   ========================================================================= */

/* =========================================================================
   1. Main app grid (3 columns: sidebar | resizer | preview)
   ========================================================================= */
.app {
    --sidebar-width: 320px;
    --preview-height: 50vh;
    display: grid;
    grid-template-columns: var(--sidebar-width) 8px 1fr;
    /* 8px for the resizer */
    grid-template-rows: auto 1fr auto auto;
    width: 100%;
    height: 100%;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
}

/* Header spans full width of grid in app layout */
header {
    grid-column: 1 / -1;
}

/* Sidebar */
aside {
    grid-column: 1;
    grid-row: 2;
    border-right: none;
    background: var(--surface);
    overflow-y: auto;
    padding: 14px 14px 60px 14px;
    display: flex;
    flex-direction: column;
    gap: var(--gap);
    min-height: 0;
}

/* Pin the seed + undo/redo block to the top of the sidebar so it
   remains accessible regardless of which panels are scrolled. The
   negative margins extend it edge-to-edge over the aside's padding,
   and top:-14px compensates for that same padding so it sits flush
   at the top of the scroll viewport. */
.sticky-actions {
    position: sticky;
    top: -14px;
    z-index: 20;
    margin: -14px -14px 0 -14px;
    padding: 12px 14px 10px 14px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    box-shadow: 0 4px 6px -4px rgba(0, 0, 0, 0.18);
}

/* =========================================================================
   2. Color-coded panel accents
   ========================================================================= */
.panel-stock {
    border-left-color: #64748b;
}

.panel-terrain {
    border-left-color: #0066cc;
}

.panel-smooth {
    border-left-color: #8b5cf6;
}

.panel-sculpt-t {
    border-left-color: #059669;
}

.panel-thicken {
    border-left-color: #d97706;
}

.panel-sculpt-b {
    border-left-color: #dc2626;
}

.panel-stamp {
    border-left-color: #20c997;
}

.panel-resolution {
    border-left-color: #65a30d;
}

.panel-preset {
    border-left-color: #0e7490;
}

/* =========================================================================
   3. Sub-panels (nested category groupings)
   ========================================================================= */
.panel-sub {
    background: rgba(0, 0, 0, 0.02);
    border-left: 2px solid rgba(0, 0, 0, 0.08);
    border-radius: 3px;
    overflow: hidden;
    flex-shrink: 0;
}

.panel-sub .panel-header {
    font-size: 10px;
    padding: 5px 10px;
    background: rgba(0, 0, 0, 0.03);
    letter-spacing: 0.08em;
}

.panel-sub .panel-header::before {
    font-size: 11px;
}

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

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

/* =========================================================================
   4. Edit-Filter sub-panel (b-spline-gen tweak sliders)
   ========================================================================= */
.panel-filter-tweaks .panel-header {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* The label span eats remaining space so the Reset button hugs the right.
   The chevron ::before pseudo-element stays left of the label. */
.panel-filter-tweaks .panel-header > span {
    flex: 1;
}

.filter-tweaks-reset {
    all: unset;
    cursor: pointer;
    font-size: 10px;
    letter-spacing: 0.04em;
    padding: 2px 8px;
    border-radius: 3px;
    color: var(--text-dim, #64748b);
    border: 1px solid var(--border, rgba(0, 0, 0, 0.12));
    background: var(--surface, #fff);
    text-transform: none;
}

.filter-tweaks-reset:hover {
    color: var(--text);
    background: var(--surface2, rgba(0, 0, 0, 0.04));
}

.panel-filter-tweaks .panel-body {
    gap: 8px;
    display: flex;
    flex-direction: column;
    padding-top: 8px;
}

.tweak-row {
    gap: 4px;
}

.tweak-row > .slider-row > input[type=range] {
    flex: 1;
    min-width: 0;
    accent-color: var(--accent);
}

.tweak-row > span {
    font-size: 11px;
    letter-spacing: 0.02em;
}

.tweak-row.tweak-modified > span {
    color: var(--accent, #2563eb);
    font-weight: 600;
}

.tweak-row.tweak-modified > span::after {
    content: ' •';
}

.tweak-reset {
    all: unset;
    cursor: pointer;
    width: 22px;
    height: 22px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    color: var(--text-dim, #64748b);
    border-radius: 3px;
}

.tweak-reset:hover {
    color: var(--text);
    background: var(--surface2, rgba(0, 0, 0, 0.06));
}

/* =========================================================================
   5. ck_ constraint toggles (b-spline-gen)
   ========================================================================= */
.ck-toggle-wrap .slider-header {
    padding-bottom: 0;
}

.ck-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    cursor: pointer;
    user-select: none;
}

.ck-toggle input[type=checkbox] {
    width: 16px;
    height: 16px;
    margin: 0;
    accent-color: var(--good);
}

.ck-toggle.ck-on {
    color: var(--good);
}

.ck-toggle.ck-off {
    color: var(--text-dim);
}

/* =========================================================================
   6. Header button overrides (b-spline-gen header)
   ========================================================================= */
#btnDownload {
    background: linear-gradient(180deg, #1d4ed8, #2563eb) !important;
    color: #ffffff !important;
    border-color: #1e40af !important;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
    font-weight: 700;
    min-width: 84px !important;
    height: 32px !important;
    padding: 0 14px !important;
}

/* #btnDownloadAddin width is now handled by the .cad-nav-btn class
   (24×24 icon button) defined inline in bspline_gen_palette.html. */

#theme-btn {
    width: 32px !important;
    min-width: 32px !important;
    padding: 0 !important;
}

#btnDownload:hover {
    background: linear-gradient(180deg, #2563eb, #1d4ed8) !important;
}

/* =========================================================================
   7. Preview area
   ========================================================================= */
#previewArea {
    grid-column: 3;
    grid-row: 2;
    border-left: none;
    position: relative;
    background: transparent !important;
    overflow: hidden;
    padding: 0;
    min-height: 0;
    min-width: 0;
    display: flex;
    align-items: stretch;
    justify-content: stretch;
    width: 100%;
    height: 100%;
}

#previewCanvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    opacity: 0;
    background: transparent !important;
}

#previewCanvas.ready {
    animation: canvasFadeIn 2s ease-out both;
}

@keyframes canvasFadeIn {
    to { opacity: 1; }
}

.preview-hint {
    position: absolute;
    bottom: 12px;
    right: 14px;
    font-size: 11px;
    color: var(--muted);
    pointer-events: none;
    background: rgba(255, 255, 255, .8);
    padding: 3px 8px;
    border-radius: 4px;
    border: 1px solid var(--border);
}

/* =========================================================================
   8. Bottom status bar
   ========================================================================= */
#bottomStatusBar {
    grid-row: 4;
}

/* =========================================================================
   9. Native CAD layout (.cad-app-shell / .cad-main-content / .cad-sidebar
       / .cad-resizer / .cad-viewport / #previewArea / #previewCanvas)
   -------------------------------------------------------------------------
   These rules used to live in an inline <style> block at the top of
   bspline_gen_palette.html. They were moved here so the mobile @media
   block (Section 10 below) can actually override them at narrow
   viewports — when this rule lived after layout-app.css in source order,
   it stomped on the @media rules' grid-template-columns / -rows even at
   ≤700px and the responsive layout never engaged.
   Page-specific styles (.cad-sidebar .panel overrides, .cad-nested-input,
   .cad-stepper, etc.) intentionally stay inline in the page since they
   only apply to b-spline-gen and nothing else loads them.
   ========================================================================= */
:root {
    --cad-sidebar-width: 260px;
}

.cad-app-shell {
    background: #f5f5f5;
}

.cad-main-content {
    display: grid;
    grid-template-columns: var(--cad-sidebar-width) auto 1fr;
    grid-template-rows: 1fr;
    flex: 1;
    height: calc(100vh - 35px); /* Adjust for navbar exact height */
    overflow: hidden;
    background: #f5f5f5;
}

.cad-sidebar {
    grid-column: 1;
    grid-row: 1;
    width: var(--cad-sidebar-width);
    height: 100%;
    background: #fdfdfd;
    border-right: 1px solid var(--cad-border-standard);
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    min-height: 0;
}

.cad-resizer {
    grid-column: 2;
    grid-row: 1;
    width: 10px; /* Broader interactive area */
    height: 100% !important;
    align-self: stretch !important;
    cursor: col-resize;
    background: #eee;
    border-left: 1px solid #ddd;
    border-right: 1px solid #ddd;
    transition: background 0.2s;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    z-index: 100; /* Stay above canvas */
}

.cad-resizer::after {
    content: "";
    width: 2px;
    height: 60px; /* Centered pill length */
    background: #888;
    border-radius: 2px;
    transition: background 0.2s, height 0.2s;
}

.cad-resizer:hover,
.cad-resizer.resizing {
    background: #e8e8e8;
}

.cad-resizer:hover::after,
.cad-resizer.resizing::after {
    background: #0696D7; /* Highlight pill on interaction */
    height: 80px;
}

.cad-viewport {
    grid-column: 3;
    grid-row: 1;
    height: 100%;
    width: 100%;
    min-width: 0;
    min-height: 0;
    background: #111;
    position: relative;
    display: flex;
    flex-direction: column;
}

/* Ensure the Three.js canvas fills the CAD viewport exactly */
#previewArea {
    flex: 1;
    width: 100%;
    height: 100%;
    position: relative;
    background: #111;
    overflow: hidden;
    min-height: 0;
}

#previewCanvas {
    width: 100% !important;
    height: 100% !important;
    display: block;
}

/* =========================================================================
   10. Responsive — Mobile layout for .cad-main-content
   =========================================================================
   The desktop layout (defined in Section 9 above as a 3-column grid:
   sidebar | resizer | viewport) flips to a single-column vertical
   stack on narrow viewports:
     row 1 — .cad-viewport (3D preview, 40vh — 35vh under 400px)
     row 2 — .cad-resizer  (horizontal grip, 12px tall)
     row 3 — .cad-sidebar  (panels, scrollable, takes remaining space)
   The sticky `.cad-panel-section` at the top of .cad-sidebar is already
   position: sticky in the page's inline styles, so the Seed / Undo / Redo
   block stays pinned at the top of the now-bottom panel area without
   needing extra rules here.
   NOTE on the resizer: the existing JS in bspline_gen_palette.html
   (~line 976) tracks horizontal X-delta and adjusts sidebar column
   width. On this mobile layout the column is 1fr — so the cursor reads
   row-resize but the drag won't actually adjust preview height. CSS
   layout is correct without that fix; a follow-up JS change can detect
   viewport width and switch to Y-delta + grid-template-rows adjustment.
   The pre-cad-* mobile rules that previously lived here were scoped
   with `.app:not(.cad-main-content)` to fence themselves off from the
   migrated page. Since no HTML in the project still uses the bare
   `.app` layout, those rules were removed in this refactor along with
   the corresponding desktop resizer fence.
   ========================================================================= */
@media (max-width: 700px) {
    .cad-main-content {
        grid-template-columns: 1fr;
        grid-template-rows: 40vh 12px 1fr;
    }

    .cad-main-content > .cad-viewport {
        grid-column: 1;
        grid-row: 1;
        min-height: 0;
    }

    .cad-main-content > .cad-resizer {
        grid-column: 1;
        grid-row: 2;
        width: 100%;
        height: 12px !important;
        cursor: row-resize;
        border-left: none;
        border-right: none;
        border-top: 1px solid #ddd;
        border-bottom: 1px solid #ddd;
    }

    .cad-main-content > .cad-resizer::after {
        width: 60px;
        height: 2px;
    }

    .cad-main-content > .cad-sidebar {
        grid-column: 1;
        grid-row: 3;
        width: 100%;
        border-right: none;
        border-top: none;
        padding-bottom: 60px;
    }
}

@media (max-width: 400px) {
    .cad-main-content {
        grid-template-rows: 35vh 12px 1fr;
    }
}
