/* builder.css — demo builder UI chrome (W2 — single right sidebar).
 *
 * Layout:
 *   topnav (56px) · canvas (flex: 1) · right sidebar (360px, 4 tabs).
 *
 * No left sidebar — every panel (Elements / Controls / Page / Themes)
 * lives in the single right sidebar's tab strip per user direction
 * (W2 mid-wave restructure 2026-05-07).
 *
 * Loaded after tokens.css + app.css; consumes --demo-* tokens only. No
 * hardcoded hex anywhere. Light/dark inverts via [data-theme] on <html>;
 * Bootstrap form controls + BuilderJS internals (.bjs-* / .form-control /
 * .toggle-switch / .form-range) sync via the matching `data-bs-theme`
 * attribute that theme-toggle.js mirrors.
 *
 * Sections:
 *   1.  Layout shell + body reset
 *   2.  Top nav (.demo-builder__topnav)
 *   3.  Right sidebar (tab strip + 4 panels)
 *   4.  Canvas + device-mode classes
 *   5.  Loading overlay
 *   6.  BuilderJS bridge — SettingsContainer wrapper styling, scrollbars
 *   7.  Change Theme modal
 *   8.  Notifications (toast)
 *   9.  Responsive tweaks (≤1280, ≤1024, ≤768)
 *
 * @see docs/archived/demo/DESIGN.md §5
 * @see docs/archived/demo/W2_BUILDER_UI.md
 */

/* ──────────────────────────────────────────────
 * 1. Layout shell + token aliases
 * ────────────────────────────────────────────── */

:root {
    --demo-builder-topnav-h: 56px;
    --demo-builder-sidebar-w: 360px;            /* 3-widget grid + breathing room */
    --demo-builder-canvas-bg: var(--demo-bg-elevated);
    --demo-builder-canvas-paper: #ffffff;       /* email canvas always paints on white paper */
    --demo-builder-canvas-grid: rgba(0, 0, 0, 0.05);   /* faint grid line — design-tool vibe */
    --demo-builder-canvas-grid-strong: rgba(0, 0, 0, 0.07);
    --demo-builder-scrollbar-thumb: var(--demo-border);
    --demo-builder-scrollbar-thumb-hover: var(--demo-text-muted);
}

[data-theme='dark'] {
    --demo-builder-canvas-bg: #0a0d12;          /* a touch deeper than --demo-bg for contrast */
    --demo-builder-canvas-paper: #ffffff;       /* still white — emails render on white */
    --demo-builder-canvas-grid: rgba(255, 255, 255, 0.04);
    --demo-builder-canvas-grid-strong: rgba(255, 255, 255, 0.06);

    /* ── Dark-mode tone bridge ─────────────────────────────────────────
     * BuilderJS dark palette in dist/builder.css uses #1a1a1a-family
     * grays; demo chrome's dark uses the cooler #11161d-family. The
     * two reading side-by-side feels like "two different dark themes".
     * Override the BG-family `--bjs-*` tokens (text/border stay native
     * — BuilderJS's text contrast is fine) so the BuilderJS surfaces
     * inside the right sidebar inherit the chrome's tone. Loaded after
     * /dist/builder.css (see builder.php) so this wins the cascade. */
    --bjs-bg:              var(--demo-bg-elevated);
    --bjs-bg-subtle:       var(--demo-bg-elevated);
    --bjs-bg-surface:      var(--demo-bg-elevated);
    --bjs-bg-muted-subtle: var(--demo-bg);
}

.demo-body--app {
    overflow: hidden;
    height: 100vh;
}

.demo-builder {
    display: flex;
    align-items: stretch;
    height: calc(100vh - var(--demo-builder-topnav-h));
}

/* ──────────────────────────────────────────────
 * 2. Top nav
 * ────────────────────────────────────────────── */

.demo-builder__topnav {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: var(--demo-space-3);
    height: var(--demo-builder-topnav-h);
    padding: 0 var(--demo-space-4);
    background: var(--demo-bg);
    border-bottom: 1px solid var(--demo-border);
    flex-shrink: 0;
}

.demo-builder__topnav-section {
    display: inline-flex;
    align-items: center;
    gap: var(--demo-space-2);
}
.demo-builder__topnav-section--left   { justify-self: start; }
.demo-builder__topnav-section--center { justify-self: center; }
.demo-builder__topnav-section--right  { justify-self: end; }

.demo-builder__brand {
    display: inline-flex;
    align-items: center;
    gap: var(--demo-space-2);
    color: var(--demo-text-strong);
    font-weight: var(--demo-fw-semibold);
    font-size: var(--demo-fs-md);
    text-decoration: none;
}
.demo-builder__brand:hover { color: var(--demo-text-strong); }
.demo-builder__brand-logo {
    display: inline-block;
    width: 28px;
    height: 28px;
    background-image: url('https://app.appstudio.top/fav.ico');
    background-repeat: no-repeat;
    background-position: center;
    background-size: contain;
}
[data-theme='dark'] .demo-builder__brand-logo {
    background-image: url('https://app.appstudio.top/fav.ico');
}
.demo-builder__brand-wordmark { letter-spacing: -0.01em; }
.demo-builder__brand-accent   { color: var(--demo-accent); }

.demo-builder__sep {
    display: inline-block;
    width: 1px;
    height: 24px;
    background: var(--demo-border);
    margin: 0 var(--demo-space-2);
}

.demo-builder__theme-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--demo-space-1);
    padding: 4px 10px;
    background: var(--demo-accent-soft);
    color: var(--demo-accent);
    font-size: 13px;
    font-weight: var(--demo-fw-semibold);
    letter-spacing: var(--demo-ls-body);
    border-radius: var(--demo-radius-pill);
    max-width: 280px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.demo-builder__theme-badge-icon {
    font-size: 16px;
    line-height: 1;
}

.demo-builder__device-toggle {
    display: inline-flex;
    align-items: center;
    padding: 2px;
    background: var(--demo-bg-elevated);
    border: 1px solid var(--demo-border);
    border-radius: var(--demo-radius-md);
}

.demo-builder__device-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 32px;
    background: transparent;
    border: 0;
    color: var(--demo-text-muted);
    cursor: pointer;
    border-radius: var(--demo-radius-sm);
    transition: background 120ms ease, color 120ms ease;
}
.demo-builder__device-btn .material-symbols-outlined { font-size: 18px; }
.demo-builder__device-btn:hover { color: var(--demo-text); }
.demo-builder__device-btn:focus-visible {
    outline: 2px solid var(--demo-accent);
    outline-offset: 1px;
}
.demo-builder__device-btn.is-active {
    background: var(--demo-bg);
    color: var(--demo-text-strong);
    box-shadow: var(--demo-shadow-sm);
}

.demo-builder__icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    background: transparent;
    border: 1px solid transparent;
    color: var(--demo-text-muted);
    cursor: pointer;
    border-radius: var(--demo-radius-md);
    transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.demo-builder__icon-btn .material-symbols-outlined { font-size: 20px; }
.demo-builder__icon-btn:hover {
    background: var(--demo-bg-elevated);
    color: var(--demo-text);
}
.demo-builder__icon-btn:focus-visible {
    outline: 2px solid var(--demo-accent);
    outline-offset: 2px;
}
.demo-builder__icon-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

/* Export dropdown */

.demo-builder__export {
    position: relative;
}
.demo-builder__export-caret {
    font-size: 16px;
    margin-left: 2px;
}
.demo-builder__export-menu {
    position: absolute;
    top: calc(100% + var(--demo-space-2));
    right: 0;
    z-index: 30;
    width: 360px;
    margin: 0;
    padding: var(--demo-space-2);
    list-style: none;
    background: var(--demo-bg);
    border: 1px solid var(--demo-border);
    border-radius: var(--demo-radius-lg);
    box-shadow: var(--demo-shadow-lg);
}
.demo-builder__export-menu[hidden] { display: none; }

.demo-builder__export-item {
    display: block;
    width: 100%;
    padding: var(--demo-space-3);
    background: transparent;
    border: 0;
    border-radius: var(--demo-radius-md);
    text-align: left;
    cursor: pointer;
    transition: background 120ms ease;
}
.demo-builder__export-item:hover,
.demo-builder__export-item:focus-visible {
    background: var(--demo-bg-elevated);
    outline: none;
}
.demo-builder__export-item-title {
    display: block;
    color: var(--demo-text-strong);
    font-size: var(--demo-fs-sm);
    font-weight: var(--demo-fw-semibold);
    margin-bottom: 2px;
}
.demo-builder__export-item-desc {
    display: block;
    color: var(--demo-text-muted);
    font-size: var(--demo-fs-xs);
    line-height: 1.4;
}

/* ──────────────────────────────────────────────
 * 3. Right sidebar (single column, 4 tabs)
 * ────────────────────────────────────────────── */

.demo-builder__sidebar {
    display: flex;
    flex-direction: column;
    background: var(--demo-bg-elevated);
    overflow: hidden;
    flex-shrink: 0;
}
.demo-builder__sidebar--right {
    width: var(--demo-builder-sidebar-w);
    border-left: 1px solid var(--demo-border);
}

/* Tab strip — flush with sidebar edges, no padding around the buttons.
 * Each tab carries a transparent 2 px bottom border that flips to
 * `--demo-text-strong` on active. The strip's own `border-bottom: 1px`
 * sits beneath; the active tab's 2 px border overlaps it so the
 * indicator visually "lives" on the bottom edge of the tab — the
 * "folder tab" feel the user asked for. No tab radius, no inset
 * shadow, no inner padding around the strip. */

.demo-builder__sidebar-tabs {
    display: flex;
    align-items: stretch;
    gap: 0;
    padding: 0;
    background: var(--demo-bg);
    border-bottom: 1px solid var(--demo-border);
    flex-shrink: 0;
}
.demo-builder__sidebar-tab {
    flex: 1;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: var(--demo-space-3) var(--demo-space-2);
    background: transparent;
    border: 0;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;          /* overlap the strip border-bottom */
    color: var(--demo-text-muted);
    font-size: var(--demo-fs-xs);
    font-weight: var(--demo-fw-medium);
    cursor: pointer;
    transition: color 120ms ease, border-color 120ms ease;
}
.demo-builder__sidebar-tab .material-symbols-outlined { font-size: 18px; }
.demo-builder__sidebar-tab-label { line-height: 1; }
.demo-builder__sidebar-tab:hover { color: var(--demo-text); }
.demo-builder__sidebar-tab:focus-visible {
    outline: 2px solid var(--demo-accent);
    outline-offset: -2px;
}
.demo-builder__sidebar-tab.is-active {
    color: var(--demo-text-strong);
    font-weight: var(--demo-fw-semibold);
    border-bottom-color: var(--demo-text-strong);
}

.demo-builder__sidebar-panel {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.demo-builder__sidebar-panel[hidden] { display: none; }

.demo-builder__sidebar-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    /* Flush with sidebar edges — let the inner content (widget grid,
     * Controls renderer) decide its own gutter. Vertical padding keeps
     * the first row off the panel header divider. */
    /* padding: var(--demo-space-3) 0; */
}

.demo-builder__panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--demo-space-2);
    padding: var(--demo-space-3);
    border-bottom: 1px solid var(--demo-border);
    flex-shrink: 0;
}
.demo-builder__panel-title {
    margin: 0;
    color: var(--demo-text-strong);
    font-size: var(--demo-fs-sm);
    font-weight: var(--demo-fw-semibold);
    letter-spacing: var(--demo-ls-caps);
    text-transform: uppercase;
}
.demo-builder__panel-hint-inline {
    color: var(--demo-text-muted);
    font-size: var(--demo-fs-xs);
}
.demo-builder__panel-empty,
.demo-builder__panel-hint {
    margin: 0;
    padding: var(--demo-space-4);
    color: var(--demo-text-muted);
    font-size: var(--demo-fs-sm);
    text-align: center;
}

/* Padded wrapper for action buttons inside a panel body. The sidebar-body
 * is flush with the sidebar edges (vertical-only padding) so consumers
 * that want gutter bring their own — this is the canonical pattern for
 * stretched-width buttons (Open page controls, future "Reset", etc.). */
.demo-builder__panel-action {
    padding: 0 var(--demo-space-3) var(--demo-space-3);
}
.demo-builder__panel-action-btn {
    width: 100%;
    justify-content: center;
}
.demo-builder__panel-empty .material-symbols-outlined {
    display: block;
    margin: 0 auto var(--demo-space-3);
    font-size: 32px;
    color: var(--demo-text-muted);
    opacity: 0.6;
}
.demo-builder__panel-empty p { margin: 0; }

/* Theme list (Themes panel) — 2-up grid of thumbnail cards. */

.demo-builder__theme-list {
    list-style: none;
    margin: 0;
    /* The sidebar-body is now flush with the sidebar edges (vertical
     * padding only, no sides), so each consumer that wants gutter brings
     * its own. Theme list = symmetric padding on all four sides. */
    padding: var(--demo-space-3);
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--demo-space-2);
}
.demo-builder__theme-list-item { margin: 0; }

.demo-builder__theme-list-link {
    display: block;
    border: 1px solid var(--demo-border);
    border-radius: var(--demo-radius-md);
    overflow: hidden;
    text-decoration: none;
    color: var(--demo-text);
    background: var(--demo-bg);
    transition: border-color 120ms ease, transform 120ms ease, box-shadow 160ms ease;
}
.demo-builder__theme-list-link:hover {
    border-color: var(--demo-text-muted);
    transform: translateY(-1px);
    box-shadow: var(--demo-shadow-sm);
}
.demo-builder__theme-list-link.is-current {
    border-color: var(--demo-accent);
    box-shadow: 0 0 0 1px var(--demo-accent);
}
.demo-builder__theme-list-thumb {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 5;
    background: var(--demo-bg-elevated);
    border-bottom: 1px solid var(--demo-border);
    overflow: hidden;
}
.demo-builder__theme-list-thumb img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.demo-builder__theme-list-title {
    display: block;
    padding: var(--demo-space-2) var(--demo-space-3);
    font-size: var(--demo-fs-xs);
    color: var(--demo-text);
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Import (collapsible details). */

.demo-builder__import {
    margin-top: var(--demo-space-4);
    border-top: 1px solid var(--demo-border);
    padding-top: var(--demo-space-3);
}
.demo-builder__import > summary {
    list-style: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: var(--demo-space-2);
    padding: var(--demo-space-2) var(--demo-space-3);
    border-radius: var(--demo-radius-md);
    color: var(--demo-text);
    font-size: var(--demo-fs-sm);
    font-weight: var(--demo-fw-medium);
}
.demo-builder__import > summary:hover { background: var(--demo-bg); }
.demo-builder__import > summary::-webkit-details-marker { display: none; }
.demo-builder__import > summary .material-symbols-outlined { font-size: 18px; color: var(--demo-text-muted); }

.demo-builder__import-form {
    display: flex;
    flex-direction: column;
    gap: var(--demo-space-3);
    padding: var(--demo-space-3) 0;
}
.demo-builder__import-drop {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--demo-space-2);
    padding: var(--demo-space-5);
    background: var(--demo-bg);
    border: 2px dashed var(--demo-border);
    border-radius: var(--demo-radius-md);
    color: var(--demo-text-muted);
    text-align: center;
    cursor: pointer;
    transition: border-color 120ms ease, background 120ms ease;
}
.demo-builder__import-drop:hover,
.demo-builder__import-drop.is-dragover {
    border-color: var(--demo-accent);
    background: var(--demo-accent-soft);
    color: var(--demo-text);
}
.demo-builder__import-drop .material-symbols-outlined { font-size: 28px; }
.demo-builder__import-drop-text { font-size: var(--demo-fs-sm); }
.demo-builder__import-help {
    margin: 0;
    color: var(--demo-text-muted);
    font-size: var(--demo-fs-xs);
}

/* ──────────────────────────────────────────────
 * 4. Canvas
 * ────────────────────────────────────────────── */

.demo-builder__canvas {
    flex: 1;
    min-width: 0;
    overflow: auto;
    background-color: var(--demo-builder-canvas-bg);
    /* Subtle 24px grid pattern — Figma/Linear/Mailchimp design-tool vibe.
     * Two stacked linear-gradients build the grid lines on a flat token
     * background. Both grid tokens flip via [data-theme=dark] so light +
     * dark inherit the same intensity ratio. Stronger lines every 96px
     * (4× the base) give a "major grid" feel without noise. */
    background-image:
        linear-gradient(to right,  var(--demo-builder-canvas-grid-strong) 1px, transparent 1px),
        linear-gradient(to bottom, var(--demo-builder-canvas-grid-strong) 1px, transparent 1px),
        linear-gradient(to right,  var(--demo-builder-canvas-grid)        1px, transparent 1px),
        linear-gradient(to bottom, var(--demo-builder-canvas-grid)        1px, transparent 1px);
    background-size: 96px 96px, 96px 96px, 24px 24px, 24px 24px;
    background-position: 0 0;
    padding: var(--demo-space-6) var(--demo-space-7);
    transition: background-color 200ms ease;
}

.demo-builder__canvas-inner {
    margin: 0 auto;
    background: var(--demo-builder-canvas-paper);
    /* Stronger shadow than the chrome's --demo-shadow-md so the email
     * paper visibly floats above the patterned canvas. */
    box-shadow: var(--demo-shadow-lg);
    border-radius: var(--demo-radius-md);
    transition: max-width 200ms ease, width 200ms ease;
}

.demo-builder[data-current-mode='preview'] .demo-builder__canvas {
    padding: var(--demo-space-7);
}
.demo-builder[data-current-device='desktop'] .demo-builder__canvas-inner {
    max-width: 100%;
    width: 100%;
}
.demo-builder[data-current-device='tablet'] .demo-builder__canvas-inner {
    max-width: 768px;
    width: 768px;
}
.demo-builder[data-current-device='mobile'] .demo-builder__canvas-inner {
    max-width: 375px;
    width: 375px;
}

/* ──────────────────────────────────────────────
 * 5. Loading overlay
 * ────────────────────────────────────────────── */

.demo-builder__loading {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--demo-bg);
    transition: opacity 240ms ease, visibility 0s linear 240ms;
}
.demo-builder__loading.is-hidden {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}
/* "Bouncing Trio" — twin of the host app builder canvas loader (chosen via the
 * /rui/ui → Builder Loaders gallery). A triangle, a square and a circle hop in
 * a staggered, SMOOTH elastic wave: ease-OUT up (decelerate into a slow apex
 * "hang"), ease-IN down (gravity), a squash only on floor contact, and a
 * contact shadow that spreads on impact. Two nested layers per shape (jump vs
 * squish) so vertical travel and squash never fight over transform — that is
 * what keeps it buttery-smooth, never janky. Uses the demo accent. */
.demo-builder__loading-spinner {
    width: 96px;
    height: 96px;
    display: block;
    overflow: visible;
}
.demo-builder__loading-spinner .bld-trio { width: 100%; height: 100%; overflow: visible; display: block; }
.bld-trio-tri { fill: var(--demo-accent); }
.bld-trio-sq  { fill: color-mix(in srgb, var(--demo-accent) 50%, white); }
.bld-trio-ci  { fill: var(--demo-accent); }
.bld-trio-floor  { stroke: var(--demo-border); }
.bld-trio-shadow {
    fill: var(--demo-border);
    transform-box: fill-box; transform-origin: 50% 50%;
    animation: demo-trio-shade 1.4s ease-in-out infinite;
}
.bld-trio-jump {
    transform-box: fill-box; transform-origin: 50% 100%;
    animation: demo-trio-jump 1.4s infinite;
}
.bld-trio-squish {
    transform-box: fill-box; transform-origin: 50% 100%;
    animation: demo-trio-squish 1.4s infinite;
}
.bld-trio-c2 .bld-trio-jump,
.bld-trio-c2 .bld-trio-squish,
.bld-trio-c2 .bld-trio-shadow { animation-delay: 0.14s; }
.bld-trio-c3 .bld-trio-jump,
.bld-trio-c3 .bld-trio-squish,
.bld-trio-c3 .bld-trio-shadow { animation-delay: 0.28s; }
@keyframes demo-trio-jump {
    0%        { transform: translateY(0);     animation-timing-function: cubic-bezier(.22,.66,.3,1); }
    46%       { transform: translateY(-30px); animation-timing-function: cubic-bezier(.66,0,.82,.36); }
    88%, 100% { transform: translateY(0); }
}
@keyframes demo-trio-squish {
    0%        { transform: scale(1.16, .84); animation-timing-function: cubic-bezier(.2,.8,.3,1); }
    16%       { transform: scale(.94, 1.06); animation-timing-function: ease-in-out; }
    46%       { transform: scale(1, 1);      animation-timing-function: ease-in-out; }
    78%       { transform: scale(.96, 1.04); animation-timing-function: cubic-bezier(.6,0,.85,.4); }
    88%, 100% { transform: scale(1.16, .84); }
}
@keyframes demo-trio-shade {
    0%, 88%, 100% { transform: scale(1.18, 1); opacity: .55; }
    46%           { transform: scale(.5, 1);   opacity: .18; }
}
@media (prefers-reduced-motion: reduce) {
    .bld-trio-jump, .bld-trio-squish, .bld-trio-shadow {
        animation: demo-trio-calm 2.6s ease-in-out infinite !important;
        transform: none !important;
    }
    @keyframes demo-trio-calm { 0%, 100% { opacity: .5; } 50% { opacity: 1; } }
}

/* ──────────────────────────────────────────────
 * 6. BuilderJS bridge
 *
 * BuilderJS internals (#WidgetsContainer + #SettingsContainer) own their
 * own typography + spacing via `dist/builder.css` (which exposes its
 * dark-mode palette via `[data-theme="dark"]`). The chrome only needs to:
 *   - paint the surrounding sidebar so the panel has bg continuity
 *   - thin every scrollbar to match the chrome's quiet aesthetic
 *   - bridge any class that BuilderJS leaves un-themed (BootStrap form
 *     controls + form labels)
 * ────────────────────────────────────────────── */

#WidgetsContainer,
#SettingsContainer {
    color: var(--demo-text);
}

#MainContainer {
    /* Builder injects its iframe here. */
    min-height: 320px;
}
/* Eliminate the iframe-inline-element bottom gap. Without `display: block`,
 * iframe defaults to inline and leaves a descender-sized strip below it
 * — the wrapper's white background bleeds through that strip and reads
 * as a strange "extra row" beneath the email. Discovered 2026-05-07. */
#MainContainer > iframe {
    display: block;
}

/* Widget palette — override BuilderJS's hard-coded 95px per card so the
 * grid packs 3-per-row inside the sidebar's content area at 360px. The
 * `.widget-item-image` rich variant (image+text widgets) stays full-
 * width — its content is too dense for 3-column compaction.
 *
 * src/builder.css already drops the inner max-height/overflow + side
 * padding on `.widget-items` / `.widgets-box` so the sidebar's own
 * scroll handles overflow (no nested scrollbar). The chrome only needs
 * to tighten the per-card width here. */
.demo-builder__sidebar #WidgetsContainer .widget-group-items {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--demo-space-2);
}
.demo-builder__sidebar #WidgetsContainer .widget-item:not(.widget-item-image):not(.widget-rich) {
    width: 100%;
    padding: var(--demo-space-3) var(--demo-space-2);
}
.demo-builder__sidebar #WidgetsContainer .widget-item-image,
.demo-builder__sidebar #WidgetsContainer .widget-rich {
    grid-column: 1 / -1;   /* rich/image variants span the row */
}
.demo-builder__sidebar #WidgetsContainer .widget-icon-box .material-symbols-rounded {
    font-size: 22px;       /* tightened from BuilderJS default 26px to fit 3-up */
}
.demo-builder__sidebar #WidgetsContainer .widget-label,
.demo-builder__sidebar #WidgetsContainer .widget-item .widget-label {
    font-size: var(--demo-fs-xs);
    line-height: 1.25;
}

/* The "✨ Just drag & drop the widget…" intro card ships from BuilderJS
 * as a Bootstrap `.alert.fst-italic` (16 px italic) — too loud for the
 * chrome. Demote it to a quiet hint: smaller, non-italic, muted text. */
.demo-builder__sidebar #WidgetsContainer .widget-header {
    padding: var(--demo-space-3) var(--demo-space-3) 0;
}
.demo-builder__sidebar #WidgetsContainer .widget-header .alert {
    margin: 0;
    padding: var(--demo-space-2) var(--demo-space-3);
    background: var(--demo-bg-elevated);
    color: var(--demo-text-muted);
    font-size: var(--demo-fs-xs);
    font-style: normal;
    line-height: 1.4;
}

/* Thin scrollbars — chrome-wide. Honours --demo-* tokens so dark mode
 * inverts automatically. Scoped to the builder surface so the design /
 * docs / showcase pages keep platform-default scrollbars. */
.demo-builder,
.demo-builder *,
.demo-builder__modal-body,
.demo-builder__notifications {
    scrollbar-width: thin;
    scrollbar-color: var(--demo-builder-scrollbar-thumb) transparent;
}
.demo-builder ::-webkit-scrollbar,
.demo-builder__modal-body ::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}
.demo-builder ::-webkit-scrollbar-track,
.demo-builder__modal-body ::-webkit-scrollbar-track {
    background: transparent;
}
.demo-builder ::-webkit-scrollbar-thumb,
.demo-builder__modal-body ::-webkit-scrollbar-thumb {
    background: var(--demo-builder-scrollbar-thumb);
    border-radius: 999px;
    border: 2px solid transparent;
    background-clip: padding-box;
}
.demo-builder ::-webkit-scrollbar-thumb:hover,
.demo-builder__modal-body ::-webkit-scrollbar-thumb:hover {
    background: var(--demo-builder-scrollbar-thumb-hover);
    background-clip: padding-box;
}

/* BuilderJS uses bare `<input>` / `<select>` inside the SettingsContainer.
 * Bootstrap 5.3's `data-bs-theme="dark"` (mirrored by theme-toggle.js)
 * already flips its `.form-control` palette — we only patch a couple of
 * legacy classes that BuilderJS still uses without --bjs-* tokens. */
[data-theme='dark'] .demo-builder__sidebar input[type='text'],
[data-theme='dark'] .demo-builder__sidebar input[type='number'],
[data-theme='dark'] .demo-builder__sidebar input[type='url'],
[data-theme='dark'] .demo-builder__sidebar input[type='email'],
[data-theme='dark'] .demo-builder__sidebar select,
[data-theme='dark'] .demo-builder__sidebar textarea {
    background-color: var(--demo-bg);
    color: var(--demo-text);
    border-color: var(--demo-border);
}

/* `.bbg-*` (BackgroundControl) section labels ship with markup but no
 * CSS in dist/builder.css. Without these chrome-side rules, IMAGE /
 * GRADIENT / EFFECTS section headers render in browser-default text
 * color and read "faded" against dark surfaces. Tokenise them so both
 * themes get readable section-header treatment. */
.demo-builder__sidebar .bbg-section-head {
    margin: var(--demo-space-3) 0 var(--demo-space-2);
}
.demo-builder__sidebar .bbg-section-label {
    display: inline-block;
    font-size: var(--demo-fs-xs);
    font-weight: var(--demo-fw-semibold);
    letter-spacing: var(--demo-ls-caps);
    text-transform: uppercase;
    color: var(--demo-text-secondary);
}
.demo-builder__sidebar .bbg-title {
    color: var(--demo-text-strong);
    font-weight: var(--demo-fw-semibold);
    font-size: var(--demo-fs-sm);
}
.demo-builder__sidebar .bbg-desc {
    color: var(--demo-text-muted);
    font-size: var(--demo-fs-xs);
}
.demo-builder__sidebar .bbg-section + .bbg-section {
    border-top: 1px solid var(--demo-border);
    padding-top: var(--demo-space-3);
    margin-top: var(--demo-space-3);
}

/* ──────────────────────────────────────────────
 * 7. Change Theme modal (Bootstrap base + token overrides)
 * ────────────────────────────────────────────── */

.demo-builder__modal {
    background: var(--demo-bg);
    color: var(--demo-text);
    border: 1px solid var(--demo-border);
    border-radius: var(--demo-radius-lg);
    box-shadow: var(--demo-shadow-lg);
}

.demo-builder__modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--demo-space-3);
    padding: var(--demo-space-5);
    border-bottom: 1px solid var(--demo-border);
}

.demo-builder__modal-title {
    margin: 0;
    color: var(--demo-text-strong);
    font-size: var(--demo-fs-lg);
    font-weight: var(--demo-fw-semibold);
}

.demo-builder__modal-tabs {
    display: flex;
    align-items: stretch;
    gap: 0;
    padding: 0 var(--demo-space-5);
    background: var(--demo-bg);
    border-bottom: 1px solid var(--demo-border);
    overflow-x: auto;
    /* Sibling of modal-header/modal-body inside a flex-column modal-content;
       without this, a tall grid in modal-body squeezes the tab strip because
       body's min-height:auto refuses to shrink. Lock tabs at content height. */
    flex-shrink: 0;
}
.demo-builder__modal-tab {
    display: inline-flex;
    align-items: center;
    gap: var(--demo-space-2);
    padding: var(--demo-space-3) var(--demo-space-4);
    background: transparent;
    border: 0;
    border-bottom: 2px solid transparent;
    color: var(--demo-text-muted);
    font-size: var(--demo-fs-sm);
    font-weight: var(--demo-fw-medium);
    cursor: pointer;
    transition: color 120ms ease, border-color 120ms ease;
}
.demo-builder__modal-tab:hover { color: var(--demo-text); }
.demo-builder__modal-tab:focus-visible {
    outline: 2px solid var(--demo-accent);
    outline-offset: -2px;
}
.demo-builder__modal-tab.is-active {
    color: var(--demo-text-strong);
    border-bottom-color: var(--demo-text-strong);
    font-weight: var(--demo-fw-semibold);
}
.demo-builder__modal-tab-count {
    transform: scale(0.85);
}

.demo-builder__modal-body {
    padding: var(--demo-space-5);
    background: var(--demo-bg);
    /* Pair with tabs' flex-shrink:0 — overrides flex item's default
       min-height:auto so overflow-y:auto actually scrolls instead of
       expanding modal-content past its scrollable max-height. */
    min-height: 0;
}
.demo-builder__modal-panel { display: block; }
.demo-builder__modal-panel[hidden] { display: none; }

.demo-builder__theme-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: var(--demo-space-4);
}

.demo-builder__theme-card {
    display: flex;
    flex-direction: column;
    gap: var(--demo-space-2);
    padding: var(--demo-space-2);
    background: var(--demo-bg);
    border: 1px solid var(--demo-border);
    border-radius: var(--demo-radius-md);
    color: var(--demo-text);
    text-decoration: none;
    transition: border-color 120ms ease, transform 120ms ease, box-shadow 160ms ease;
}
.demo-builder__theme-card:hover {
    border-color: var(--demo-text-muted);
    transform: translateY(-2px);
    box-shadow: var(--demo-shadow-md);
    color: var(--demo-text);
}
.demo-builder__theme-card:focus-visible {
    outline: 2px solid var(--demo-accent);
    outline-offset: 2px;
}
.demo-builder__theme-card.is-current {
    border-color: var(--demo-accent);
    box-shadow: 0 0 0 2px var(--demo-accent-soft);
}
.demo-builder__theme-card-thumb {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    aspect-ratio: 4 / 5;
    background: var(--demo-bg-elevated);
    border-radius: var(--demo-radius-sm);
    overflow: hidden;
}
.demo-builder__theme-card-thumb img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.demo-builder__theme-card-placeholder {
    color: var(--demo-text-muted);
    font-size: 32px;
    opacity: 0.6;
}
.demo-builder__theme-card-title {
    padding: 0 var(--demo-space-2) var(--demo-space-2);
    font-size: var(--demo-fs-sm);
    font-weight: var(--demo-fw-medium);
    color: var(--demo-text);
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.demo-builder__theme-empty {
    grid-column: 1 / -1;
    margin: 0;
    padding: var(--demo-space-7);
    text-align: center;
    color: var(--demo-text-muted);
    font-size: var(--demo-fs-sm);
}

/* Bootstrap modal backdrop dimming — single token-driven rule. */
.modal-backdrop.show { opacity: 0.55; }

/* ──────────────────────────────────────────────
 * 8. Notifications (toast)
 * ────────────────────────────────────────────── */

.demo-builder__notifications {
    position: fixed;
    right: var(--demo-space-5);
    bottom: var(--demo-space-5);
    z-index: 1100;
    display: flex;
    flex-direction: column-reverse;
    gap: var(--demo-space-2);
    pointer-events: none;
}

.demo-builder__notification {
    pointer-events: auto;
    display: inline-flex;
    align-items: center;
    gap: var(--demo-space-3);
    min-width: 280px;
    max-width: 420px;
    padding: var(--demo-space-3) var(--demo-space-4);
    background: var(--demo-bg);
    border: 1px solid var(--demo-border);
    border-radius: var(--demo-radius-md);
    color: var(--demo-text);
    box-shadow: var(--demo-shadow-md);
    font-size: var(--demo-fs-sm);
    transform: translateY(8px);
    opacity: 0;
    transition: opacity 200ms ease, transform 200ms ease;
}
.demo-builder__notification.is-visible {
    opacity: 1;
    transform: translateY(0);
}
.demo-builder__notification--success {
    border-color: var(--demo-success);
    color: var(--demo-text-strong);
}
.demo-builder__notification--success .material-symbols-outlined { color: var(--demo-success); }
.demo-builder__notification--error {
    border-color: var(--demo-error);
    color: var(--demo-text-strong);
}
.demo-builder__notification--error .material-symbols-outlined { color: var(--demo-error); }
.demo-builder__notification--info {
    border-color: var(--demo-accent);
    color: var(--demo-text-strong);
}
.demo-builder__notification--info .material-symbols-outlined { color: var(--demo-accent); }
.demo-builder__notification .material-symbols-outlined { font-size: 20px; flex-shrink: 0; }
.demo-builder__notification-message {
    flex: 1;
    line-height: 1.4;
}

/* ──────────────────────────────────────────────
 * 9. Responsive
 * ────────────────────────────────────────────── */

@media (max-width: 1280px) {
    .demo-builder__sidebar--right { width: 320px; }
    .demo-builder__theme-badge    { max-width: 180px; }
}

@media (max-width: 1024px) {
    .demo-builder__topnav { grid-template-columns: 1fr 1fr; padding: 0 var(--demo-space-3); }
    .demo-builder__topnav-section--center { display: none; }
    .demo-builder__sidebar--right { width: 300px; }
    /* Compact chrome — icon-only buttons; labels collapse to icons. */
    .demo-builder__topnav .demo-btn--with-icon span:not(.material-symbols-outlined):not(.demo-builder__export-caret) {
        display: none;
    }
    .demo-builder__topnav .demo-btn { padding: 0 var(--demo-space-2); width: 36px; }
    .demo-builder__topnav-section { gap: var(--demo-space-1); }
    .demo-builder__theme-badge { max-width: 160px; }
}

@media (max-width: 768px) {
    .demo-builder__sidebar--right { display: none; }
    .demo-builder__theme-badge    { display: none; }
    .demo-builder__brand-wordmark { display: none; }
    .demo-builder__sep            { display: none; }
}

/* ── Export menu: "Inline CSS" email-ready accent item (export-inline feature) ──
 *
 * The Inline-CSS item sits ABOVE the HTML/ZIP/Bundle trio (it's the buyer's
 * most-asked export — "why does my email look broken in Gmail?"). Accent-soft
 * tint + a tiny "email-ready" flag pill mark it as the recommended path; a
 * hairline separator below divides it from the three "developer" exports. */
.demo-builder__export-menu { min-width: 300px; }
.demo-builder__export-item--accent { background: var(--demo-accent-soft); }
.demo-builder__export-item--accent:hover,
.demo-builder__export-item--accent:focus-visible { background: var(--demo-accent-soft); filter: brightness(0.97); }
.demo-builder__export-item--accent .demo-builder__export-item-title {
    display: flex;
    align-items: center;
    gap: 6px;
    color: var(--demo-accent);
}
.demo-builder__export-flag {
    display: inline-block;
    padding: 1px 7px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: #fff;
    background: var(--demo-accent);
}
.demo-builder__export-sep {
    height: 1px;
    margin: var(--demo-space-1) var(--demo-space-2);
    background: var(--demo-border);
    list-style: none;
}
/* ============================================================================
   MOBILE CHROME (≤767px) — bottom nav + left menu + left-drawer sidebar
   ----------------------------------------------------------------------------
   Everything is scoped inside the media query. Desktop is byte-identical.
   ============================================================================ */

/* Desktop floor — the mobile shells are hidden unless the media query
   un-hides them. */
.demo-builder__hamburger,
.demo-builder__mobile-backdrop,
.demo-builder__mobile-menu,
.demo-builder__bottom-nav,
.demo-builder__sheet-head {
    display: none;
}

@media (max-width: 767px) {

    /* ── Topnav: add ☰, tighten everything ───────────────────────────── */
    .demo-builder__hamburger {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 40px;
        height: 40px;
        padding: 0;
        margin-right: 4px;
        background: transparent;
        border: 0;
        border-radius: 8px;
        color: var(--demo-text);
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }
    .demo-builder__hamburger:active {
        background: rgba(0, 0, 0, 0.06);
    }
    [data-theme="dark"] .demo-builder__hamburger:active {
        background: rgba(255, 255, 255, 0.08);
    }
    .demo-builder__hamburger .material-symbols-outlined {
        font-size: 24px;
        line-height: 1;
    }

    /* Hide the actions that moved to the left menu. Keep topnav clean:
       just ☰ + brand + device toggle. */
    .demo-builder__topnav-section--right { display: all; }
    .demo-builder__theme-badge           { display: none; }
    .demo-builder__topnav-section--left .demo-btn[data-action="open-change-theme"],
    .demo-builder__topnav-section--left .demo-builder__sep {
        display: none;
    }
    .demo-builder__brand-wordmark { font-size: 14px; }
    .demo-builder__brand-logo     { width: 22px; height: 22px; }

    .demo-builder__topnav {
        height: 52px;
        min-height: 52px;
        padding: 0 8px;
        gap: 4px;
        grid-template-columns: 1fr auto;   /* left + center; right is hidden */
        position: sticky;
        top: 0;
        z-index: 800;
    }
    .demo-builder__device-toggle { padding: 2px; }
    .demo-builder__device-btn    { width: 32px; height: 32px; }

    /* ── Layout shell: single column, canvas above bottom nav ────────── */
     .demo-builder {
        display: block;
        height: calc(100vh - 52px - 64px);        /* topnav + bottom nav */
        min-height: 0;
        padding-bottom: 0;                        /* canvas owns its own scroll */
        overflow: hidden;                          /* the canvas inside scrolls */
    }

    /* Canvas — transitions its left margin so the "push" animation
       matches the drawer's own slide-in timing. The transition lives on
       the canvas itself (outside the body[data-*] rule) so it also runs
       on close — one rule, both directions. */
       .demo-builder__canvas {
        width: 100%;
        height: 100%;                             /* fill the shell */
        min-height: 0;                            /* kill any min-height that fights height:100% */
        overflow-y: auto;                         /* ← the actual scroll */
        overflow-x: hidden;
        -webkit-overflow-scrolling: touch;        /* momentum scroll on iOS */
        overscroll-behavior: contain;             /* don't chain to body */
        padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 24px);
        transition: margin-left 260ms cubic-bezier(0.22, 1, 0.36, 1);
    }
    .demo-builder__canvas-inner { width: 100%; max-width: 100%; }

    /* Push the canvas right while the sidebar is open. The margin value
       MATCHES the sidebar width below so the canvas edge sits exactly at
       the drawer's right border — no gap, no overlap. Change both
       together if you tune the drawer width. */
    body[data-mobile-sidebar-open="true"] .demo-builder__canvas {
        margin-left: min(58vw, 260px);     /* ← reduced from min(72vw, 320px) */
    }

    /* ── Sidebar → LEFT slide-in drawer (push layout) ────────────────── */
    .demo-builder__sidebar {
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        right: auto;
        width: min(58vw, 260px);           /* ← reduced from min(72vw, 320px) */
        height: auto;
        max-height: 100vh;
        z-index: 960;
        background: var(--demo-bg-elevated);
        box-shadow: 8px 0 32px rgba(0, 0, 0, 0.20);
        transform: translateX(-100%);
        transition: transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
        display: flex;
        flex-direction: column;
        overflow: hidden;
        border-left: 0;
        border-right: 1px solid var(--demo-border);
    }
    [data-theme="dark"] .demo-builder__sidebar {
        box-shadow: 8px 0 32px rgba(0, 0, 0, 0.55);
    }
    .demo-builder__sidebar.is-open {
        transform: translateX(0);
    }
    .demo-builder__sidebar--right {
        /* Override the desktop width override at ≤1280/≤1024 */
        width: min(58vw, 260px);           /* ← must match the base rule */
    }

    /* ── Sidebar drawer head — title + close ─────────────────────────── */
    .demo-builder__sheet-head {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 8px;
        flex: 0 0 auto;
        padding: 12px 12px 12px 16px;
        border-bottom: 1px solid var(--demo-border);
        background: var(--demo-bg);
    }
    .demo-builder__sheet-title {
        font-size: 14px;
        font-weight: 600;
        color: var(--demo-text-strong);
    }
    .demo-builder__sheet-close {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 36px;
        height: 36px;
        padding: 0;
        background: transparent;
        border: 0;
        border-radius: 8px;
        color: var(--demo-text-muted);
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }
    .demo-builder__sheet-close:active {
        background: rgba(0, 0, 0, 0.06);
    }
    .demo-builder__sheet-close .material-symbols-outlined {
        font-size: 22px;
    }

    /* ── Bottom nav ──────────────────────────────────────────────────── */
    .demo-builder__bottom-nav {
        display: flex;
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 900;
        height: calc(64px + env(safe-area-inset-bottom, 0px));
        padding: 0 6px env(safe-area-inset-bottom, 0px);
        background: var(--demo-bg);
        border-top: 1px solid var(--demo-border);
        box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.06);
    }
    [data-theme="dark"] .demo-builder__bottom-nav {
        box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.4);
    }
    .demo-builder__bottom-nav-btn {
        flex: 1 1 0;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 3px;
        min-width: 0;
        padding: 8px 4px;
        background: transparent;
        border: 0;
        color: var(--demo-text-muted);
        font: inherit;
        font-size: 11px;
        font-weight: 500;
        line-height: 1;
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
        transition: color 120ms ease;
    }
    .demo-builder__bottom-nav-btn .material-symbols-outlined {
        font-size: 22px;
        line-height: 1;
    }
    .demo-builder__bottom-nav-btn.is-active {
        color: var(--demo-accent);
    }
    .demo-builder__bottom-nav-btn:active {
        background: rgba(0, 0, 0, 0.05);
        border-radius: 8px;
    }
    .demo-builder__bottom-nav-label {
        font-size: 11px;
        line-height: 1;
    }

    /* ── Left menu (actions) — OVERLAY, not push. Also reduced. ──────── */
    /* The ☰ menu is a transient navigation surface, not an editing panel,
       so it keeps the overlay behavior (dim backdrop, tap to dismiss).
       Width matches the sidebar so both feel like the "same drawer" that
       happens to contain different content. */
    .demo-builder__mobile-backdrop {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 950;
        background: rgba(0, 0, 0, 0.45);
        opacity: 0;
        pointer-events: none;
        transition: opacity 220ms ease;
    }
    .demo-builder__mobile-backdrop.is-open {
        opacity: 1;
        pointer-events: auto;
    }
    .demo-builder__mobile-menu {
        display: flex;
        flex-direction: column;
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        width: min(58vw, 260px);           /* ← reduced from min(80vw, 300px) */
        z-index: 960;
        background: var(--demo-bg);
        box-shadow: 8px 0 32px rgba(0, 0, 0, 0.20);
        transform: translateX(-100%);
        transition: transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
    }
    [data-theme="dark"] .demo-builder__mobile-menu {
        box-shadow: 8px 0 32px rgba(0, 0, 0, 0.55);
    }
    .demo-builder__mobile-menu.is-open {
        transform: translateX(0);
    }
    .demo-builder__mobile-menu-head {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 12px 12px 12px 16px;
        border-bottom: 1px solid var(--demo-border);
        flex: 0 0 auto;
    }
    .demo-builder__mobile-menu-title {
        font-size: 14px;
        font-weight: 600;
        color: var(--demo-text-strong);
    }
    .demo-builder__mobile-menu-close {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 36px;
        height: 36px;
        padding: 0;
        background: transparent;
        border: 0;
        border-radius: 8px;
        color: var(--demo-text-muted);
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }
    .demo-builder__mobile-menu-close:active {
        background: rgba(0, 0, 0, 0.06);
    }
    .demo-builder__mobile-menu-close .material-symbols-outlined {
        font-size: 22px;
    }
    .demo-builder__mobile-menu-body {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        padding: 8px;
    }

    /* Buttons CLONED into the menu by JS — style them as full-width rows.
       The menu is narrower now, so trim vertical padding a touch and step
       the label font down 1px so long labels ("Source bundle", "Inline
       CSS") don't wrap awkwardly. */
    .demo-builder__mobile-menu-body > button,
    .demo-builder__mobile-menu-body > .demo-btn {
        display: flex !important;
        align-items: center;
        justify-content: flex-start !important;
        gap: 10px;
        width: 100% !important;
        height: auto !important;
        min-height: 44px;
        padding: 10px 12px !important;
        margin: 0 0 3px !important;
        background: transparent !important;
        border: 0 !important;
        border-radius: 8px !important;
        color: var(--demo-text) !important;
        font: inherit !important;
        font-size: 14px !important;
        text-align: left !important;
        box-shadow: none !important;
        cursor: pointer;
    }
    .demo-builder__mobile-menu-body > button:active,
    .demo-builder__mobile-menu-body > .demo-btn:active {
        background: rgba(0, 0, 0, 0.06) !important;
    }
    [data-theme="dark"] .demo-builder__mobile-menu-body > button:active,
    [data-theme="dark"] .demo-builder__mobile-menu-body > .demo-btn:active {
        background: rgba(255, 255, 255, 0.08) !important;
    }
    /* Hide the labels that only make sense in the topnav */
    .demo-builder__mobile-menu-body .demo-builder__export-caret { display: none; }

    /* Icon sizing — 20px (down from 22) to fit the narrower menu. */
    .demo-builder__mobile-menu-body .material-symbols-outlined { font-size: 20px; }

    /* ── History pill — lift it above the bottom nav ─────────────────── */
    .bjs-history-widget[data-bjs-history-position="bottom-left"],
    .bjs-history-widget[data-bjs-history-position="bottom-right"] {
        bottom: calc(64px + 16px + env(safe-area-inset-bottom, 0px)) !important;
    }
     .demo-body--app {
        overflow: auto;          /* allow the body to breathe; not the scroller though */
        height: auto;
        min-height: 100vh;
    }
}

/* ────────────────────────────────────────────────────────────────────────
   Very small phones (≤480px) — tighten the drawer further so the canvas
   still has a usable strip of width on a 320–375px viewport.

   Sibling media query (NOT nested) so every CSS parser handles it.
   The drawer width and the canvas margin MUST stay in sync — both are
   `min(78vw, 300px)` here. If you tune one, tune the other.
   ──────────────────────────────────────────────────────────────────────── */
/* ────────────────────────────────────────────────────────────────────────
   Very small phones (≤480px) — tighten the drawer a touch further so the
   canvas still has a usable strip on a 320–375px viewport.

   Sibling media query (NOT nested) so every CSS parser handles it.
   The drawer width and the canvas margin MUST stay in sync — both are
   `min(54vw, 240px)` here. If you tune one, tune the other.
   ──────────────────────────────────────────────────────────────────────── */
@media (max-width: 480px) {
    .demo-builder__sidebar,
    .demo-builder__sidebar--right,
    .demo-builder__mobile-menu {
        width: min(54vw, 240px);           /* ← tighter than the 767 rule */
    }
    body[data-mobile-sidebar-open="true"] .demo-builder__canvas {
        margin-left: min(54vw, 240px);     /* ← must match the width above */
    }
}

/* ────────────────────────────────────────────────────────────────────────
   Reduced motion — kill the slide + push animations.
   ──────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    .demo-builder__sidebar,
    .demo-builder__mobile-menu,
    .demo-builder__mobile-backdrop,
    .demo-builder__canvas {
        transition: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .demo-builder__sidebar,
    .demo-builder__mobile-menu,
    .demo-builder__mobile-backdrop {
        transition: none;
    }
}

/* ── Build-App modal ─────────────────────────────────────────── */
.demo-buildapp-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.55);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    z-index: 10050;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    animation: demo-buildapp-fade .18s ease-out;
}

@keyframes demo-buildapp-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.demo-buildapp-dialog {
    width: 100%;
    max-width: 460px;
    max-height: calc(100vh - 40px);
    overflow-y: auto;
    background: var(--demo-surface, #ffffff);
    color: var(--demo-text, #0f172a);
    border-radius: 14px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.32);
    animation: demo-buildapp-pop .22s cubic-bezier(0.2, 1, 0.3, 1);
}

@keyframes demo-buildapp-pop {
    from { transform: translateY(8px) scale(0.97); opacity: 0; }
    to   { transform: translateY(0)    scale(1);    opacity: 1; }
}

.demo-buildapp-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 16px;
    background: linear-gradient(135deg, #3289E5 0%, #1e6fc4 100%);
    color: #ffffff;
}

.demo-buildapp-header .material-symbols-outlined {
    font-variation-settings: 'FILL' 1;
    font-size: 22px;
}

.demo-buildapp-title {
    flex: 1;
    margin: 0;
    font-size: 16px;
    font-weight: 600;
    color: inherit;
}

.demo-buildapp-close {
    background: transparent;
    border: 0;
    color: rgba(255, 255, 255, 0.85);
    cursor: pointer;
    padding: 4px;
    border-radius: 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.demo-buildapp-close:hover {
    background: rgba(255, 255, 255, 0.14);
    color: #ffffff;
}

.demo-buildapp-form {
    padding: 16px 18px 18px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.demo-buildapp-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.demo-buildapp-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--demo-text-muted, #475569);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.demo-buildapp-input {
    width: 100%;
    padding: 10px 12px;
    border: 1px solid var(--demo-border, #cbd5e1);
    border-radius: 8px;
    font-size: 14px;
    font-family: inherit;
    background: var(--demo-input-bg, #ffffff);
    color: inherit;
    outline: none;
    transition: border-color .15s, box-shadow .15s;
    box-sizing: border-box;
}
.demo-buildapp-input:focus {
    border-color: #3289E5;
    box-shadow: 0 0 0 3px rgba(50, 137, 229, 0.18);
}

.demo-buildapp-hint {
    font-size: 11.5px;
    color: var(--demo-text-muted, #64748b);
}

.demo-buildapp-error {
    margin: 0;
    padding: 8px 10px;
    background: #fef2f2;
    color: #b91c1c;
    font-size: 13px;
    border-radius: 8px;
    border: 1px solid #fecaca;
}

.demo-buildapp-actions {
    display: flex;
    gap: 10px;
    justify-content: flex-end;
    margin-top: 4px;
}

/* ── Icon picker ─────────────────────────────────────────────── */
.demo-buildapp-iconpicker {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 110px;
    border: 2px dashed var(--demo-border, #cbd5e1);
    border-radius: 10px;
    background: var(--demo-input-bg, #f8fafc);
    cursor: pointer;
    transition: border-color .15s, background .15s;
    overflow: hidden;
    position: relative;
    outline: none;
}
.demo-buildapp-iconpicker:hover,
.demo-buildapp-iconpicker:focus-visible {
    border-color: #3289E5;
    background: rgba(50, 137, 229, 0.04);
}
.demo-buildapp-iconpicker.is-filled {
    border-style: solid;
    background: var(--demo-surface, #ffffff);
}

.demo-buildapp-iconplaceholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    color: var(--demo-text-muted, #64748b);
    font-size: 12px;
    text-align: center;
    padding: 0 12px;
}
.demo-buildapp-iconplaceholder .material-symbols-outlined {
    font-size: 28px;
    color: #94a3b8;
}

.demo-buildapp-iconpreview {
    max-width: 100%;
    max-height: 100%;
    display: block;
    object-fit: contain;
}

/* Dark theme overrides */
[data-theme="dark"] .demo-buildapp-dialog {
    background: #0f172a;
    color: #e2e8f0;
}
[data-theme="dark"] .demo-buildapp-input {
    background: #1e293b;
    border-color: #334155;
    color: #e2e8f0;
}
[data-theme="dark"] .demo-buildapp-label,
[data-theme="dark"] .demo-buildapp-hint {
    color: #94a3b8;
}
[data-theme="dark"] .demo-buildapp-error {
    background: #2a1017;
    border-color: #7f1d1d;
    color: #fca5a5;
}
[data-theme="dark"] .demo-buildapp-iconpicker {
    background: #1e293b;
    border-color: #334155;
}
[data-theme="dark"] .demo-buildapp-iconpicker.is-filled {
    background: #0f172a;
}