:root {
    --color-bg-tab:          #edf0f5;
    --color-accent-blue:     #7AAEC8;
    --color-accent-blue-dark: #305674;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}


html,
body {
    overflow: hidden;
    max-width: 100%;
}

html {
    height: 100%;
}


body {
    font-family: 'Century Gothic', CenturyGothic, AppleGothic, 'Trebuchet MS', sans-serif;
    background: #000000;
    padding: 12px;
    color: #333;
    zoom: 0.75;
    height: 133.333vh;
}

.container {
    width: 100%;
    height: calc(133.333vh - 32px);
    background: #f4f8fb;
    border-radius: 0;
    padding: 14px 4px 16px;
    box-shadow: none;
    display: grid;
    grid-template-rows: auto auto minmax(0, 1fr);
    gap: 12px;
    overflow: hidden;
}

.top-header {
    display: flex;
    align-items: stretch;
    gap: 8px;
    /* Matches the horizontal inset used by the tab content panels below
       (.glass-selector-section, .only-glass-layout) so the tab bar's width
       lines up with the panels instead of being narrower than them. */
    margin: 0 clamp(10px, 8vw, 200px);
}

.nav-logo-box {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: clamp(4px, 0.5vh, 6px) clamp(10px, 1vw, 20px);
    background: #fff;
    border: 1px solid var(--panel-border);
    box-shadow: 0 2px 8px rgba(34, 48, 67, 0.06);
    flex-shrink: 0;
    align-self: stretch;
    min-height: clamp(36px, 5vh, 54px);
}

.guide-me-btn {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    align-self: stretch;
    min-height: clamp(36px, 5vh, 54px);
    padding: clamp(4px, 0.5vh, 6px) clamp(12px, 1.2vw, 20px);
    background: #fff;
    border: 1.5px solid var(--color-accent-blue-dark);
    border-radius: 10px;
    color: var(--color-accent-blue-dark);
    font-family: inherit;
    font-weight: 700;
    font-size: clamp(11px, 0.95vw, 15px);
    cursor: pointer;
    transition: background 0.15s ease;
}

.guide-me-btn:hover {
    background: rgba(122, 174, 200, 0.12);
}

.guide-me-q {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--color-accent-blue-dark);
    color: #fff;
    font-size: 10px;
    font-weight: 800;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

/* ── Guided tour (Guide me) ───────────────────────────────────────────────
   Every panel that can be a tour stop gets dimmed/desaturated while the
   tour is active; the current stop gets .tour-spot, which cancels the dim
   and adds a highlight ring instead — same spotlight approach validated in
   the mockup (dim everything, ring the current target, caption at the
   bottom), just applied to the real panel classes instead of mock ones. */
body.tour-active .rail-panel,
body.tour-active .facade-sketch-panel,
body.tour-active .limits-panel,
body.tour-active .rail-viewer,
body.tour-active .rail-solar,
body.tour-active .rail-results-row,
body.tour-active .nav-tabs,
/* Tab 3 has no .rail-solar/.rail-results-row split — its equivalent tour
   stops (#ccfBShadingFreqCard/#ccfBViewsOutCard) are sibling cards sharing
   this class instead, so dimming has to target them individually rather
   than their shared .ccf-panel ancestor: opacity/filter on a parent apply
   to its whole rendered subtree, so a child's own .tour-spot filter:none
   can't cancel a dimmed ancestor's effect the way sibling-level dimming does. */
body.tour-active .ccf-section-card {
    filter: grayscale(0.5) brightness(0.92);
    opacity: 0.5;
    transition: filter 0.3s ease, opacity 0.3s ease, box-shadow 0.3s ease;
}

body.tour-active .tour-spot {
    filter: none;
    opacity: 1;
    position: relative;
    z-index: 60;
    box-shadow: 0 0 0 3px var(--color-accent-blue-dark), 0 14px 32px rgba(34, 48, 67, 0.4);
    border-radius: 10px;
}

/* .container, .tab-panel.active, .rail-layout, .performance-panel (the
   shared card-chrome base class — #ccfBPerformancePanel/.ccf-panel is one),
   and (Tab 3 only) .ccf-results-outer all clip overflow (scrollbar/layout
   containment, unrelated to the tour) — panels that sit flush against any
   of those edges had the highlight ring above clipped off at the top or
   bottom instead of rendering fully. .ccf-results-outer has zero top
   padding (see style.css), so #ccfBShadingFreqCard's ring had nowhere to
   go at the top specifically, and .performance-panel's own overflow:hidden
   (its base rule, not overridden by .ccf-panel) was clipping it a level
   further up regardless. Only relaxed while the tour is active, so normal
   layout containment is unaffected otherwise. */
body.tour-active .container,
body.tour-active .tab-panel.active,
body.tour-active .rail-layout,
body.tour-active .performance-panel,
body.tour-active .ccf-results-outer {
    overflow: visible;
}

.tour-caption {
    position: fixed;
    left: 50%;
    bottom: 28px;
    transform: translateX(-50%);
    width: min(860px, calc(100vw - 40px));
    z-index: 200;
    background: var(--color-navy-text);
    color: #fff;
    border-radius: 14px;
    padding: 24px 28px;
    box-shadow: 0 14px 38px rgba(0, 0, 0, 0.4);
    display: none;
}

.tour-caption.show {
    display: block;
}

.tour-caption .tc-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 10px;
}

.tour-caption .tc-step {
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    color: var(--color-accent-blue);
}

.tour-caption .tc-close {
    background: none;
    border: none;
    color: #c9d3dd;
    font-size: 26px;
    cursor: pointer;
    line-height: 1;
    padding: 2px 6px;
}

.tour-caption .tc-title {
    font-size: 22px;
    font-weight: 700;
    margin-bottom: 10px;
}

.tour-caption .tc-body {
    font-size: 17px;
    line-height: 1.6;
    color: #dbe4ec;
}

.tour-caption .tc-body ul {
    margin: 0;
    padding-left: 22px;
}

/* Nested list (e.g. Flexible Limit's Cooling Season/3% allowance/Toutdoor
   sub-items) — a bit of breathing room from the parent bullet's own text. */
.tour-caption .tc-body li > ul {
    margin-top: 6px;
}

.tour-caption .tc-body li {
    margin-bottom: 8px;
}

.tour-caption .tc-body li:last-child {
    margin-bottom: 0;
}

.tour-caption .tc-body li b {
    color: #fff;
}

.tour-caption .tc-nav {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 12px;
    margin-top: 20px;
}

.tour-caption .tc-btn {
    font-family: inherit;
    font-size: 16px;
    font-weight: 700;
    border-radius: 8px;
    padding: 10px 20px;
    cursor: pointer;
    border: 1px solid rgba(255, 255, 255, 0.3);
    background: transparent;
    color: #fff;
}

.tour-caption .tc-btn.primary {
    background: var(--color-accent-blue);
    border-color: var(--color-accent-blue);
    color: #12202c;
}

.tour-caption .tc-dots {
    display: flex;
    gap: 7px;
    margin-right: auto;
}

.tour-caption .tc-dots span {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.3);
}

.tour-caption .tc-dots span.on {
    background: var(--color-accent-blue);
}

.top-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 clamp(10px, 1.25vw, 24px);
    min-height: clamp(36px, 5vh, 54px);
    background: transparent;
    border: none;
    box-shadow: none;
    flex: 1;
}

.nav-logo {
    height: auto;
    max-height: clamp(22px, 3vh, 34px);
    width: auto;
    max-width: clamp(100px, 8.3vw, 160px);
    object-fit: contain;
}

.nav-tabs {
    display: flex;
    gap: 6px;
    justify-content: center;
    align-items: center;
    background: var(--color-bg-tab);
    border: 1px solid rgba(34, 48, 67, 0.08);
    border-radius: 8px;
    padding: 3px 8px;
    align-self: stretch;
    width: 100%;
    box-shadow: inset 0 2px 4px rgba(36, 52, 71, 0.08);
}

.nav-tab {
    font-size: clamp(10px, 1.05vw, 18px);
    font-weight: 700;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    border: none;
    background: transparent;
    color: var(--text-faint);
    cursor: pointer;
    border-radius: 6px;
    transition: all 0.2s ease;
    font-family: inherit;
    white-space: nowrap;
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: clamp(8px, 1.5vh, 16px) clamp(6px, 1vw, 20px);
}

.nav-tab:hover {
    color: var(--text-muted);
    background: rgba(255,255,255,0.7);
}

.nav-tab.active {
    /* Same keycap shape/shadow/lift as the selector rail's active pills,
       but kept on the original light-blue fill (not the pills' navy) —
       just the "3D pressed" treatment applied to the old color template. */
    background: var(--color-accent-blue);
    color: #fff;
    box-shadow: 0 3px 0 #4d7891, 0 5px 8px rgba(34, 48, 67, 0.3);
    transform: translateY(-1px);
}

.tab-panel {
    display: none;
    min-height: 0;
    overflow: hidden;
    grid-row: 3;
}

.tab-panel.active {
    position: relative;
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
    gap: 12px;
}

.container[data-active-tab="sawtooth-options"] #inflectionWrapper {
    display: none;
}

h1 {
    color: var(--color-navy-text);
    text-align: center;
    font-size: 20px;
    font-weight: 700;
    letter-spacing: 1.2px;
    text-transform: uppercase;
}

h2 {
    color: var(--color-navy-text);
    font-size: 15px;
    text-transform: uppercase;
    letter-spacing: 1px;
    padding-bottom: 0;
    margin: 0;
}

.solar-panel h2 {
    font-size: 20px;
}

.panel-header-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-bottom: 1px solid var(--border-light);
    padding-bottom: 16px;
}

.season-legend {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 12px;
    font-weight: 600;
    color: #555;
}

.season-legend span:not(.legend-dot) {
    margin-left: -6px;
}

/* Moved to the very bottom of the charts grid, centered, instead of sitting
   inline with the PSG Limit/Flexible Limit filter row up top. */
.season-legend--bottom {
    justify-content: center;
    flex-shrink: 0;
    margin-top: 6px;
    font-size: 13px;
}

.legend-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    display: inline-block;
    flex-shrink: 0;
}

.glass-selector-section {
    position: relative;
    min-height: clamp(100px, 17.6vh, 190px);
    padding: clamp(8px, 1vh, 12px) 32px;
    display: flex;
    justify-content: space-evenly;
    align-items: flex-start;
    gap: 10px;
    /* visible (not hidden) so the "Find Compliant Case" hover tooltip can
       pop out below the button without being clipped by this panel's
       fairly short fixed height. */
    overflow: visible;
    border: 1px solid rgba(255, 255, 255, 0.55);
    border-radius: 14px;
    box-shadow: 0 4px 22px rgba(34, 48, 67, 0.20), inset 0 1px 0 rgba(255, 255, 255, 0.5);
    margin: 0 clamp(10px, 8vw, 200px);
}

/* Sky photo, blurred — this is the "glass" itself. Lives on ::before
   (inset:0 against this same element) rather than a fixed-size layer on
   an ancestor, so it always exactly matches the panel's real rendered box
   even when its height grows (e.g. the DGU/Frit/Width option lists making
   the panel taller than its clamp() min-height) — no more guessing a
   height and leaving flat page background exposed underneath.
   clip-path (not overflow:hidden, since the panel needs overflow:visible
   for the "Find Compliant Case" tooltip) keeps the blur from bleeding
   past the rounded corners. */
.glass-selector-section::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    clip-path: inset(0 round 14px);
    background-image: url("assets/sky-backdrop.jpg");
    background-size: cover;
    background-position: center 65%;
    filter: blur(1.5px) saturate(115%);
    z-index: 0;
    pointer-events: none;
}

/* Tint + frit dots, combined into one translucent layer that sits on top
   of the blurred sky (::before) and below the real content (which keeps
   its own z-index: 2/3 to stay above both). Tint color reacts to the
   selected DGU type, dot pattern to the selected Frit Density — both set
   via CSS custom properties in updateDguPanelTint()/updateFritDotTexture()
   (main.js). --tint-a/--tint-b fallbacks are the default (70/33) tint. */
.glass-selector-section::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background-image:
        radial-gradient(circle, rgba(0, 0, 0, calc(0.65 * var(--dot-opacity, 0))) var(--dot-r, 0px), transparent var(--dot-r, 0px)),
        linear-gradient(135deg, var(--tint-a, rgba(173, 214, 232, 0.42)), var(--tint-b, rgba(122, 174, 200, 0.34)));
    background-size: var(--dot-gap, 14px) var(--dot-gap, 14px), cover;
    background-blend-mode: multiply, normal;
    z-index: 1;
    pointer-events: none;
    transition: background 0.25s ease;
}

/* ==========================================
   SHARED 3-COLUMN TAB LAYOUT (tabs 1-4)
   Vertical selector rail (every parameter that tab exposes, as one
   continuous stacked list) | Limits panel above the 3D viewer | Solar
   Gains above the Daylight/Thermal Comfort result cards.

   Replaces the old horizontal top selector bar
   (.glass-selector-section / .tab2-selector-row / .fixed-elements-card)
   and the per-tab .main-layout grid. The rail keeps the exact same
   blurred-sky + DGU-reactive tint + frit-dot treatment the old top bar
   had, just reshaped for a tall narrow box — the CSS custom properties
   driving it (--tint-a/--tint-b from updateDguPanelTint(),
   --dot-r/--dot-gap/--dot-opacity from updateFritDotTexture(), both in
   main.js) are unchanged.
   ========================================== */
.rail-layout {
    display: grid;
    /* Design Variables rail widened (was clamp(290px,23vw,420px)); middle
       column at 0.7fr (was 0.72fr originally, dipped to 0.55/0.60/0.85 in
       between) — results column back to its original 1.4fr. */
    grid-template-columns: clamp(340px, 27vw, 480px) minmax(0, 0.7fr) minmax(0, 1.4fr);
    /* Explicit 1fr row so the 3D viewer/solar panel get a definite height
       to stretch into — without it the canvas's container can resolve to
       0 height and the WebGLRenderer initializes at 0x0 (invisible). */
    grid-template-rows: minmax(0, 1fr);
    gap: clamp(8px, 0.9vw, 18px);
    width: 100%;
    margin: 0 auto;
    padding: 0 clamp(10px, 8vw, 200px);
    min-height: 0;
    overflow: hidden;
    flex: 1;
}

/* Reuses .performance-panel for the card chrome (border/radius/shadow),
   overriding its overflow:hidden so a rail that outgrows a short viewport
   scrolls instead of clipping rows. */
.rail-panel {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 0;
    min-height: 0;
    overflow: auto;
    isolation: isolate;
}

/* Cloud backdrop + DGU tint/frit-dot overlay removed for every tab (used to
   be Tab 1-only via a #railOnlyGlass::before/::after override cancelling
   the .glass-rail::before/::after rules below — now removed for tabs 2-4
   too, so the base rules themselves are gone rather than left dead). */

/* Wraps just the rows (not the centering slack .rail-panel adds above and
   below) so the dynamically-drawn chain line (drawRailNetwork in main.js)
   measures from an unpadded box.
   No explicit width — shrinks to fit its widest row's natural content
   width (e.g. DGU Type's 3-pill row), and .rail-panel's align-items:center
   centers that shrink-wrapped block within the panel. Every .rail-row then
   stretches (flex default) to match that same width, so every row's circle
   still lines up at the same left edge — centered as a block, but each
   row's own contents stay left-anchored to one another. */
.rail-inner {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    gap: clamp(28px, 4.6vh, 54px);
    max-width: 100%;
}

/* Tab 2 now has 6 rows (DGU/Frit/Window Width/Shading Type/Brise Soleil
   Depth/Brise Soleil Inclination) — the base gap (tuned for 3-4 rows) was
   already tightened once for this tab, but at the base circle size (shared
   .rail-row-container .glass-circle, ~90-132px) 6 of them still read as
   crowded. Tightened further here (smaller gap) and the circles/pills
   below shrunk to match, so the row density feels intentional rather than
   squeezed — same visual language, just scaled down. */
#railFe .rail-inner,
#railFeb .rail-inner {
    gap: clamp(18px, 3.4vh, 36px);
}

#railFe .rail-row-container .glass-circle,
#railFeb .rail-row-container .glass-circle {
    width: clamp(80px, 8.5vh, 112px);
    height: clamp(80px, 8.5vh, 112px);
    font-size: clamp(13px, 1.15vw, 19px);
}

#railFe .glass-option,
#railFe .fabric-option,
#railFe .winwidth-option,
#railFe .elementdepth-option,
#railFe .sidefinrot-option,
#railFe .shadingtype-option,
#railFe .frit-option,
#railFeb .glass-option,
#railFeb .fabric-option,
#railFeb .winwidth-option,
#railFeb .elementdepth-option,
#railFeb .sidefinrot-option,
#railFeb .shadingtype-option,
#railFeb .frit-option {
    min-width: 42px;
    padding: 7px 15px;
    font-size: 16px;
}

/* Approved rail rearrangement (mockup): circle stays pinned to the row's
   left edge (its default flex position — unchanged), and the pill popup
   centers itself in whatever space is left to the right of it, rather than
   sitting immediately next to it. margin:auto on a non-growing flex child
   is the standard way to center a single item within a flex row's leftover
   space — .glass-popup.rail-hpopup already has justify-content:center for
   its own pills, so this just gives the *popup itself* the same treatment
   one level up, no markup changes needed. The dashed connector chain
   (drawRailNetwork() in main.js) measures actual element positions at
   runtime, so it automatically follows the new layout with no JS changes. */
#railFe .glass-popup.rail-hpopup,
#railFeb .glass-popup.rail-hpopup,
#railCcf .glass-popup.rail-hpopup {
    margin-left: auto;
    margin-right: auto;
}

/* .rail-inner normally shrink-wraps to its widest row's natural content
   width, then .rail-panel's align-items:center centers that (narrower)
   block as a whole — which left every row's circle sitting inset from the
   panel's actual left edge rather than flush against it. Stretching
   .rail-inner to the panel's full width fixes that (circles now sit right
   at the padding edge) and also gives the popups' margin:auto more real
   room to center into. */
#railFe .rail-inner,
#railFeb .rail-inner,
#railCcf .rail-inner {
    width: 100%;
    /* Shifts the whole row block (circle + pills) inward from the panel's
       left edge — the circle used to sit flush against it. */
    padding-left: clamp(16px, 2.4vw, 36px);
}

/* Labels used to force a line break (e.g. "FRIT<br>DENSITY (%)") to keep
   them from wrapping awkwardly at the old, narrower rail width — the rail
   is wider now, so the <br>s were removed from the markup and this just
   guarantees the browser doesn't pick its own wrap point instead. */
#railFe .rail-row .glass-label-text,
#railFeb .rail-row .glass-label-text {
    white-space: nowrap;
}

/* .rail-panel centers .rail-inner vertically by default — extra bottom
   padding shifts that centered block up a bit within the panel. */
/* No longer needs bottom padding reserved for .compliant-case-btn — that
   button moved out into its own .compliant-case-panel next to Facade
   Articulation (see .rail-bottom-row above), freeing this space for the
   selector rows themselves. */

.rail-row {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    gap: 4px;
    width: 100%;
}

.rail-row .glass-label-text {
    min-height: 0;
    text-align: left;
    white-space: normal;
    font-size: clamp(12px, 0.9vw, 17px);
    /* Every multi-word title now wraps onto 2 lines (see the <br> in
       index.html — e.g. "WINDOW"/"WIDTH (m)") — tight line-height keeps
       the two lines close together instead of reading as separate rows. */
    line-height: 1.05;
}

/* Same legibility treatment the old tinted top bar gave its field titles —
   bold navy on an opaque chip, so the labels stay readable however dense
   the frit dot texture gets. */
.glass-rail .glass-label-text {
    display: inline-block;
    /* Left-aligned so the title sits directly above the circle (the
       leftmost element in .rail-row-container) instead of centered over
       the whole row, which drifted right of the circle whenever the pill
       options made the row wider than the title itself. */
    align-self: flex-start;
    font-weight: 800;
    color: var(--color-navy-text);
    background: rgba(255, 255, 255, 0.85);
    padding: 2px 8px;
    border-radius: 5px;
    box-shadow: 0 1px 3px rgba(34, 48, 67, 0.12);
}

/* No cloud backdrop behind these titles on any tab anymore (see the removed
   .glass-rail::before/::after rules above), so the opaque white legibility
   chip would just read as a stray box/border around the text — removed for
   all 4 tabs, not just Tab 1. */
.glass-rail .glass-label-text {
    background: none;
    padding: 0;
    box-shadow: none;
}

.rail-row-container {
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    align-items: center;
    gap: 16px;
    width: 100%;
}

/* Sized off viewport height rather than width: the binding constraint is
   fitting Tab 4's 6 rows into the column without scrolling. */
.rail-row-container .glass-circle {
    /* Raised so the circle's min/max stay >= the largest fixed-px header
       image (94px, see renderHeaderImage() call sites in main.js) at every
       viewport height — previously the circle could shrink to 62px while
       the image inside stayed 94px, getting clipped by the circle's round
       mask. */
    width: clamp(90px, 9vh, 132px);
    height: clamp(90px, 9vh, 132px);
    font-size: clamp(13px, 1.15vw, 21px);
    flex-shrink: 0;
}

/* The rail is vertical, so each row's options rotate to a horizontal list
   beside its circle (the old top bar stacked them below it). Reuses
   .glass-popup's pill chrome and each option's own base styling as-is.
   Combined with .glass-popup in the selector (not just .rail-hpopup alone)
   so this wins the cascade regardless of source order — .glass-popup's own
   flex-direction:column further down the file was silently overriding a
   same-specificity .rail-hpopup rule before this fix. */
.glass-popup.rail-hpopup {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px;
}

.rail-hpopup .glass-option,
.rail-hpopup .fabric-option,
.rail-hpopup .winwidth-option,
.rail-hpopup .elementdepth-option,
.rail-hpopup .sidefinrot-option,
.rail-hpopup .shadingtype-option,
.rail-hpopup .frit-option {
    cursor: pointer;
    font-size: clamp(13px, 0.95vw, 17px);
    padding: 7px 13px;
    white-space: nowrap;
}

/* Middle column: Limits panel stacked above the 3D viewer. */
.rail-mid {
    min-height: 0;
    display: grid;
    grid-template-rows: minmax(0, 0.55fr) minmax(0, 1fr);
    gap: clamp(8px, 0.9vw, 18px);
}

.limits-panel {
    min-height: 0;
    overflow: auto;
    gap: 0;
    /* .performance-panel (base class) is flex-column with no
       justify-content, so content sits at the top and leaves empty space
       below inside this panel — centering shifts the whole block (title,
       PSG slider, divider, Fixed/Flexible Limit) down to close that gap. */
    justify-content: center;
}

/* CCF's Limits panel only has the PSG Limit Target slider (no Fixed/
   Flexible Limit row like Tabs 2/4), so the base rule's vertical centering
   (above) left "Limits" sitting well below the panel's top edge instead of
   pinned there like every other tab's title. */
#tab-tab6 .limits-panel {
    justify-content: flex-start;
    padding-top: clamp(16px, 3vh, 32px);
}

/* The PSG Limit Target slider (CCF's only Limits row — no Fixed/Flexible
   Limit pair like Tabs 2/4) used to sit right under the "Limits" title with
   a large empty gap below it, since the title-to-top fix above stopped the
   whole panel from centering. Growing the slider row to fill the rest of
   the panel and centering its own content within that puts the slider back
   in the middle of the panel's remaining space, title still pinned at top. */
#tab-tab6 .filter-row.limits-stack {
    flex: 1;
    justify-content: center;
    min-height: 0;
}

.limits-panel h2 {
    text-align: center;
    margin: 0 0 6px;
    font-size: 18px;
}

/* Direct child of .rail-panel (sibling to .rail-inner), pinned to the
   panel's own top edge the same way .compliant-case-btn is pinned to the
   bottom — .rail-panel centers .rail-inner vertically, so a title placed
   inside .rail-inner just sits at the top of that centered block, not the
   actual top of the panel. Absolute positioning fixes it in place
   regardless of how many rows .rail-inner ends up centering. */
.rail-panel-title {
    position: absolute;
    top: 12px;
    left: 12px;
    right: 12px;
    text-align: center;
    margin: 0;
    font-size: 18px;
    z-index: 1;
}

/* This column is much narrower than the old full-width header row, so the
   three controls shrink to fit. .filter-row already stacks them
   vertically; this just tightens the spacing and sizing. */
.limits-stack {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 24px;
}

.limits-stack .filter-group {
    padding: 8px 6px 10px;
    width: 100%;
}

/* #psgFilterRow (Tab 1's) carries id-specificity size bumps further up
   this file for the old wide top-bar layout — these have to match that
   specificity to win them back down for the narrow column. */
.limits-stack .filter-group-label,
#psgFilterRow.limits-stack .filter-group-label {
    font-size: clamp(12px, 0.9vw, 17px);
    font-weight: 800;
    color: var(--color-navy-text);
}

.limits-stack .psg-slider,
#psgFilterRow.limits-stack .psg-slider,
.filter-row.limits-stack .psg-slider {
    width: calc(100% - 30px);
    margin: 0 auto;
}

/* Horizontal rule between the PSG Limit slider and the Fixed/Flexible
   Limit row below it. */
.limits-divider {
    width: 100%;
    max-width: 280px;
    border: none;
    border-top: 1px solid var(--panel-border);
    margin: 0;
}

/* Tabs 3/4 (Automated Blinds) — Fixed/Flexible Limit toggle removed since
   the tabs always run with blinds on and no Flexible Limit mode applies to
   dynamic shading; this note replaces it. */
.limits-fixed-note {
    width: 100%;
    max-width: 320px;
    margin: 0 auto;
    text-align: left;
    font-size: 17px;
    font-weight: 700;
    color: var(--text-body-dark);
    line-height: 1.4;
    padding: 6px 6px 0 26px;
}

.limits-fixed-note li {
    margin-bottom: 4px;
}

.limits-fixed-note li:last-child {
    margin-bottom: 0;
}

/* Fixed Limit and Flexible Limit share the row equally (flex:1 each on the
   .filter-group children below), split by a thin vertical rule — instead
   of stacking one above the other like every other row in this column. */
.limits-pair {
    display: flex;
    align-items: flex-start;
    gap: 18px;
    width: 100%;
}

.limits-pair .filter-group {
    flex: 1;
    width: auto;
    min-width: 0;
}

.limits-vdivider {
    align-self: stretch;
    width: 1px;
    background: var(--panel-border);
    flex-shrink: 0;
}

/* The Flexible Limit group's 3 options don't fit this narrow column even
   at reduced size, so they stack into a vertical pill list instead of the
   horizontal sliding-thumb segment — the thumb doesn't translate to a
   vertical layout, so it's hidden in favor of .seg-opt's own solid fill
   to show the active option. */
.limits-stack .scatter-seg {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    /* Gap so the 3 stacked options read as separate pills — .seg-opt has no
       background/border of its own when inactive (see base .seg-opt further
       down), so with gap:0 (the base .scatter-seg default) they blended
       into one solid block against the shared track background. */
    gap: 6px;
    border-radius: 10px;
    width: 100%;
    max-width: 280px;
}

.limits-stack .seg-thumb {
    display: none;
}

.limits-stack .seg-opt,
#psgFilterRow.limits-stack .seg-opt {
    font-size: 17px;
    padding: 10px 12px;
    text-align: center;
    border-radius: 9px;
    white-space: normal;
    /* Inactive options have no background of their own (base .seg-opt is
       transparent) — without this, the gap above between pills only shows
       the shared track background, which can still read as one block if it
       doesn't contrast enough with the panel behind it. */
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
}

/* .seg-thumb (the sliding highlight pill) is hidden above since it can't
   translate to this stacked/column layout — without it, .seg-opt.active's
   own color:#fff (further down this file) had nothing to show against,
   reading as invisible white text on the plain panel background. Give the
   active option its own solid fill directly instead.
   Must match #psgFilterRow.limits-stack .seg-opt's specificity (that rule
   carries an ID, this one didn't) — otherwise the ID-qualified rule's
   panel-bg background wins over this navy fill on Tab 1, leaving white
   .active text invisible against a light background. */
.limits-stack .seg-opt.active,
#psgFilterRow.limits-stack .seg-opt.active {
    /* Same fill/border/weight as the selector rail's active pills (DGU
       Type, Frit Density, etc. — see .glass-option.active and friends
       above) instead of the darker --seg-thumb-bg, so Fixed/Flexible Limit
       match the rest of the panel's "selected" look. */
    background: var(--color-accent-blue-dark);
    border-color: var(--color-accent-blue-dark);
    font-weight: 700;
    /* Same "Keycap" treatment as the selected rail pills/Compliant Case
       button — solid darker bottom lip + drop shadow, lifted slightly. */
    box-shadow: 0 3px 0 #1c3346, 0 5px 8px rgba(34, 48, 67, 0.4);
    transform: translateY(-1px);
}

.rail-viewer {
    min-height: 0;
    position: relative;
}

/* Right column: Solar Gains above the two result cards. */
.rail-right {
    min-height: 0;
    display: grid;
    grid-template-rows: minmax(0, 1.35fr) minmax(0, 1fr);
    gap: clamp(8px, 0.9vw, 18px);
}

.rail-solar {
    min-height: 0;
    gap: 0;
}

.rail-solar h2 {
    text-align: center;
    margin: 0 0 8px;
    white-space: nowrap;
}

.rail-results-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(8px, 0.9vw, 18px);
    min-height: 0;
}

/* Tab 4's No Blinds vs With Blinds comparison — DEMO layout (static
   illustrative numbers, see index.html) replacing the usual Solar Gains
   chart + Daylight/Thermal Comfort cards in .rail-right. Single-row
   override for .rail-right, matching CCF's own #tab-tab6 .rail-right
   pattern for a one-child panel instead of the usual 2-row split. */
/* Lets you reset all Tab 1 selections back to defaults ("Optimised Route")
   without a page refresh, or lift the compliance-no click restriction
   ("All Cases"). A real flex item (not absolutely positioned) so it gets
   its own centered slot in the row, matching the other selector columns. */
.selection-mode-toggle {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: center;
    align-self: center;
    gap: 10px;
    z-index: 3;
    flex-shrink: 0;
}

.selection-mode-btn {
    position: relative;
    width: 250px;
    min-height: 140px;
    border-radius: 18px;
    border: 2px solid var(--panel-border);
    background: #fff;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 15px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    line-height: 1.3;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 12px 18px 24px;
    cursor: pointer;
    white-space: normal;
    box-shadow: 0 2px 6px rgba(34, 48, 67, 0.12);
    transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease, transform 0.12s ease, box-shadow 0.18s ease;
}

/* "Click to reset" caption — small, pinned to the very bottom of the
   button regardless of how many lines the main label wraps to. */
.selection-mode-btn-sub {
    position: absolute;
    bottom: 8px;
    left: 0;
    right: 0;
    font-size: 13px;
    font-weight: 600;
    text-transform: none;
    letter-spacing: 0.2px;
    opacity: 0.75;
}

/* Hover card on the "Find Compliant Case" button, reminding the user a zone
   needs to be selected for the compliance highlighting to do anything. */
.selection-mode-tooltip {
    position: absolute;
    top: calc(100% + 12px);
    left: 50%;
    transform: translateX(-50%);
    background: var(--color-navy-text);
    color: #fff;
    font-size: 13px;
    font-weight: 700;
    text-transform: none;
    letter-spacing: normal;
    white-space: nowrap;
    padding: 8px 16px;
    border-radius: 8px;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.25);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s ease;
    z-index: 10;
}

.selection-mode-tooltip::after {
    content: '';
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent;
    border-bottom-color: var(--color-navy-text);
}

.selection-mode-btn:hover .selection-mode-tooltip {
    opacity: 1;
}

.selection-mode-btn:hover {
    transform: scale(1.02);
    border-color: var(--color-accent-blue-dark);
    box-shadow: 0 4px 10px rgba(34, 48, 67, 0.18);
}

.selection-mode-btn.active {
    background: var(--color-accent-blue-dark);
    border-color: var(--color-accent-blue-dark);
    color: #fff;
    box-shadow: 0 4px 12px rgba(48, 86, 116, 0.35);
}

/* Highlights while "Find Compliant Case" is the active mode — the
   button itself, plus every selector's currently-selected option pill. */
.selection-mode-btn--optimized.active {
    background: var(--mode-optimized-accent);
    border-color: var(--mode-optimized-accent);
    color: #fff;
}

.rail-panel[data-selection-mode="optimized"] .glass-option.active,
.rail-panel[data-selection-mode="optimized"] .fabric-option.active,
.rail-panel[data-selection-mode="optimized"] .winwidth-option.active,
.rail-panel[data-selection-mode="optimized"] .zonewidth-option.active,
.rail-panel[data-selection-mode="optimized"] .elementdepth-option.active,
.rail-panel[data-selection-mode="optimized"] .overhang-incl-option.active,
.rail-panel[data-selection-mode="optimized"] .sidefinrot-option.active,
.rail-panel[data-selection-mode="optimized"] .frit-option.active {
    background: var(--mode-optimized-accent);
    border-color: var(--mode-optimized-accent);
    box-shadow: 0 3px 8px rgba(102, 153, 204, 0.35);
}

.glass-selector-wrapper {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    min-width: 80px;
    z-index: 2;
}

.opaque-panel-width {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-muted);
    white-space: nowrap;
    text-align: center;
}

.glass-label-text {
    min-height: clamp(16px, 2.4vh, 26px);
    font-size: clamp(9px, 0.85vw, 16px);
    font-weight: 700;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    line-height: 1.3;
    text-align: center;
    white-space: nowrap;
}

/* Legacy horizontal top selector bar — no tab uses this markup any more
   (tabs 1-4 moved to the .rail-* layout, whose own label chip lives with
   .glass-rail .glass-label-text). Kept only so the remaining
   .glass-selector-section rules stay self-consistent. */
.glass-selector-section .glass-label-text {
    display: inline-block;
    font-weight: 800;
    color: var(--color-navy-text);
    background: rgba(255, 255, 255, 0.85);
    padding: 3px 10px;
    border-radius: 5px;
    box-shadow: 0 1px 3px rgba(34, 48, 67, 0.12);
}

.glass-label-unit {
    font-size: 0.65em;
    font-weight: 600;
    text-transform: none;
    letter-spacing: 0;
}

.glass-selector-container {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
}

.selector-network {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 1;
}

.selector-network svg {
    width: 100%;
    height: 100%;
    display: block;
}

.glass-circle {
    width: clamp(60px, 5.2vw, 100px);
    height: clamp(60px, 5.2vw, 100px);
    border-radius: 50%;
    /* Opaque — text/value images stay fully legible regardless of the
       tinted glass + frit dot texture on the section behind it. */
    background: #ffffff;
    border: 1.5px solid rgba(255, 255, 255, 0.9);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    box-shadow: 0 4px 12px rgba(34, 48, 67, 0.14);
    cursor: pointer;
    z-index: 5;
    font-size: clamp(14px, 1.25vw, 24px);
    font-weight: 800;
    color: var(--color-navy-text);
    flex-shrink: 0;
}

.glass-circle:hover {
    transform: scale(1.04);
}

.glass-popup {
    position: static;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    background: var(--glass-popup-bg);
    border: 1px solid rgba(34, 48, 67, 0.18);
    border-radius: 12px;
    padding: 4px;
    z-index: 2;
}

.glass-option,
.fabric-option,
.winwidth-option,
.zonewidth-option,
.elementdepth-option,
.overhang-incl-option,
.sidefinrot-option,
.shadingtype-option,
.frit-option,
.psg-option {
    min-width: 40px;
    padding: 5px 12px;
    text-align: center;
    font-size: 16px;
    font-weight: 600;
    color: var(--text-muted);
    cursor: pointer;
    transition: background 0.15s ease;
    border: none;
    background: transparent;
    border-radius: 8px;
    box-shadow: none;
    position: relative;
    z-index: 2;
}

.glass-option:hover,
.fabric-option:hover,
.winwidth-option:hover,
.zonewidth-option:hover,
.elementdepth-option:hover,
.overhang-incl-option:hover,
.sidefinrot-option:hover,
.shadingtype-option:hover,
.frit-option:hover,
.psg-option:hover {
    background: rgba(255, 255, 255, 0.65);
    color: var(--color-navy-text);
}

.glass-option.active,
.fabric-option.active,
.winwidth-option.active,
.zonewidth-option.active,
.elementdepth-option.active,
.overhang-incl-option.active,
.sidefinrot-option.active,
.shadingtype-option.active,
.frit-option.active,
.psg-option.active {
    background: var(--color-accent-blue-dark);
    color: #fff;
    font-weight: 700;
    border: 1.5px solid var(--color-accent-blue-dark);
    box-shadow: 0 3px 8px rgba(49, 87, 117, 0.35);
}

/* "Keycap" active-pill treatment (mockup option 2, approved) — a solid
   darker bottom "lip" plus a bigger drop shadow, lifted slightly with
   translateY, reading as a pressed 3D key. Applied to every tab's rail
   selector options (DGU/Frit/Window Width/Element Depth/Side Fin Rotation/
   Automated Blinds), not just Tab 1. */
#railOnlyGlass .glass-option.active,
#railOnlyGlass .frit-option.active,
#railOnlyGlass .winwidth-option.active,
#railFe .glass-option.active,
#railFe .frit-option.active,
#railFe .winwidth-option.active,
#railFe .elementdepth-option.active,
#railFe .sidefinrot-option.active,
#railFe .shadingtype-option.active,
#railAb .glass-option.active,
#railAb .frit-option.active,
#railAb .winwidth-option.active,
#railAb .fabric-option.active,
#railFeb .glass-option.active,
#railFeb .frit-option.active,
#railFeb .winwidth-option.active,
#railFeb .elementdepth-option.active,
#railFeb .sidefinrot-option.active,
#railFeb .fabric-option.active,
#railFeb .shadingtype-option.active,
#railCcf .ccf-option.active {
    box-shadow: 0 3px 0 #1c3346, 0 5px 8px rgba(34, 48, 67, 0.4);
    transform: translateY(-1px);
}

/* Compliance wizard: highlights which options in the *next* button still
   leave a path to PSG <= limit, given everything picked so far. Pulses to
   draw the eye to what's still selectable, instead of a static outline. */
@keyframes complianceOkPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(102, 153, 204, 0.5); }
    50%      { box-shadow: 0 0 10px 5px rgba(102, 153, 204, 0.5); }
}

.glass-option.compliance-ok,
.fabric-option.compliance-ok,
.frit-option.compliance-ok,
.winwidth-option.compliance-ok,
.zonewidth-option.compliance-ok,
.elementdepth-option.compliance-ok,
.overhang-incl-option.compliance-ok,
.sidefinrot-option.compliance-ok {
    border: 3px dotted var(--mode-optimized-accent);
    animation: complianceOkPulse 1.4s ease-in-out infinite;
}

/* "Find Compliant Case" step guidance: pulses a glow around whichever
   control the user should interact with next — the 3D model panel (select
   a zone) first, then PSG Limit / Flexible Limit (pick both) once a zone
   is selected. Reused on both the rectangular viewer panel and the pill-
   shaped segmented controls; box-shadow follows each element's own radius. */
@keyframes guidanceGlowPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(102, 153, 204, 0.55); }
    50%      { box-shadow: 0 0 22px 8px rgba(102, 153, 204, 0.75); }
}

.guidance-glow {
    border: 3px solid var(--mode-optimized-accent) !important;
    animation: guidanceGlowPulse 1.6s ease-in-out infinite;
}

/* Shown when the wizard's next dimension has zero compliance-ok options —
   i.e. no completion of the remaining free dimensions can reach PSG <=
   limit, so every option in that step is compliance-no. See
   updateComplianceHighlights() in main.js. */
.wizard-no-compliance-msg {
    text-align: center;
    font-size: 14px;
    font-weight: 700;
    color: #8a0d16;
    background: rgba(226, 184, 186, 0.35);
    border: 1px solid #c98a8e;
    border-radius: 8px;
    padding: 8px 10px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.glass-option.compliance-no,
.fabric-option.compliance-no,
.frit-option.compliance-no,
.winwidth-option.compliance-no,
.zonewidth-option.compliance-no,
.elementdepth-option.compliance-no,
.overhang-incl-option.compliance-no,
.sidefinrot-option.compliance-no {
    opacity: 0.4;
}

/* Overhang/Side Fin Rotation options other than 0° — disabled whenever
   Element Depth is 0 (no overhang/fin to rotate). Used across Tab 1, 2 and
   3's rotation selectors. */
.overhang-incl-option.depth-locked,
.sidefinrot-option.depth-locked {
    opacity: 0.4;
    pointer-events: none;
    cursor: not-allowed;
}


.main-layout {
    display: grid;
    /* 3D viewer (click a window to select its zone) | performance panel |
       daylight/thermal column (titles only, no images/data for now). */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr) minmax(0, 0.9fr);
    gap: clamp(8px, 0.9vw, 18px);
    width: 100%;
    margin: 0 auto;
    padding: 0 clamp(10px, 8vw, 200px);
    min-height: 0;
    overflow: hidden;
    flex: 1;
}

.viewer-container,
.performance-panel,
.result-card,
.future-panel,
.facade-sketch-panel {
    border: 1px solid var(--panel-border);
    border-radius: 12px;
    background: var(--panel-bg);
    box-shadow: 0 6px 20px var(--panel-shadow);
}

/* Wraps the rail-panel + the Facade Sketch panel below it in the same grid
   column, so .rail-layout doesn't need a second row just for tab 1. The
   rail-panel keeps its own scroll/overflow behavior via flex:1; the sketch
   panel is a fixed-height card underneath it, view-only — see
   renderFacadeSketch()/buildFacadeSketch() in main.js. */
.rail-col {
    display: flex;
    flex-direction: column;
    gap: clamp(8px, 0.9vw, 18px);
    min-height: 0;
    height: 100%;
}

.rail-col .rail-panel {
    flex: 1;
    min-height: 0;
}

.facade-sketch-panel {
    flex: 0 0 auto;
    padding: 10px 12px 12px;
}

/* Tab 2's "Find Compliant Case" button moved out of the Design Variables
   panel (freed up the space it used to reserve there via #railFe's
   padding-bottom, below) into its own small panel next to Facade
   Articulation instead. */
.rail-bottom-row {
    display: flex;
    flex-direction: row;
    gap: clamp(8px, 0.9vw, 18px);
    flex: 0 0 auto;
}

.rail-bottom-row .facade-sketch-panel {
    flex: 1 1 auto;
    min-width: 0;
}

.compliant-case-panel {
    flex: 0 0 clamp(120px, 12vw, 160px);
    /* No padding of its own — the button fills the panel completely (same
       border-radius as the panel, below), so the whole card is clickable
       rather than just a smaller button floating inside it. Deliberately
       NOT overflow:hidden — the active state's "keycap" lift/shadow (see
       the base .compliant-case-btn.active rule) needs to spill slightly
       past the edge, and clipping it there would cut that effect off. */
    padding: 0;
}

/* Base .compliant-case-btn (further down) pins itself to its parent's
   bottom edge with position:absolute and has its own border — built for
   sitting inside the much taller Design Variables panel. Inside this small
   dedicated panel it fills the panel edge-to-edge instead (matching corner
   radius, so it reads as one card rather than a button floating in a
   second box), so clicking anywhere on the card counts. */
.compliant-case-panel .compliant-case-btn {
    position: static;
    width: 100%;
    height: 100%;
    left: auto;
    right: auto;
    bottom: auto;
    border: none;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
}

.facade-sketch-header {
    font-size: 18px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--color-navy-text);
    margin-bottom: 6px;
    text-align: center;
}

.facade-sketch-stage {
    height: 230px;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}

.facade-sketch-stage svg {
    width: 94%;
    height: 94%;
}

/* "Compliant Case" toggle — enters/exits the guided wizard (see
   resetToOptimizedRoute()/switchToAllCasesMode() in main.js). Active state
   mirrors the app's other "currently on" controls (solid navy fill). */
.compliant-case-btn {
    /* Direct child of .rail-panel (sibling to .rail-inner), pinned to the
       panel's own bottom edge via absolute positioning (.rail-panel has
       position:relative) instead of sitting in the normal flex flow — a
       margin-top:auto approach was tried first, but having 2 flex items in
       a justify-content:center column made the *other* item (.rail-inner,
       every selector row) snap to the top to make room, instead of staying
       centered where it always was. Absolute positioning takes this out of
       that flex flow entirely, so .rail-inner goes back to being the only
       flex item and stays centered exactly as before. */
    position: absolute;
    left: 12px;
    right: 12px;
    bottom: 12px;
    padding: 12px;
    border-radius: 10px;
    border: 1px solid var(--color-accent-blue-dark);
    background: var(--panel-bg);
    color: var(--color-accent-blue-dark);
    font-family: inherit;
    font-size: 15px;
    font-weight: 700;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}

.compliant-case-btn:hover {
    background: rgba(122, 174, 200, 0.12);
}

.compliant-case-btn.active {
    background: var(--color-accent-blue-dark);
    color: #fff;
    /* Same "Keycap" treatment as the selected rail pills above. */
    box-shadow: 0 3px 0 #1c3346, 0 5px 8px rgba(34, 48, 67, 0.4);
    transform: translateY(-1px);
}

.viewer-column {
    min-height: 0;
    display: grid;
    grid-template-rows: minmax(0, 1fr);
    gap: 10px;
}

.viewer-container {
    min-height: 0;
    overflow: hidden;
    background: var(--viewer-bg);
    position: relative;
}

.viewer-bottom-panel {
    border: 1px solid #dfe6ee;
    border-radius: 12px;
    background: #fbfcfd;
    box-shadow: 0 6px 20px rgba(34,48,67,0.28);
    min-height: 0;
    overflow: hidden;
}

#canvas3d,
#canvas3dC3pct {
    width: 100%;
    height: 100%;
    display: block;
    outline: none;
}

.analysis-column {
    min-height: 0;
    display: grid;
    grid-template-rows: minmax(0, 1fr) minmax(0, 0.67fr);
    gap: 10px;
}

.daylight-thermal-column {
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.daylight-thermal-column .result-card {
    flex: 1;
    min-height: 0;
}

.performance-panel {
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    overflow: hidden;
}

.performance-top {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr) minmax(0, 0.8fr);
    grid-template-rows: auto;
    gap: 10px;
    min-height: 0;
    align-items: start;
    flex: 1;
}

/* Tab 1's Solar Gains row — Solar Altitude scatter, its rose chart, and the
   hourly exceedance bar chart, evenly spaced side by side. The Solar
   Azimuth scatter + azimuth rose (former top row of a 2x2
   .solar-charts-grid) were removed as redundant with these, so this is now
   a flat 3-up row rather than a 2-column grid. */
.solar-panel-row {
    display: flex;
    gap: 10px;
    min-height: 0;
    flex: 1;
    padding-top: 8px;
}

.solar-panel-row > .chart-panel {
    flex: 1 1 0;
    min-width: 0;
}

/* The rose is a semicircle, not a full rectangle, so it doesn't need as
   much width as the scatter/bar panels either side of it to read clearly. */
.solar-panel-row > .chart-panel.rose-panel {
    flex: 0.7 1 0;
}

/* .solar-charts-grid (2x2 scatter+rose grid) is still used by Tabs 2/4 —
   left as-is, just no longer referenced by Tab 1's markup. */
.solar-charts-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
    grid-template-rows: 1fr 1fr;
    gap: 16px 8px;
    min-height: 0;
    align-items: stretch;
    flex: 1;
    padding-top: 8px;
}

.exceedance-bar-panel {
    min-width: 0;
    display: flex;
    flex-direction: column;
    /* Transparent (not none) so the reserved space/padding stays identical
       whether or not it's visible — only the color changes, no layout
       shift when a zone gets picked. */
    border-left: 1px solid transparent;
    padding-left: 10px;
}

/* Separates it from the rose chart to its left, matching how the pie/bar
   split reads on Tab 3 — only shown once a zone is actually selected and
   there's a real chart to divide from (see showWindowData/hidePanel in
   main.js, which toggle this class). */
.exceedance-bar-panel.zone-selected {
    border-left-color: #c3ccd6;
}

#exceedanceBarFe,
#exceedanceBarFeb {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.exceedance-bar-title {
    flex-shrink: 0;
    text-align: center;
    font-size: 17px;
    font-weight: 700;
    color: var(--color-navy-text);
    margin-top: 34px;
    margin-bottom: 0;
}

#exceedanceBarFe svg,
#exceedanceBarFeb svg {
    display: block;
    width: 100%;
    /* flex:1 (not height:100%) — the title above it is a sibling flex item
       now, so the svg needs to claim whatever's left rather than the
       container's full height, which would overlap/overflow past the title. */
    flex: 1;
    min-height: 0;
}

.panel-content {
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
    justify-content: center;
    align-items: center;
    height: 100%;
    align-self: stretch;
}

#windowInfo {
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

#solarRoseChart {
    width: 100%;
    flex-shrink: 0;
}

#solarRoseChart svg {
    width: 100%;
    height: auto;
    overflow: visible;
    display: block;
}

.info-row {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 14px 0;
}

.info-label {
    font-size: 16px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-subtle);
    text-align: center;
}

.info-value {
    display: inline-block;
    font-size: 16px;
    font-weight: 700;
    color: #223043;
    padding: 2px 8px;
}

.info-value--safe {
    background: var(--psg-safe);
    border-color: var(--psg-safe-border);
    color: #fff;
}

.info-value--warning {
    background: var(--psg-warning);
    border-color: var(--psg-warning-border);
    color: #fff;
}

.info-value--danger {
    background: var(--psg-danger);
    border-color: var(--psg-danger-border);
    color: #fff;
}

/* Daylight/Thermal Comfort's "unavailable" messages (e.g. "Daylight results
   not available", "Case does not exist") — centered in the remaining space
   below the title, and a darker color than the base .hint below since
   these read more like a real state than a subtle placeholder note. */
.result-card .hint {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted, #4a5a6e);
}

.hint {
    color: #95a5a6;
    font-size: 17px;
    text-align: center;
    padding: 18px 0;
    width: 100%;
}

.result-card {
    position: relative;
    padding: 8px;
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.chart-panel {
    padding: 8px;
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.chart-title {
    font-size: 16px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--color-navy-text);
    margin-bottom: 6px;
}

/* Shown in the Daylight/Thermal Comfort cards before a zone is selected —
   ported over from the AH-dashboard sibling project, which still had this
   (it got dropped from this project's markup during the tab-unification
   refactor, leaving only dead JS references to these ids). Toggled by
   applyZoneResultsVisibility() (tab 1) / showWindowData()+hidePanel()
   (tabs 2-4) — hidden once a zone is selected and real content renders. */
.placeholder-result-img {
    display: block;
    max-height: 75%;
    max-width: 75%;
    object-fit: contain;
    margin: auto;
    opacity: 0.85;
}

.result-title {
    font-size: 20px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--color-navy-text);
    margin-bottom: 6px;
    text-align: center;
}

/* Tab 2's Daylight thumbnail specifically — matches the Thermal Comfort
   placeholder's size (#thermalPlaceholderImgFe/Feb below) rather than the
   shared .placeholder-result-img cap (75%), without affecting Tab 1's
   thumbnail or either tab's panel/column layout. Explicit width/height
   (not max-*) is required to actually grow it — max-width/max-height alone
   only ever shrinks an <img>, never grows it past its natural pixel size,
   which is why raising the cap on its own had no visible effect. */
#daylightPlaceholderImgFeb {
    width: 65%;
    height: 65%;
}

/* Tab 2's Daylight card only — this tab defaults to the 50 W/m² PSG limit
   (see tabStates['glass-fixed-blinds']/wizardFeb.resetValues), so this
   flags that context on the card itself rather than leaving it implicit. */
.result-title-note {
    display: block;
    font-size: 11px;
    font-weight: 600;
    text-transform: none;
    letter-spacing: normal;
    color: var(--text-muted, #4a5a6e);
    margin-top: 2px;
}

/* Both share the same treatment now — #altitudeChart used to be left out,
   which (combined with the axis-title font bump below) was why the two
   charts rendered at different sizes and the altitude one's rotated
   y-axis title clipped off on the left. Attribute selectors also cover the
   Fe/Ab/Feb variants (scatterChartFe, altitudeChartAb, etc.) on tabs 2-4 —
   these were missing this constraint entirely, which is why their charts
   rendered oversized/unconstrained compared to tab 1's. */
/* PSG limit line (the red dashed line in the scatter charts) — soft drop
   shadow so the thicker line reads as sitting slightly above the points
   rather than flat/flush with the chart. .limit-line is the main Solar
   Gains scatter (horizontal line); .alt-limit-line is the Solar Altitude
   scatter underneath it (vertical line) — same treatment, both charts,
   every tab. */
.limit-line line,
.alt-limit-line line {
    filter: drop-shadow(0 1px 2px rgba(200, 30, 30, 0.5));
}

#scatterChart,
#altitudeChart,
[id^="scatterChart"],
[id^="altitudeChart"] {
    flex: 1;
    min-height: 0;
    display: flex;
    align-items: center;
    /* flex-start, not center — centering each chart independently means
       any tiny width difference between the two containers shifts their
       y-axes to different absolute positions. Left-aligning both pins
       margin.left to the same spot on every row, so the axes always line
       up regardless of container width. */
    justify-content: flex-start;
    margin-top: -20px;
}

/* Reduced from 85px so the chart (unchanged size) sits higher in its panel
   — its bottom (the x-axis title) was getting clipped by this panel's
   overflow:hidden before. */
.solar-charts-grid .chart-panel:nth-child(1) {
    padding-top: 25px;
}

/* Azimuth row (scatterChart + roseGainChart) on top, Altitude row
   (altitudeChart + altRoseChart) below — East facade convention. Reordered
   visually via `order` rather than moving the DOM nodes, so the padding
   fix above (tied to nth-child(1), the altitude chart) still applies to
   the right panel regardless of where it's displayed. */
.solar-charts-grid .chart-panel:nth-child(1) { order: 3; }
.solar-charts-grid .chart-panel:nth-child(2) { order: 4; }
.solar-charts-grid .chart-panel:nth-child(3) { order: 1; }
.solar-charts-grid .chart-panel:nth-child(4) { order: 2; }

.scatter-seg-wrap {
    display: flex;
    justify-content: center;
    margin-top: 5px;
}

/* Three stacked rows — PSG Limit, then Fixed Limit, then Flexible Limit —
   instead of the old side-by-side layout. Each .filter-group is already a
   column (label above control), so this just stacks the groups themselves. */
.filter-row {
    display: flex;
    flex-direction: column;
    gap: 14px;
    justify-content: center;
    align-items: center;
    padding: 4px 0 2px;
    width: 100%;
}

.filter-group {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    border: none;
    border-radius: 0;
    padding: 6px 14px 8px;
    background: transparent;
    align-self: center;
    width: fit-content;
}

.filter-group-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-label);
}

/* Info icon + hover/focus popover, same mechanics as .selection-mode-tooltip
   (opacity/pointer-events transition, arrow via ::after) so it matches the
   rest of the app's hover-card styling. */
.info-icon {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 15px;
    height: 15px;
    border-radius: 50%;
    background: var(--color-accent-blue);
    color: #fff;
    font-size: 10px;
    font-weight: 800;
    font-style: italic;
    text-transform: none;
    letter-spacing: normal;
    cursor: help;
    user-select: none;
}

.info-popover {
    position: absolute;
    top: calc(100% + 10px);
    left: 50%;
    transform: translate(-50%, -4px);
    width: 240px;
    background: var(--color-navy-text);
    color: #fff;
    font-size: 12px;
    font-weight: 500;
    text-transform: none;
    letter-spacing: normal;
    line-height: 1.5;
    text-align: left;
    white-space: normal;
    padding: 10px 12px;
    border-radius: 8px;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.25);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s ease, transform 0.15s ease;
    z-index: 20;
}

.info-popover::after {
    content: '';
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent;
    border-bottom-color: var(--color-navy-text);
}

.info-icon:hover .info-popover,
.info-icon:focus .info-popover,
.info-icon:focus-visible .info-popover {
    opacity: 1;
    pointer-events: auto;
    transform: translate(-50%, 0);
}

.scatter-seg {
    position: relative;
    display: inline-flex;
    background: var(--seg-track-bg);
    border-radius: 999px;
    padding: 2px;
    gap: 0;
}

.seg-thumb {
    position: absolute;
    top: 2px;
    left: 2px;
    height: calc(100% - 4px);
    background: var(--seg-thumb-bg);
    border-radius: 999px;
    transition: left 0.22s ease, width 0.22s ease;
    pointer-events: none;
    z-index: 0;
}

.seg-opt {
    position: relative;
    z-index: 1;
    padding: 3px 10px;
    font-size: 13px;
    font-weight: 600;
    border: none;
    background: transparent;
    color: var(--color-navy-text);
    cursor: pointer;
    border-radius: 999px;
    white-space: nowrap;
    transition: color 0.18s ease;
    user-select: none;
}

/* Tab 1's Solar Gains header: PSG Limit + Flexible Limit toggles, sized up
   from the base .seg-opt so they're easier to read/click. */
#psgFilterRow .filter-group-label {
    font-size: 19px;
}

#psgFilterRow .seg-opt {
    font-size: 16px;
    padding: 6px 16px;
}

/* PSG Limit slider — a true draggable handle (native <input type="range">)
   snapping between 8 uneven-step values (40, then +5 up to 80). Position is
   index-based (0-7 into PSG_LIMIT_VALUES in main.js) since the gaps aren't
   uniform, so a plain numeric range/step wouldn't line up with the values. */
.psg-slider {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    box-sizing: border-box;
    width: 150px;
    padding: 2px 4px 0;
}

/* Stacked-row layout gives the PSG Limit slider its own full row instead of
   squeezing it next to Fixed/Flexible Limit, so it can run wider. */
.filter-row .psg-slider {
    width: min(420px, 90vw);
}

/* Tab 1's PSG Limit slider specifically — bigger track/dots/ticks and
   label, since it has the whole row to itself and is the primary control
   up top. */
#psgFilterRow .psg-slider {
    width: min(560px, 92vw);
}

.psg-slider-input {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    height: 4px;
    margin: 10px 0 2px;
    background: var(--seg-track-bg);
    border-radius: 999px;
    outline: none;
    cursor: pointer;
}

.psg-slider-input::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--seg-thumb-bg);
    border: 2px solid #fff;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
    cursor: grab;
}

.psg-slider-input::-webkit-slider-thumb:active {
    cursor: grabbing;
}

.psg-slider-input::-moz-range-thumb {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--seg-thumb-bg);
    border: 2px solid #fff;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
    cursor: grab;
}

.psg-slider-input::-moz-range-track {
    height: 4px;
    background: var(--seg-track-bg);
    border-radius: 999px;
}

.psg-slider-ticks {
    display: flex;
    justify-content: space-between;
    padding: 0 1px;
}

.psg-slider-tick {
    font-size: 10px;
    font-weight: 600;
    color: var(--text-muted);
    user-select: none;
    transition: color 0.15s ease, font-weight 0.15s ease;
}

.psg-slider-tick.active {
    color: var(--color-accent-blue-dark);
    font-weight: 800;
}

/* Stepped-dot PSG Limit slider, see frontend/stepped-slider-spec.md
   (colors mapped to the app's existing blue theme instead of the spec's
   literal amber palette). Originally Tab 1 (#psgSeg) only — now scoped to
   the shared .psg-stepped class so all 4 tabs' sliders use it, as long as
   their markup includes the track-wrap/line-fill/dots structure (see
   index.html) and the .psg-slider container also carries .psg-stepped. */
/* Ticks used to rely on flex space-between, which lines up item *edges*
   (first item's left edge to the container's left edge, etc.), not their
   text centers — so with each label a different width, none of them sat
   centered above its dot below (the dots are absolutely positioned at
   exact percentages via the nth-child rules further down). Switching to
   the same absolute-percentage positioning as the dots guarantees every
   label's center lines up with its dot's center exactly. */
.psg-stepped .psg-slider-ticks {
    position: relative;
    display: block;
    height: 20px;
    padding: 0;
}

.psg-stepped .psg-slider-tick {
    position: absolute;
    top: 0;
    transform: translateX(-50%);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    font-size: 16px;
    opacity: 0.75;
    /* Purely a read-only label (JS only ever toggles its .active class,
       never listens for clicks on it — see syncPsgSliderTicks in main.js).
       Needs to stay click-through: giving .psg-slider-ticks a higher
       z-index than .psg-slider-track-wrap (below, so the BCO backdrop
       paints behind the numbers instead of over them) means the tick text
       now sits stacking-wise above the invisible range input too, in the
       area right around 40/50 where the two happen to sit close together —
       without this, clicks/drags landing on the tick text there got
       swallowed instead of reaching the actual slider input underneath it. */
    pointer-events: none;
}

.psg-stepped .psg-slider-tick.active {
    opacity: 1;
    color: #000;
    font-weight: 700;
}

/* 5 stops, 10 W/m² apart (40/50/60/70/80) — evenly spaced 25% apart. */
.psg-stepped .psg-slider-tick:nth-child(1) { left: 0%; }
.psg-stepped .psg-slider-tick:nth-child(2) { left: 25%; }
.psg-stepped .psg-slider-tick:nth-child(3) { left: 50%; }
.psg-stepped .psg-slider-tick:nth-child(4) { left: 75%; }
.psg-stepped .psg-slider-tick:nth-child(5) { left: 100%; }

.psg-stepped .psg-slider-track-wrap {
    position: relative;
    height: 36px;
    margin: 10px 0 2px;
}

.psg-stepped .psg-slider-track-wrap::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    height: 1px;
    background: var(--border-input);
    transform: translateY(-50%);
}

.psg-stepped .psg-slider-line-fill {
    position: absolute;
    top: 50%;
    left: 0;
    width: 0%;
    height: 1px;
    background: var(--color-accent-blue-dark);
    transform: translateY(-50%);
    transition: width 150ms ease;
}

.psg-stepped .psg-slider-dots {
    position: relative;
    height: 100%;
}

.psg-stepped .psg-slider-dot {
    position: absolute;
    top: 50%;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--panel-bg);
    border: 2px solid var(--border-input);
    transform: translate(-50%, -50%);
    transition: width 150ms ease, height 150ms ease, background 150ms ease, border-color 150ms ease;
}

.psg-stepped .psg-slider-dot.passed {
    background: var(--color-accent-blue-dark);
    border-color: var(--color-accent-blue-dark);
}

.psg-stepped .psg-slider-dot.current {
    width: 28px;
    height: 28px;
    /* Same "Keycap" treatment as the selected rail pills/Fixed-Flexible
       Limit pills/Compliant Case button — solid navy fill (was a hollow
       ring) with a darker bottom lip + drop shadow, lifted slightly. The
       base .psg-slider-dot's translate(-50%,-50%) centers the dot on its
       position — has to stay combined in one transform, not overridden. */
    background: var(--color-accent-blue-dark);
    border: 3.5px solid var(--color-accent-blue-dark);
    box-shadow: 0 3px 0 #1c3346, 0 5px 8px rgba(34, 48, 67, 0.4);
    transform: translate(-50%, calc(-50% - 1px));
}

.psg-stepped .psg-slider-dot:nth-child(1) { left: 0%; }
.psg-stepped .psg-slider-dot:nth-child(2) { left: 25%; }
.psg-stepped .psg-slider-dot:nth-child(3) { left: 50%; }
.psg-stepped .psg-slider-dot:nth-child(4) { left: 75%; }
.psg-stepped .psg-slider-dot:nth-child(5) { left: 100%; }

.psg-stepped .psg-slider-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    background: transparent;
    opacity: 0;
    z-index: 2;
}

/* BCO-recommended highlight behind the 40/50 PSG Limit stops — a rectangular
   backdrop panel spanning both ticks (see .psg-slider-ticks z-index below)
   and dots, plus a small tag underneath. Deliberately doesn't recolor the
   40/50 tick text or dots themselves (mockup-approved) — only the panel
   marks them, so 40/50 still look/behave like every other stop. */
.psg-stepped .psg-slider-ticks {
    z-index: 2;
}

.psg-stepped .psg-slider-track-wrap {
    z-index: 1;
}

.psg-bco-backdrop {
    position: absolute;
    left: -24px;
    /* Sized to just enclose the "40"/"50" tick labels above and the slider
       dots below (labels start ~30px above the track-wrap's top, dots
       bottom out ~26px below it — see .psg-stepped .psg-slider-ticks/-dot),
       plus a few px of padding on each side. */
    top: -34px;
    width: calc(25% + 48px);
    height: 84px;
    background: #f4f9f6;
    border: 1px dashed #2f7d4a;
    border-radius: 3px;
    z-index: 0;
    pointer-events: none;
}

.psg-bco-tag {
    position: absolute;
    left: 50%;
    top: calc(100% + 10px);
    transform: translateX(-50%);
    background: #2f7d4a;
    color: #fff;
    font-size: 14px;
    font-weight: 800;
    letter-spacing: 0.3px;
    padding: 4px 11px;
    border-radius: 4px;
    white-space: nowrap;
    z-index: 2;
    pointer-events: none;
}

.seg-opt.active {
    color: #fff;
}

/* #altitudeChart (and its Fe/Ab/Feb equivalents on tabs 2-4) never had
   this — without it, that SVG wasn't constrained to its container at all
   (rendered at some browser-default/intrinsic size instead), which is why
   it looked huge next to the scatter chart and its bottom axis title ran
   off the visible area. Attribute-selectors cover every tab's chart id
   (scatterChart, scatterChartFe, altitudeChart, altitudeChartAb, etc.) in
   one rule instead of listing each one out. */
#scatterChart svg,
[id^="scatterChart"] svg,
[id^="altitudeChart"] svg {
    width: 100%;
    height: 100%;
    overflow: visible;
}

#barChart {
    flex: 1;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

#barChart svg {
    width: 100%;
    height: 100%;
    overflow: visible;
}

.performance-bottom {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
    min-height: 0;
}

.result-meta {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-meta);
    margin-bottom: 6px;
}

.result-image-wrap {
    position: relative;
    flex: 1;
    min-height: 0;
    border: 1px solid var(--result-image-border);
    border-radius: 12px;
    background: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    padding: 8px;
}

.result-image-wrap img {
    max-width: 75%;
    max-height: 75%;
    width: auto;
    height: auto;
    object-fit: contain;
    display: block;
    margin: auto auto auto 0;
}

.result-photo {
    width: 100%;
    /* Was flex:1 (grows to fill all remaining vertical space in the card) —
       object-fit:contain then letterboxes the actual image inside that
       oversized box, leaving visible blank space between the image content
       and the sDA/Thermal Comfort text below it. Capping the box height
       instead of letting it grow keeps the image close to its natural
       size, so the text sits right under the actual picture. */
    flex: 0 1 auto;
    max-height: 82%;
    min-height: 0;
    object-fit: contain;
    object-position: center;
    display: block;
}

.placeholder-result-img {
    display: block;
    max-height: 75%;
    max-width: 75%;
    object-fit: contain;
    margin: auto;
    opacity: 0.85;
}

/* Thermal Comfort's placeholder (ThermalComfort.png) is a small source image
   (295x189) — .placeholder-result-img's max-height/max-width alone never
   actually constrained it (the browser rendered it at its small natural
   size, well under either cap, so raising the cap had no visible effect).
   Explicit width/height forces it to actually scale up to fill that box;
   object-fit:contain (inherited from the base rule) keeps it proportional. */
#thermalPlaceholderImgFe,
#thermalPlaceholderImgFeb {
    width: 65%;
    height: 65%;
}

/* Was an absolutely-positioned box floating over the image's bottom-right
   corner — capped the image at 80% width to keep clear of it, and covered
   part of whatever it did overlap. Now a normal flex child sitting below
   the image (result-card is display:flex; flex-direction:column, and
   .result-title/.result-photo/.result-legend-wrap are its only children
   in that DOM order), so the image can run full width/height and the
   metric text just reads as a bar underneath it. */
.result-legend-wrap {
    position: relative;
    width: 100%;
    flex-shrink: 0;
    pointer-events: none;
    /* Unconditionally hidden — !important so this wins regardless of init
       timing/ordering (a plain, non-important default relied on JS running
       showMetricsPlaceholder()/renderMetricCard() at exactly the right
       moment to set an inline style, which wasn't reliably happening and
       left the legend key visible over the placeholder illustration). Only
       .result-card.has-result overrides it, and only renderMetricCard()
       adds that class, when a real result image is actually rendering. */
    display: none !important;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    /* Was picking up the card's own off-white --panel-bg (#fbfcfd), which
       read as light grey against the page — pinned to pure white so the
       sDA/Thermal Comfort text sits on a clean white strip. */
    background: #fff;
}

.result-card.has-result .result-legend-wrap {
    display: flex !important;
}

.result-legend-img {
    /* Centered — the left-nudge this used to have only made sense when the
       sDA/floor-area text sat below it; now that text sits above (see
       renderMetricCard in main.js), the legend is the card's last/bottom
       element on its own and reads better centered. */
    width: 62%;
    max-width: 220px;
    height: auto;
    object-fit: contain;
    display: block;
    align-self: center;
    margin: 0 auto;
}

.result-metric-text {
    text-align: center;
    /* No longer nested inside .result-legend-wrap (which had its own
       gap:4px between children) — now a standalone sibling sitting between
       the result image and the legend key, so it needs its own spacing on
       both sides. */
    flex-shrink: 0;
    margin: 6px 0;
}

.result-metric-title-main {
    font-size: 16px;
    font-weight: 700;
    color: var(--text-body-dark);
    letter-spacing: 0.5px;
    line-height: 1.3;
}

.result-metric-title-sub {
    font-size: 13px;
    font-weight: 700;
    color: var(--text-body-dark);
    text-transform: none;
    letter-spacing: 0.5px;
    margin-bottom: 4px;
}

.result-metric-value {
    display: inline-block;
    font-size: 18px;
    font-weight: 800;
    color: #223043;
    border: 2px solid #223043;
    border-radius: 0;
    padding: 2px 8px;
    margin-top: 4px;
}

.result-metric-value--pass {
    background: #FFD700;
    border-color: #C9A800;
    color: #223043;
}

.result-metric-value--fail {
    background: #6B3FA0;
    border-color: #4A2B72;
    color: #fff;
}

.x-axis text,
.y-axis text {
    font-size: 11px;
}

#barChart .x-axis text,
#barChart .y-axis text {
    font-size: 16px;
}

/* KPI scatter chart axes */
#scatterChart .x-axis text,
#scatterChart .y-axis text {
    font-size: 16px;
    font-weight: 400;
}



.future-panel {
    min-height: 0;
    background:
        linear-gradient(180deg, rgba(107, 155, 209, 0.06), rgba(107, 155, 209, 0.02)),
        #fbfcfd;
}

.sawtooth-main h2 {
    font-size: 16px;
}

.facade-articulation-panel .panel-header-row h2,
.sawtooth-panel .panel-header-row h2 {
    font-size: clamp(12px, 1.04vw, 20px);
}

.sawtooth-main {
    display: flex;
    flex-direction: row;
    flex: 1;
    min-height: 0;
    gap: clamp(16px, 2.5vw, 48px);
    align-items: stretch;
    justify-content: center;
    padding: 0 clamp(10px, 15.6vw, 300px);
}

.facade-articulation-panel {
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: clamp(8px, 1.2vw, 24px);
    background: #ffffff;
    border: 1px solid #dfe6ee;
    border-radius: 12px;
    padding: clamp(8px, 0.8vw, 16px);
    overflow: hidden;
    box-shadow: 0 6px 20px rgba(34,48,67,0.28);
}

.facade-controls-col {
    display: flex;
    flex-direction: column;
    gap: 16px;
    flex: 0 0 auto;
    width: 260px;
    padding: 12px 16px;
    justify-content: center;
    border-right: 1px solid #dfe6ee;
    background: #f7f8fa;
}

.facade-control-group {
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 0 0 auto;
    align-items: flex-start;
}

.facade-control-label {
    font-size: clamp(10px, 0.94vw, 18px);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: #4a5a6e;
}

.facade-control-opts {
    display: flex;
    flex-direction: row;
    gap: 3px;
    flex-wrap: nowrap;
    align-items: center;
    background: var(--color-bg-tab);
    border: 1px solid rgba(34, 48, 67, 0.08);
    border-radius: 999px;
    padding: 3px;
    box-shadow: inset 0 2px 4px rgba(36, 52, 71, 0.08);
}

.facade-control-opt {
    padding: 3px 8px;
    font-size: 15px;
    font-weight: 600;
    color: #4a5a6e;
    cursor: pointer;
    border: none;
    border-radius: 999px;
    background: transparent;
    transition: background 0.15s ease;
    white-space: nowrap;
    text-align: center;
    box-shadow: none;
}

.facade-control-opt:hover {
    background: rgba(255, 255, 255, 0.65);
    color: var(--color-navy-text);
}

.facade-control-opt.active {
    background: var(--color-accent-blue-dark);
    color: #fff;
    font-weight: 700;
    border: 1.5px solid var(--color-accent-blue-dark);
    box-shadow: 0 3px 8px rgba(49, 87, 117, 0.35);
}

.facade-top-row {
    display: flex;
    flex-direction: row;
    flex: 0 0 auto;
    height: clamp(260px, 38vh, 400px);
    min-height: 0;
    border: 1px solid #dfe6ee;
    border-radius: 12px;
    overflow: hidden;
}

.facade-bottom-area {
    flex: 1 1 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 12px 0 4px;
}

.facade-scatter-box {
    display: flex;
    flex-direction: column;
    background: #fff;
    border: 1px solid #dde3ec;
    border-radius: 10px;
    padding: 14px 20px 16px;
    box-shadow: 0 1px 6px rgba(0,0,0,0.06);
    width: 100%;
    max-width: 960px;
    flex: 1;
    min-height: 0;
    box-sizing: border-box;
}

.facade-scatter-box-header {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-shrink: 0;
    padding-bottom: 8px;
}

.facade-scatter-box-title {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 0.7px;
    text-transform: uppercase;
    color: #6b7a90;
    white-space: nowrap;
}

.facade-scatter-charts-row {
    display: flex;
    flex-direction: row;
    gap: 16px;
    flex: 1;
    min-height: 0;
}

.facade-scatter-stack {
    flex: 1;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding-top: 0;
}

#facadeAltitudeScatter {
    margin-top: 50px;
}

.facade-scatter-chart {
    flex: 1;
    min-width: 0;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.facade-scatter-chart svg {
    display: block;
}

.facade-viz-wrap {
    flex: 1 1 0;
    min-height: 0;
    min-width: 0;
    position: relative;
    overflow: hidden;
    background: #f7f8fa;
    display: flex;
    align-items: center;
    justify-content: center;
}

#canvas3dFacade svg {
    width: 100%;
    height: 100%;
    display: block;
}

#canvas3dFacade {
    width: 100%;
    height: 100%;
    display: block;
}

.facade-viz-hint {
    position: absolute;
    bottom: 8px;
    left: 0;
    right: 0;
    text-align: center;
    font-size: 11px;
    font-weight: 600;
    color: #7d8ea3;
    pointer-events: none;
    letter-spacing: 0.5px;
    text-transform: uppercase;
}

.facade-rose-col {
    flex: 1;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.kpi-left-section {
    display: flex;
    flex-direction: column;
    flex: 3;
    min-width: 0;
    gap: 12px;
}

#sawProfilePanel {
    flex: 1 1 0;
    min-width: 0;
    max-width: none;
    align-self: stretch;
}

.sawtooth-layout {
    display: grid;
    grid-template-columns: 1fr;
    gap: 18px;
    width: 100%;
    min-height: 0;
    overflow: hidden;
}

.kpi-selector-section {
    position: relative;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    gap: 24px;
    padding: 6px 16px 10px;
    background: #ffffff;
    border-radius: 12px;
    border: 1px solid #dfe6ee;
    flex-shrink: 0;
    min-height: 260px;
    flex-wrap: wrap;
}

.kpi-panels-row {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 18px;
    width: 100%;
    min-height: 0;
    flex: 1;
}

.kpi-limit-bar {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 4px 8px 6px;
    flex-shrink: 0;
}

.kpi-limit-label {
    font-size: 12px;
    
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--text-subtle);
    white-space: nowrap;
}

.kpi-limit-opts {
    display: flex;
    gap: 2px;
    background: var(--color-bg-tab);
    border: 1px solid rgba(34, 48, 67, 0.08);
    border-radius: 999px;
    padding: 4px;
    box-shadow: inset 0 2px 4px rgba(36, 52, 71, 0.08);
}

.kpi-limit-btn {
    padding: 5px 12px;
    border-radius: 999px;
    border: none;
    background: transparent;
    color: #4a5a6e;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s ease;
    box-shadow: none;
}

.kpi-limit-btn:hover {
    background: rgba(255, 255, 255, 0.65);
    color: var(--color-navy-text);
}

.kpi-limit-btn.active {
    background: var(--color-accent-blue-dark);
    color: #fff;
    font-weight: 700;
    border: 1.5px solid var(--color-accent-blue-dark);
    box-shadow: 0 3px 8px rgba(49, 87, 117, 0.35);
}

.kpi-panel {
    display: flex;
    flex-direction: column;
    min-height: 120px;
}

.kpi-panel-body {
    flex: 1;
    min-height: 0;
    overflow: hidden;
    padding: 8px 0;
}

.saw-panel-selectors {
    display: flex;
    flex-direction: row;
    gap: 60px;
    flex-wrap: wrap;
    flex-shrink: 0;
    justify-content: center;
}

.saw-sel-group {
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 0 0 auto;
    align-items: center;
}

.saw-sel-label {
    font-size: clamp(10px, 0.94vw, 18px);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: #4a5a6e;
    white-space: nowrap;
}

.saw-sel-opts {
    display: flex;
    flex-direction: row;
    gap: 2px;
    flex-wrap: wrap;
    align-items: center;
    background: var(--color-bg-tab);
    border: 1px solid rgba(34, 48, 67, 0.08);
    border-radius: 999px;
    padding: 4px;
    box-shadow: inset 0 2px 4px rgba(36, 52, 71, 0.08);
}

.saw-sel-opt {
    padding: 5px 12px;
    text-align: center;
    font-size: 14px;
    font-weight: 600;
    color: #4a5a6e;
    cursor: pointer;
    border: none;
    border-radius: 999px;
    background: transparent;
    transition: background 0.15s ease;
    white-space: nowrap;
    font-family: inherit;
    box-shadow: none;
}

.saw-sel-opt:hover {
    background: rgba(255, 255, 255, 0.65);
    color: var(--color-navy-text);
}

.saw-sel-opt.active {
    background: var(--color-accent-blue-dark);
    color: #fff;
    font-weight: 700;
    border: 1.5px solid var(--color-accent-blue-dark);
    box-shadow: 0 3px 8px rgba(49, 87, 117, 0.35);
}

.container[data-active-tab="sawtooth-options"] .glass-selector-section {
    display: none;
}

.sawtooth-panel {
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
    border: 1px solid #dfe6ee;
    border-radius: 12px;
    background: #fbfcfd;
    padding: clamp(8px, 0.8vw, 16px);
    display: flex;
    flex-direction: column;
    gap: clamp(8px, 1.2vw, 24px);
    min-height: 0;
    overflow: hidden;
    box-sizing: border-box;
    box-shadow: 0 6px 20px rgba(34,48,67,0.28);
}

.sawtooth-viz-wrap {
    flex: 1 1 0;
    min-height: 0;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-top: auto;
    background: #f7f8fa;
    border: 1px solid #dfe6ee;
    border-radius: 12px;
}

.sawtooth-viz-wrap svg {
    width: 100%;
    max-height: 380px;
    display: block;
    user-select: none;
    -webkit-user-select: none;
    overflow: visible;
    user-select: none;
    -webkit-user-select: none;
}

.saw-config-label {
    font-size: 14px;
    font-weight: 600;
    color: #6b7280;
}

.saw-inline-results {
    display: flex;
    flex-direction: column;
    flex-shrink: 0;
    width: 100%;
    min-height: 0;
    margin-top: auto;
}

.saw-inline-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
    flex-shrink: 0;
    width: 100%;
    grid-column: 1 / -1;
}

.saw-inline-stat {
    display: flex;
    flex-direction: column;
    gap: 1px;
    align-items: center;
    text-align: center;
}

.saw-stat-label {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: #7d8ea3;
}

.saw-stat-value {
    font-size: 9px !important;
    font-weight: 700;
    color: #223043;
    line-height: 1.1;
}

.saw-stat-unit {
    font-size: 11px;
    color: #7d8ea3;
    font-weight: 600;
}

.saw-inline-chart {
    grid-column: 1 / -1;
    min-width: 0;
    height: clamp(280px, 54vh, 520px);
    border-radius: 0;
    border: 1px solid #dfe6ee;
    background: #f7f8fa;
    overflow: hidden;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding-top: 0;
}

@media (max-width: 1400px) {
    .glass-selector-section {
        gap: 6px;
        padding-inline: 10px;
        justify-content: center;
    }

    .glass-selector-wrapper {
        min-width: 76px;
    }

    .main-layout {
        grid-template-columns: 500px minmax(260px, 1.3fr) minmax(200px, 0.9fr);
        max-width: 1480px;
    }

    .performance-top {
        grid-template-columns: minmax(0, 0.75fr) minmax(0, 1fr) minmax(0, 1fr);
    }

    .result-photo {
        width: 80%;
        height: 100%;
        object-fit: contain;
        object-position: left center;
        margin-right: auto;
    }
}

/* ==========================================
   GLARE ANALYSIS TAB
   ========================================== */
.container[data-active-tab="extra-services"] .glass-selector-section {
    display: none;
}

.container[data-active-tab="simple-facade"] .glass-selector-section {
    display: none;
}

.container[data-active-tab="ccf-options"] .glass-selector-section,
.container[data-active-tab="tab6"] .glass-selector-section {
    display: none;
}

/* ==========================================
   VERTICAL SELECTOR RAIL — ONLY GLASS (3% ALLOWANCE) TAB
   Originally built for the Facade Layout (draft) tab, which has since been
   removed; tabs 1-4 now use the .rail-* family near the top of this file
   instead. Kept because .c3pct-layout below still documents/uses these
   exact class names for its own left-hand selector rail.
   ========================================== */
.facade-draft-rail {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    min-height: 0;
    /* .performance-panel (reused here for the card background/border/shadow)
       defaults to overflow:hidden, which would clip the 6 rows instead of
       scrolling on shorter viewports. */
    overflow: auto;
    isolation: isolate;
}

/* Its own sky photo (separate asset from the .glass-rail one), same
   blurred-glass treatment: sits behind the row content via ::before, real
   rows stay on top via .facade-draft-row's own z-index: 1. Clip-path keeps the
   the blur from bleeding past the rail's rounded corners. */
.facade-draft-rail::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    clip-path: inset(0 round 12px);
    background-image: url("assets/sky-backdrop-tab5.jpg");
    background-size: cover;
    background-position: center 30%;
    filter: blur(1.5px) saturate(115%);
    z-index: 0;
}

/* Tint reacts to the selected DGU type, same mechanism/values as .glass-rail's
   (--tint-a/--tint-b set in updateDguPanelTint(),
   main.js) — fallback here is the default (70/33) tint. */
.facade-draft-rail::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: linear-gradient(135deg, var(--tint-a, rgba(173, 214, 232, 0.42)), var(--tint-b, rgba(122, 174, 200, 0.34)));
    transition: background 0.25s ease;
    z-index: 0;
    pointer-events: none;
}

/* Wraps just the rows (not the centering slack .facade-draft-rail adds
   above/below) so the dynamically-drawn chain line measures from an
   unpadded box. */
.facade-draft-rail-inner {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
}

/* The connecting chain itself is drawn dynamically in JS (drawRailNetwork()
   in main.js) into a .selector-network SVG, so it always tracks whichever
   pill is actually active in each row. */

.facade-draft-row {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.facade-draft-row .glass-label-text {
    min-height: 26px;
    text-align: center;
    white-space: normal;
    font-size: 13px;
    line-height: 1.25;
    width: 100%;
}

.facade-draft-row-container {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 10px;
}

.facade-draft-row-container .glass-circle {
    width: 100px;
    height: 100px;
    font-size: 15px;
    cursor: default;
    flex-shrink: 0;
}

.facade-draft-row-container .glass-circle:hover {
    transform: none;
}

/* Options laid out horizontally (Tab 1's popups are a vertical stack below
   the circle; this rail is vertical instead, so the options rotate to a
   horizontal row beside the circle). Reuses .glass-popup's pill chrome
   (background/border/padding) and each option's own base styling as-is. */
.facade-draft-hpopup {
    flex-direction: row;
    gap: 2px;
}

.facade-draft-hpopup .glass-option,
.facade-draft-hpopup .fabric-option,
.facade-draft-hpopup .winwidth-option,
.facade-draft-hpopup .elementdepth-option,
.facade-draft-hpopup .sidefinrot-option,
.facade-draft-hpopup .frit-option {
    cursor: pointer;
    font-size: 12px;
    padding: 5px 9px;
    white-space: nowrap;
}

/* ==========================================
   TAB 2 — ONLY GLASS (3% ALLOWANCE)
   Exact structural clone of Tab 1's main-layout (viewer | Solar Gains
   panel | Daylight/Thermal column), plus a 4th column on the left for the
   5 geometry selectors that Tab 1 gets for free from the shared top bar
   (.glass-selector-section, hidden for this tab — see the
   container[data-active-tab="only-glass-3pct"] rule below). Reuses Tab 3
   (Facade Layout Draft)'s vertical rail solution as-is (.facade-draft-rail/
   -rail-inner/-row/-row-container/-hpopup) rather than inventing a new
   rail layout, since it already solves "how do you fit Tab 1's 5 selectors
   somewhere when there's no shared top bar to sit under". */
.c3pct-layout {
    display: grid;
    grid-template-columns: 320px minmax(0, 1fr) minmax(0, 1.3fr) minmax(0, 0.9fr);
    gap: clamp(8px, 0.9vw, 18px);
    width: 100%;
    margin: 0 auto;
    padding: 0 clamp(10px, 8vw, 200px);
    min-height: 0;
    overflow: hidden;
    flex: 1;
}

/* CCF tab selector section */
.ccf-selector-section {
    position: relative;
    min-height: clamp(100px, 17.6vh, 190px);
    padding: clamp(8px, 1vh, 12px) 32px;
    display: flex;
    justify-content: space-evenly;
    align-items: center;
    gap: 10px;
    overflow: hidden;
    background: #ffffff;
    border: 1px solid #e4ebf3;
    border-radius: 14px;
    box-shadow: 0 2px 10px rgba(34, 48, 67, 0.07);
    margin: 0 clamp(10px, 15.6vw, 300px);
    flex-shrink: 0;
}

.ccf-main-layout {
    grid-template-columns: minmax(0, 0.7fr) minmax(0, 2fr);
    margin-top: 10px;
}

.ccf-panel {
    background: transparent;
    border: none;
    box-shadow: none;
    padding: 0;
}

/* CCF Options has a Limits panel (PSG Limit Target) above its viewer, same
   shape as Tabs 2/4's .rail-mid — but no separate Solar Gains panel, so
   .rail-right (results only) still gets a single grid row instead of the
   2-row split. */
#tab-tab6 .rail-right {
    grid-template-rows: minmax(0, 1fr);
}

/* Matches .glass-option/.elementdepth-option/etc's base look exactly (same
   font size, same 8px rounded-rect shape rather than a pill) so the CCF
   rail's buttons read as the same control as every other tab's, not a
   separate style — the keycap active-state shadow further down does the
   same job for the "pressed" look. */
.ccf-option {
    min-width: 40px;
    padding: 5px 12px;
    text-align: center;
    font-size: 16px;
    font-weight: 600;
    color: var(--text-muted);
    cursor: pointer;
    transition: background 0.15s ease;
    border: none;
    background: transparent;
    border-radius: 8px;
    box-shadow: none;
    position: relative;
    z-index: 2;
}

.ccf-option:hover {
    background: rgba(255, 255, 255, 0.65);
    color: var(--color-navy-text);
}

.ccf-option.active {
    background: var(--color-accent-blue-dark);
    color: #fff;
    font-weight: 700;
    border: 1.5px solid var(--color-accent-blue-dark);
    box-shadow: 0 3px 8px rgba(49, 87, 117, 0.35);
}

#canvas3dCCF {
    width: 100%;
    height: 100%;
    display: block;
    outline: none;
}

/* ── CCF results panel ─────────────────────────────────────────────────────── */
.ccf-hint {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    font-size: 13px;
    color: #8a9baa;
    text-align: center;
    padding: 20px;
}

/* Two-row container filling the full panel */
.ccf-results-outer {
    display: flex;
    flex-direction: column;
    height: 100%;
    gap: 8px;
    padding: 0 8px 8px;
    overflow: hidden;
}

/* Each half is a white card */
.ccf-section-card {
    min-height: 0;
    background: #ffffff;
    border: 1px solid #e4ebf3;
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(34,48,67,0.06);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding: 10px 14px 8px;
}

.ccf-section-card:first-child {
    flex: 2 1 0;
    align-items: center;
    justify-content: flex-start;
}

.ccf-section-card:last-child {
    flex: 1 1 0;
}

/* ── Top card: shading charts ────────────────────────────────────────────── */
.ccf-charts-title-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    flex-shrink: 0;
    margin-bottom: 4px;
    width: 100%;
}

.ccf-charts-title {
    font-size: 18px;
    font-weight: 600;
    color: #223043;
    letter-spacing: 0.01em;
}

.ccf-charts-zone {
    font-size: 11px;
    font-weight: 500;
    color: #4a90d9;
    background: #eaf2fb;
    border-radius: 4px;
    padding: 1px 7px;
}

.ccf-charts-row {
    display: flex;
    flex: 1 1 0;
    min-height: 0;
    max-height: 70%;
    width: 100%;
    gap: 6px;
    align-items: stretch;
    margin: auto;
}

.ccf-pie-col,
.ccf-hourly-col,
.ccf-seasonal-col {
    flex: 1 1 0;
    min-width: 0;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.ccf-pie-col svg,
.ccf-hourly-col svg,
.ccf-seasonal-col svg {
    display: block;
    overflow: visible;
    height: 100%;
    width: auto;
    max-width: 100%;
}

/* ── Bottom card ─────────────────────────────────────────────────────────── */
.ccf-bottom-card {
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 8px;
}

.ccf-bottom-title {
    font-size: 20px;
    font-weight: 700;
    color: #223043;
    flex-shrink: 0;
    text-align: center;
    width: 100%;
}

/* ── Hourly slat-angle breakdown, next to the annual pie (renderCCFBPie in
   main.js) — approved mockup: the panel splits into two equal halves via
   grid so each chart centers within its own half, rather than a flex row
   that either pinned both charts together in the middle or pushed them out
   to the panel's outer edges. */
.ccfb-charts-row {
    display: grid;
    /* Bar chart gets a bit more room than the pie — it now carries axis
       titles/ticks on top of the bars themselves, so it needs the extra
       width more than the pie needs to stay perfectly square. */
    grid-template-columns: 0.85fr 1.15fr;
    align-items: stretch;
    width: 100%;
    flex: 1 1 0;
    min-height: 0;
}

.ccfb-pie-col {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 0;
    min-height: 0;
}

.ccfb-bar-col {
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    /* Centers the (now shorter) title/bars/labels block vertically within
       the column instead of it sitting flush at the top with dead space
       below — .ccfb-bars no longer fills the full column height. */
    justify-content: center;
    gap: 6px;
    padding: 0 22px;
    border-left: 1px solid #eef2f6;
}

.ccfb-bar-col-title {
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    color: var(--text-faint, #7d8ea3);
    text-align: center;
    flex-shrink: 0;
}

.ccfb-bars-row {
    display: flex;
    align-items: stretch;
    gap: 6px;
    width: 88%;
}

/* Rotated axis title + percentage scale, grouped so the pair moves/aligns
   as one block against the matching spacer below (.ccfb-yaxis-wrap-spacer). */
.ccfb-yaxis-wrap {
    flex: 0 0 52px;
    display: flex;
    align-items: stretch;
    gap: 2px;
}

/* Matches Tab 1/2's chart axis titles (e.g. "Solar Gains (W/m²)" on the
   scatter/altitude charts — see the `.attr('font-size', 16/18).attr('fill',
   TAB1_COLORS.axisText)` calls in main.js): plain weight, no uppercase, and
   the same #666666 axis color rather than this chart's own uppercase/bold
   label style used elsewhere. */
.ccfb-yaxis-title {
    flex: 0 0 18px;
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    display: flex;
    align-items: center;
    justify-content: center;
    white-space: nowrap;
    font-size: 16px;
    font-weight: 400;
    letter-spacing: normal;
    text-transform: none;
    color: #666666;
}

/* Percentage scale beside the bars — column-reverse + space-between so
   "0%" lines up with the axis line (.ccfb-bars' border-bottom) and "100%"
   sits flush with the top of the tallest bar. Value styling (plain weight,
   default dark color) matches Tab 1/2's d3 axis tick text. */
.ccfb-yaxis {
    flex: 1;
    display: flex;
    flex-direction: column-reverse;
    justify-content: space-between;
    padding-bottom: 1.5px;
    font-size: 14px;
    font-weight: 400;
    color: #000;
    text-align: right;
}

/* Blank spacer the same width as .ccfb-yaxis-wrap, keeping the hour labels
   below aligned under the bars rather than the y-axis column. */
.ccfb-yaxis-wrap-spacer {
    flex: 0 0 52px;
}

.ccfb-xaxis-title {
    width: 88%;
    text-align: center;
    font-size: 16px;
    font-weight: 400;
    letter-spacing: normal;
    text-transform: none;
    color: #666666;
    margin-top: 2px;
}

.ccfb-bars {
    /* Was flex:1 (filled the full column height, matching the pie) — a
       fixed height instead so the bar chart reads shorter; the column's
       justify-content:center (above) keeps it from sitting lopsided at
       the top of the now-taller leftover space below/above it. */
    flex: 1 1 auto;
    height: clamp(140px, 32vh, 260px);
    display: flex;
    align-items: flex-end;
    gap: 4px;
    padding: 4px 2px 0;
    border-bottom: 1.5px solid #dfe6ee;
    /* Horizontal gridlines at 0/25/50/75/100% of the bar height, matching
       the y-axis ticks. */
    background-image: repeating-linear-gradient(to top, #eef2f6 0, #eef2f6 1px, transparent 1px, transparent 25%);
}

.ccfb-bar-unit {
    flex: 1;
    display: flex;
    flex-direction: column-reverse;
    height: 100%;
    border-radius: 1px 1px 0 0;
    overflow: hidden;
    cursor: pointer;
    border: 1px solid #223043;
}

.ccfb-bar-unit div {
    width: 100%;
}

/* Divides each slat-angle color within a bar so adjacent segments (which
   can be close in hue) don't visually run together — including between the
   bottom-most segment and the one above it (the border sits on each
   segment's own top edge, so even the first/bottom one needs it to
   separate it from its neighbour). */
.ccfb-bar-seg {
    border-top: 1px solid rgba(34, 48, 67, 0.4);
}

.ccfb-hour-labels-row {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    width: 88%;
}

.ccfb-hour-labels {
    flex: 1 1 auto;
    display: flex;
    gap: 4px;
    padding: 0 2px;
    flex-shrink: 0;
}

/* Matches Tab 1/2's d3 axis tick text (plain weight, default dark color)
   rather than this chart's own bold/muted label style used elsewhere. */
.ccfb-hour-labels span {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    font-size: 14px;
    font-weight: 400;
    color: #000;
}

/* Tick mark connecting each hour value down from the axis line
   (.ccfb-bars' border-bottom) so the row reads as a real x-axis. */
.ccfb-hour-labels span::before {
    content: '';
    display: block;
    width: 1px;
    height: 5px;
    background: #dfe6ee;
    margin-bottom: 3px;
}

.ccf-slat-img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
    flex-shrink: 1;
}

.glare-main {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    gap: 10px;
    background: #ffffff;
    border: 1px solid #dfe6ee;
    border-radius: 12px;
    padding: 16px;
    box-shadow: 0 6px 20px rgba(34,48,67,0.28);
}

.glare-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    flex-shrink: 0;
    gap: 16px;
}

.glare-header-left {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.glare-header-left h2 {
    font-size: 18px;
    font-weight: 700;
    color: #223043;
    margin: 0;
}

.glare-threshold-info {
    font-size: 12px;
    color: #7d8ea3;
    font-weight: 600;
    letter-spacing: 0.3px;
}

.glare-dgu-wrapper {
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex: 0 0 auto;
    background: #ffffff;
    border: 1px solid #dfe6ee;
    border-radius: 12px;
    padding: 12px;
    align-self: stretch;
    box-shadow: 0 6px 20px rgba(34,48,67,0.28);
}

.glare-segment-result {
    flex: 1;
    min-width: 0;
    background: #ffffff;
    border: 1px solid #dfe6ee;
    border-radius: 12px;
    padding: 12px;
    box-shadow: 0 6px 20px rgba(34,48,67,0.28);
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    overflow-y: auto;
    align-self: stretch;
}

.glare-result-placeholder {
    font-size: 12px;
    color: #a0aac0;
    text-align: center;
    width: 100%;
}


.glare-result-content {
    display: flex;
    flex-direction: column;
    gap: 12px;
    width: 100%;
}

.glare-result-title {
    font-size: clamp(10px, 0.94vw, 18px);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: #4a5a6e;
}

.glare-result-info {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.glare-result-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-bottom: 6px;
    border-bottom: 1px solid #f0f3f8;
    width: 100%;
    gap: 4px;
}

.glare-result-row:last-child {
    border-bottom: none;
}

.glare-result-label {
    font-size: 14px;
    color: #7d8ea3;
    flex-shrink: 0;
}

.glare-result-value {
    font-size: 15px;
    font-weight: 600;
    color: #223043;
    text-align: right;
    flex-shrink: 0;
}

.glare-dgu-label {
    font-size: clamp(10px, 0.94vw, 18px);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: #4a5a6e;
    text-align: center;
}

.glare-dgu-bar {
    display: flex;
    flex-direction: row;
    align-items: center;
}

.glare-dgu-circle {
    width: clamp(28px, 2.3vw, 45px);
    height: clamp(28px, 2.3vw, 45px);
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.75);
    border: 2px solid #d0dae6;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    box-shadow: 0 4px 12px rgba(34, 48, 67, 0.10);
    flex-shrink: 0;
    font-size: clamp(8px, 0.68vw, 13px);
    font-weight: 800;
    color: #223043;
}

.glare-dgu-circle img {
    width: 88%;
    height: 88%;
    object-fit: contain;
}

.glare-dgu-connector {
    display: none;
}


.glare-scenario-tabs {
    display: flex;
    flex-direction: row;
    gap: 2px;
    flex-wrap: wrap;
    background: var(--color-bg-tab);
    border: 1px solid rgba(34, 48, 67, 0.08);
    border-radius: 999px;
    padding: 4px;
    box-shadow: inset 0 2px 4px rgba(36, 52, 71, 0.08);
}

.glare-scenario-btn {
    min-width: 40px;
    padding: 5px 12px;
    font-size: 14px;
    font-weight: 600;
    color: #4a5a6e;
    cursor: pointer;
    border: none;
    border-radius: 999px;
    background: transparent;
    transition: background 0.15s ease;
    white-space: nowrap;
    font-family: inherit;
    text-align: center;
    box-shadow: none;
}

.glare-scenario-btn:hover {
    background: rgba(255, 255, 255, 0.65);
    color: var(--color-navy-text);
}

.glare-scenario-btn.active {
    background: var(--color-accent-blue-dark);
    color: #fff;
    font-weight: 700;
    border: 1.5px solid var(--color-accent-blue-dark);
    box-shadow: 0 3px 8px rgba(49, 87, 117, 0.35);
}

.glare-placeholder-notice {
    font-size: 12px;
    color: #7d8ea3;
    background: #f0f4f8;
    border: 1px solid #c8d6e5;
    border-radius: 0;
    padding: 6px 12px;
    flex-shrink: 0;
}

.glare-split-layout {
    flex: 1;
    min-height: 0;
    display: flex;
    align-items: stretch;
    gap: 40px;
    padding: 0 300px;
}

.glare-section-panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    min-width: 0;
    flex: 2.5;
    gap: 10px;
}

.carbon-col {
    flex: 1.5;
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-height: 0;
}

.glare-section-empty {
    flex: 1;
    min-height: 0;
    background: #ffffff;
    border: 1px solid #dfe6ee;
    border-radius: 12px;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 6px 20px rgba(34,48,67,0.28);
}

.carbon-panel-img {
    width: 100%;
    height: auto;
    border-radius: 0;
    object-fit: cover;
    flex-shrink: 0;
}

.glare-controls-bar {
    display: flex;
    align-items: center;
    gap: 20px;
    flex-wrap: wrap;
}

.glare-body {
    flex: 1;
    min-height: 0;
    display: flex;
    align-items: stretch;
    gap: 12px;
    overflow: hidden;
}

.glare-model-wrap {
    flex: 0.7;
    min-height: 0;
    position: relative;
    border-radius: 12px;
    overflow: hidden;
    border: 1px solid #dfe6ee;
    background: #fff;
    box-shadow: 0 6px 20px rgba(34,48,67,0.28);
}

.glare-right-col {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-height: 0;
}

.glare-center-panel {
    flex: 0 0 auto;
    display: flex;
    flex-direction: row;
    gap: 12px;
    align-items: stretch;
}

.glare-room-wrap {
    flex: 1;
    min-height: 0;
    min-width: 0;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    border-radius: 12px;
    border: 1px solid #dfe6ee;
    background: #fff;
    box-shadow: 0 6px 20px rgba(34,48,67,0.28);
}

#canvas3dGlare {
    width: 100%;
    height: 100%;
    display: block;
}

.rose-panel {
    display: flex;
    align-items: stretch;
    justify-content: center;
}

.solar-rose-container {
    width: 100%;
    height: 100%;
    min-height: 0;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    overflow: hidden;
}

.solar-rose-container svg {
    width: 100%;
    height: 100%;
    max-height: none;
}

#altRoseChart,
#altRoseChartFe,
#altRoseChartAb,
#altRoseChartFeb {
    height: 100%;
    align-items: flex-start;
}

#altRoseChart svg,
#altRoseChartFe svg,
#altRoseChartAb svg,
#altRoseChartFeb svg {
    max-height: none;
}

/* Nudged up from dead-center (xMidYMid in renderAltitudeRose) — Tabs 1/2's
   roses specifically, since they now sit alongside the scatter/bar charts
   in a single row and read better slightly higher than perfectly centered. */
#altRoseChartFe svg,
#altRoseChartFeb svg {
    transform: translateY(-8%);
}

/* Tab 1's gain rose only ever had this cap — the Fe/Ab/Feb variants never
   got it, so they rendered inconsistently vs tab 1. flex-grow (new) makes
   the rose actually claim the space up to this cap — without it, the
   sibling azimuth overlay image below (which has flex-shrink:0, see its
   max-height cap in index.html) wins any space contest and the rose gets
   squeezed to whatever's left over instead. */
#roseGainChart,
#roseGainChartFe,
#roseGainChartAb,
#roseGainChartFeb {
    max-height: 68%;
    flex: 1 1 auto;
    min-height: 0;
}

/* Tab 1's azimuth rose specifically — smaller than the shared 68% cap. The
   rose SVG's viewBox scales proportionally to fill its container (see the
   OUTER_R note in solar-rose.js), so shrinking the *container* height here
   is what actually shrinks the semicircle's radius. */
#roseGainChartFe {
    max-height: 50%;
}

#modelWindowOverlay,
#modelWindowOverlayFe,
#modelWindowOverlayAb,
#modelWindowOverlayFeb,
#modelWindowOverlayCcf {
    position: absolute;
    top: 14px;
    left: 14px;
    background: var(--overlay-panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 8px;
    padding: 10px 14px;
    text-align: left;
    pointer-events: none;
    backdrop-filter: blur(4px);
}

.model-overlay-label {
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: var(--text-body-dark);
    text-transform: uppercase;
}

/* Shows which Flexible Limit mode (All Hours/Cooling Season/etc.) the
   Exceedance Hours figure above is scoped to. */
.model-overlay-mode-label {
    margin-top: 2px;
    font-size: 14px;
    color: var(--text-body-dark);
}

/* Sub-heading under SHADING USE FREQUENCY (Tabs 3/4 only) clarifying the
   fixed 4015-hour occupied-hours denominator that figure is computed over
   (see updateExceedanceStats' comment in main.js). */
.model-overlay-sublabel {
    margin-top: 1px;
    font-size: 14px;
    color: var(--text-body-dark);
    opacity: 0.75;
}

/* Shows which hours (All hours/Occupied hours) the Flexible Limit mode
   above is actually counted over — only shown for Cooling Season/
   Toutdoor>18°C/Cooling season 3% allowance, not All Hours. */
.model-overlay-time-label {
    font-size: 15px;
    color: var(--text-body-dark);
}

.model-overlay-value {
    display: inline-block;
    margin-top: 4px;
    padding: 8px 10px;
    text-align: center;
    font-size: 16px;
    font-weight: 700;
    border-radius: 6px;
    color: #fff;
    background: var(--badge-fail);
    line-height: 1.2;
    white-space: nowrap;
}

.model-overlay-value--secondary {
    display: inline-block;
    margin-top: 4px;
    padding: 6px 10px;
    text-align: center;
    font-size: 16px;
    font-weight: 700;
    border-radius: 6px;
    color: var(--text-body-dark);
    background: var(--overlay-value-secondary-bg);
    line-height: 1.2;
    white-space: nowrap;
}

.model-overlay-value--exceed-hot {
    border: 5px solid var(--season-cooling);
}

/* Once the exceedance % is within the 3% target — was border-only (green
   outline over the same plain grey/red-bordered fill), which read as barely
   different from the non-compliant state. Fills the badge green outright,
   matching how the Peak Solar Gain badge signals "compliant" with a solid
   background swap instead of just an outline. */
.model-overlay-value--compliant {
    border: 5px solid var(--psg-safe);
    background: var(--psg-safe);
    color: var(--color-navy-text);
}

.model-psg-legend {
    position: absolute;
    top: 14px;
    right: 14px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 10px 14px;
    background: var(--overlay-panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 8px;
    font-size: 13px;
    color: var(--color-navy-text);
    pointer-events: none;
    backdrop-filter: blur(4px);
}

.model-psg-legend > div {
    display: flex;
    align-items: center;
    gap: 8px;
}

.model-psg-legend-title {
    font-size: 13px;
    font-weight: 700;
    color: var(--color-navy-text);
    margin-bottom: 2px;
}

.model-psg-legend-item {
    display: flex;
    align-items: center;
    gap: 7px;
}

.model-psg-swatch {
    width: 14px;
    height: 14px;
    border-radius: 0;
    flex-shrink: 0;
}

.model-psg-label {
    font-size: 13px;
    font-weight: 500;
    color: #223043;
    white-space: nowrap;
}

.viewer-hint-img {
    position: absolute;
    bottom: 10px;
    right: 12px;
    left: auto;
    transform: none;
    height: 44px;
    width: auto;
    pointer-events: none;
    opacity: 0.7;
    z-index: 10;
}

@keyframes logoPulse {
    0%, 100% { opacity: 0.25; }
    50%       { opacity: 0.85; }
}

#modelLoadingOverlay {
    position: fixed;
    inset: 0;
    background: #ffffff;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9999;
    transition: opacity 0.5s ease;
}

#modelLoadingOverlay.hidden {
    opacity: 0;
    pointer-events: none;
}

#modelLoadingLogo {
    width: clamp(220px, 40%, 420px);
    height: auto;
    animation: logoPulse 1.8s ease-in-out infinite;
}

.glare-model-hint {
    position: absolute;
    bottom: 8px;
    left: 0;
    right: 0;
    text-align: center;
    font-size: 11px;
    font-weight: 600;
    color: #7d8ea3;
    pointer-events: none;
    letter-spacing: 0.5px;
    text-transform: uppercase;
}

.glare-room-wrap svg {
    width: 100%;
    height: 100%;
    display: block;
}

.glare-side-panel {
    flex-shrink: 0;
    width: 200px;
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: 14px;
    background: #fbfcfd;
    border: 1px solid #dfe6ee;
    border-radius: 12px;
    overflow-y: auto;
}

.glare-panel-title {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: #7d8ea3;
    border-bottom: 1px solid #e6edf5;
    padding-bottom: 6px;
    margin-bottom: 8px;
}

.glare-legend {
    display: flex;
    flex-direction: row;
    gap: 24px;
    flex-shrink: 0;
    justify-content: center;
    flex-wrap: wrap;
    padding-top: 6px;
    border-top: 1px solid #edf2f7;
}

.glare-legend-item {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: clamp(8px, 0.63vw, 12px);
    color: #223043;
    font-weight: 500;
    white-space: nowrap;
}

.glare-legend-swatch {
    width: 14px;
    height: 14px;
    border-radius: 0;
    flex-shrink: 0;
    margin-top: 1px;
}

/* #tab-tab6 (CCF Options) intentionally excluded from these three — they
   were sized for the old horizontal-strip selector layout CCF used before
   it moved to the same compact .rail-layout as Tabs 2/4 (see git history);
   keeping them would make CCF's circles/labels visibly larger than every
   other tab's for no reason. #tab-all-options is a separate, unreachable
   legacy tab that still uses that older layout — left alone. */
#tab-all-options .glass-circle {
    font-size: 25px;
}

#tab-all-options .glass-label-text {
    font-size: clamp(16px, 1.8vw, 30px);
}

#tab-all-options .ccf-option {
    font-size: 16px;
}

.glare-swatch-red {
    background: #C00000;
}

.glare-swatch-white {
    background: #e8ecf0;
    border: 1px solid #c8d6e5;
}

.glare-compass-section {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.glare-compass-desc {
    font-size: 11.5px;
    color: #7d8ea3;
    line-height: 1.5;
}

.analysis-mini-tab {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 4px 0 8px;
    flex-shrink: 0;
}

.analysis-mini-tab--placeholder {
    background: #f4f7fb;
    border: 1px solid #dfe6ee;
    border-radius: 0;
    padding: 12px 14px;
    opacity: 0.6;
}

.analysis-mini-tab-img {
    height: clamp(80px, 13.9vh, 150px);
    width: auto;
    max-width: 100%;
    border-radius: 0;
    object-fit: contain;
    display: block;
    margin: 0 auto;
}

.analysis-mini-tab-img-placeholder {
    height: 120px;
    width: 100%;
    border-radius: 0;
    background: #dfe6ee;
}

.carbon-filter-section {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding-top: 8px;
    align-items: center;
}

.carbon-filter-row {
    display: flex;
    align-items: center;
    gap: 12px;
    justify-content: center;
}

.carbon-filter-circle {
    width: 50px;
    height: 50px;
    min-width: 50px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.75);
    border: 2px solid #6b9bd1;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 15px;
    font-weight: 700;
    color: #223043;
    cursor: pointer;
    box-shadow: 0 4px 10px rgba(107, 155, 209, 0.15);
    transition: transform 0.2s;
}

.carbon-filter-circle:hover {
    transform: scale(1.04);
}

.carbon-filter-tabs {
    display: flex;
    gap: 2px;
    flex-wrap: wrap;
    background: var(--color-bg-tab);
    border: 1px solid rgba(34, 48, 67, 0.08);
    border-radius: 999px;
    padding: 4px;
    box-shadow: inset 0 2px 4px rgba(36, 52, 71, 0.08);
}

.carbon-filter-tab {
    padding: 5px 12px;
    border-radius: 999px;
    border: none;
    background: transparent;
    color: #4a5a6e;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s ease;
    white-space: nowrap;
    box-shadow: none;
}

.carbon-filter-tab:hover {
    background: rgba(255, 255, 255, 0.65);
    color: var(--color-navy-text);
}

.carbon-filter-tab.active {
    background: var(--color-accent-blue-dark);
    color: #fff;
    font-weight: 700;
    border: 1.5px solid var(--color-accent-blue-dark);
    box-shadow: 0 3px 8px rgba(49, 87, 117, 0.35);
}

.carbon-result-section {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding-top: 12px;
    border-top: 1px solid #e6edf5;
    margin-top: 12px;
}

.carbon-result-label {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.6px;
    color: #7d8ea3;
}

.carbon-result-value {
    font-size: 22px;
    font-weight: 700;
    color: #223043;
}

.analysis-mini-tab-title {
    font-size: clamp(12px, 1.04vw, 20px);
    font-weight: 700;
    color: #223043;
    font-family: 'Century Gothic', CenturyGothic, sans-serif;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    text-align: center;
}

.glare-tooltip {
    position: fixed;
    pointer-events: none;
    background: rgba(34, 48, 67, 0.93);
    color: #fff;
    font-size: 15px;
    font-family: 'Century Gothic', CenturyGothic, sans-serif;
    padding: 8px 12px;
    border-radius: 0;
    line-height: 1.6;
    z-index: 9999;
    white-space: nowrap;
    transition: opacity 0.1s;
}

/* Simple Facade Tab */
.simple-facade-container {
    display: flex;
    flex-direction: column;
    gap: 24px;
    padding: 24px;
    height: 100%;
    overflow-y: auto;
}

.simple-facade-container h2 {
    font-size: 22px;
    font-weight: 700;
    color: #223043;
    margin-bottom: 12px;
}

.simple-controls {
    display: flex;
    flex-direction: column;
    gap: 20px;
    background: #fff;
    padding: 20px;
    border-radius: 0;
    border: 1px solid #dfe6ee;
}

.control-group {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.control-group label {
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #7d8ea3;
}

.button-group {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.control-btn {
    padding: 10px 16px;
    border-radius: 0;
    border: 1px solid #c8d6e5;
    background: #fff;
    color: #3a4a5c;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s;
    white-space: nowrap;
}

.control-btn:hover {
    border-color: #6b9bd1;
    background: #f4f9ff;
    color: #2a6aad;
}

.control-btn.active {
    background: #2a6aad;
    color: #fff;
    border-color: #2a6aad;
}

.simple-output {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
}

.output-card {
    display: flex;
    flex-direction: column;
    gap: 12px;
    background: #fff;
    padding: 20px;
    border-radius: 0;
    border: 1px solid #dfe6ee;
}

.output-label {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #7d8ea3;
}

.output-value {
    font-size: 34px;
    font-weight: 700;
    color: #2a6aad;
}

.output-config {
    font-size: 14px;
    color: #3a4a5c;
    line-height: 1.6;
    word-break: break-all;
    font-family: 'Courier New', monospace;
}

