#banner-designer-app.bd-modern {
    --bd-accent: #2271b1;
    --bd-accent-hover: #1a5a8f;
    --bd-border: #e2e2e6;
    --bd-bg-panel: #fafafa;
    --bd-radius: 10px;

    position: relative; /* positioned ancestor for #bd-guide-overlay — this IS the element requestFullscreen() targets (bindZoomAndFullscreen()), so its box stays the right frame of reference whether or not fullscreen is active */
    box-sizing: border-box;
    max-width: 1300px;
    height: 100vh;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    background: #fff;
    border: 1px solid var(--bd-border);
    border-radius: var(--bd-radius);
    overflow: hidden;
    box-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);
}


#banner-designer-app.bd-fullscreen {
    max-width: 100vw;
    width: 100vw;
    height: 100vh;
    border-radius: 0;
    display: flex;
    flex-direction: column;
}

#banner-designer-app.bd-fullscreen .bd-body {
    flex: 1;
}

/* ---------- Header ---------- */

.bd-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    padding: 8px 16px;
    background: #fff;
    border-bottom: 1px solid var(--bd-border);
    min-height: 48px;
    flex-wrap: wrap;
    row-gap: 8px;
}

.bd-header-left,
.bd-header-right {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}

.bd-header-right {
    flex-wrap: wrap;
    justify-content: flex-end;
}

.bd-language-selector {
    position: relative;
}

.bd-language-trigger {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    min-height: 32px;
    padding: 5px 8px;
    border: 1px solid var(--bd-border);
    border-radius: 5px;
    background: #fff;
    color: inherit;
    cursor: pointer;
    font: inherit;
}

.bd-language-globe {
    width: 17px;
    height: 17px;
}

.bd-language-abbreviation {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
}

.bd-language-list {
    position: absolute;
    z-index: 1000;
    top: calc(100% + 5px);
    right: 0;
    width: 220px;
    max-height: min(60vh, 420px);
    overflow-y: auto;
    padding: 4px;
    border: 1px solid var(--bd-border);
    border-radius: 6px;
    background: #fff;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .16);
}

.bd-language-option {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: 8px 10px;
    border: 0;
    border-radius: 4px;
    background: transparent;
    color: inherit;
    cursor: pointer;
    font: inherit;
    text-align: left;
}

.bd-language-option:hover,
.bd-language-option:focus-visible {
    background: #f1f5f9;
    outline: none;
}

.bd-language-option-check {
    color: #1769aa;
    font-weight: 700;
}

.bd-header-center {
    display: flex;
    align-items: center;
    flex: 1;
    justify-content: center;
    flex-wrap: wrap;
    row-gap: 8px;
    min-width: 280px;
}

.bd-toolbar-group {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    row-gap: 8px;
    justify-content: flex-start;
}

.bd-divider {
    width: 1px;
    height: 24px;
    background: var(--bd-border);
    margin: 0 3px;
}

/* Pen point-edit toolbar (#bd-toolbar-pen-edit in banner-designer.php) —
   Done is the ONLY way out of an interaction mode that otherwise leaves
   the object's normal resize/rotate handles hidden, so this can't afford
   to read as just another quiet toolbar row; it needs to be spotted on
   sight. Same amber "pay attention" language as the Shapes Manager's own
   size-mismatch warning (bd-shapes-admin.css .bd-shapes-size-compare-
   warning: #fff3e0 / #f0b429 / #7a4a00), reused for a consistent
   warning language even though that screen is wp-admin-only and this
   is front-end editor chrome — colors repeated as literal values
   rather than shared variables, since this stylesheet deliberately
   doesn't pull in bd-admin-design-system.css's own tokens (see .bd-btn-
   import's comment above for why: that system is scoped to #wpcontent
   admin screens and not meant to bleed in here). */
#bd-toolbar-pen-edit {
    background: #fff3e0;
    border: 1px solid #f0b429;
    border-radius: 8px;
    padding: 6px 10px;
    box-shadow: 0 1px 4px rgba(240, 180, 41, 0.35);
}

#bd-toolbar-pen-edit .bd-inline-label {
    color: #7a4a00;
    font-weight: 600;
}

/* Solid, same-hue as the banner it sits in — reads as "the action that
   resolves this attention state" rather than a generic secondary
   button (plain .bd-btn's white/bordered look was disappearing against
   this now much louder background). */
#bd-toolbar-pen-edit #bd-pen-edit-done {
    background: #f0b429;
    border: 1px solid #d99a00;
    color: #4a2e00;
    font-weight: 700;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
}

#bd-toolbar-pen-edit #bd-pen-edit-done:hover {
    background: #e0a91f;
}

.bd-icon-btn {
    width: 34px;
    height: 34px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid transparent;
    background: transparent;
    border-radius: 8px;
    cursor: pointer;
    color: #333;
    transition: background 0.15s;
}

.bd-icon-btn svg {
    width: 18px;
    height: 18px;
    fill: currentColor;
}

.bd-icon-btn:hover {
    background: #f0f0f0;
}

/* Delete icon button — turns red on hover for a clear "this removes
   something" affordance. Applied to .bd-icon-btn-delete (header toolbar
   and floating toolbar) and .bd-tool-btn#bd-tool-delete (sidebar). */
.bd-icon-btn-delete:hover,
.bd-tool-btn#bd-tool-delete:hover {
    color: #d32f2f;
}


.bd-icon-btn.bd-disabled {
    opacity: 0.35;
    pointer-events: none;
    cursor: default;
}

/* A valid multi-selection makes Group discoverable without becoming an
   authority: eligibility still comes exclusively from current Fabric state. */
@keyframes bd-group-available-pulse {
    0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(34, 113, 177, 0); }
    50% { transform: scale(1.035); box-shadow: 0 0 0 4px rgba(34, 113, 177, 0.16); }
}
.bd-icon-btn.bd-group-available-pulse {
    animation: bd-group-available-pulse 2.8s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
    .bd-icon-btn.bd-group-available-pulse { animation: none; }
}

@keyframes bd-focus-canvas-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(0, 115, 230, 0); }
    50% { box-shadow: 0 0 0 5px rgba(0, 115, 230, 0.22); }
}

#bd-focus-canvas-toggle[aria-pressed="true"] {
    color: #0073e6;
    background: #eaf4ff;
    border-color: #0073e6;
    animation: bd-focus-canvas-pulse 2.8s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
    #bd-focus-canvas-toggle[aria-pressed="true"] { animation: none; }
}
/* Keep the disabled appearance, but let Ungroup validate the live Fabric
   selection itself. Its action must not depend on a transient CSS state. */
#bd-ungroup-selection.bd-disabled { pointer-events: auto; }

/* Labeled pill button for a header action that deserves more visual
   weight than a bare .bd-icon-btn (currently only PSD import) but isn't
   the page's single primary CTA (.bd-btn-primary, reserved for Save
   Design & Add to Cart) — an outlined accent pill that fills solid on
   hover. Uses this editor's OWN --bd-accent (site-brand-tunable), not
   the separate wp-admin "2026" slate design system in
   bd-admin-design-system.css, which is deliberately scoped to
   #wpcontent-only admin screens and explicitly not meant to bleed into
   this front-end editor chrome (see that file's own header comment).
   Reuses banner-designer.js's existing btn.disabled/btn.title toggling
   in markSizeConfirmed() unchanged. */
.bd-btn-import {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    height: 34px;
    padding: 0 14px 0 10px;
    border: 1.5px solid var(--bd-accent);
    border-radius: 999px;
    background: #fff;
    color: var(--bd-accent);
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}

.bd-btn-import svg {
    width: 18px;
    height: 18px;
    fill: currentColor;
    flex-shrink: 0;
}

.bd-btn-import:hover:not(:disabled) {
    background: var(--bd-accent);
    color: #fff;
}

.bd-btn-import:disabled {
    border-color: var(--bd-border);
    color: #9aa0a6;
    opacity: 0.7;
    cursor: not-allowed;
}

.bd-unified-import-control { height: 48px; min-width: 190px; border-radius: 12px; gap: 9px; padding: 4px 12px; text-align: left; }
.bd-unified-import-control > svg { align-self: flex-start; margin-top: 4px; }
.bd-unified-import-copy { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.15; }
.bd-unified-import-primary { font-size: 13px; font-weight: 700; }
.bd-unified-import-formats { font-size: 10px; font-weight: 600; letter-spacing: .02em; opacity: .82; }
.bd-unified-import-description { font-size: 10px; font-weight: 400; opacity: .72; }

.bd-icon-btn.active,
.bd-icon-btn.bd-toggle.active {
    background: var(--bd-accent);
    color: #fff;
}

.bd-select {
    padding: 7px 10px;
    border: 1px solid var(--bd-border);
    border-radius: 8px;
    background: #fff;
    font-size: 13px;
    cursor: pointer;
}

.bd-select:disabled {
    background: #f5f5f5;
    color: #666;
    cursor: default;
}

.bd-font-picker {
    position: relative;
}

.bd-font-picker-trigger {
    min-width: 130px;
    max-width: 160px;
    text-align: left;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bd-font-picker-panel {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 1000;
    width: 280px;
    background: #fff;
    border: 1px solid var(--bd-border);
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(16, 24, 40, 0.16);
    padding: 10px;
}

.bd-font-picker-panel.open {
    display: block;
}

.bd-font-picker-panel .bd-searchlist-body {
    max-height: 260px;
}

.bd-stepper input {
    width: 52px;
    padding: 7px 6px;
    border: 1px solid var(--bd-border);
    border-radius: 8px;
    font-size: 13px;
    text-align: center;
}

.bd-mini-input {
    width: 42px;
    padding: 6px 4px;
    border: 1px solid var(--bd-border);
    border-radius: 8px;
    font-size: 13px;
    text-align: center;
}

.bd-inline-label {
    font-size: 13px;
    color: #666;
    margin-left: 2px;
    cursor: default;
}

.bd-slider {
    width: 90px;
}

.bd-value-tag {
    font-size: 12px;
    color: #666;
    min-width: 36px;
}

.bd-color-swatch-btn {
    width: 34px;
    height: 34px;
    border-radius: 8px;
    border: 1px solid var(--bd-border);
    background: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}

.bd-swatch {
    width: 20px;
    height: 20px;
    border-radius: 5px;
    border: 1px solid rgba(0, 0, 0, 0.15);
    display: block;
}

.bd-btn {
    padding: 8px 14px;
    border: 1px solid var(--bd-border);
    border-radius: 8px;
    background: #fff;
    font-size: 13px;
    cursor: pointer;
}

.bd-btn:hover {
    background: #f5f5f5;
}

.bd-btn-primary {
    padding: 10px 20px;
    border: none;
    border-radius: 8px;
    background: var(--bd-accent);
    color: #fff;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.15s;
}

.bd-btn-primary:hover {
    background: var(--bd-accent-hover);
}

.bd-btn-primary:disabled {
    background: #c2c8d0;
    color: #fff;
    cursor: not-allowed;
}
.bd-btn-primary:disabled:hover {
    background: #c2c8d0;
}

/* Dropdown (arrange menu) */

.bd-dropdown {
    position: relative;
}

.bd-dropdown-menu,
.bd-shape-menu {
    display: none;
    position: absolute;
    top: 40px;
    left: 0;
    background: #fff;
    border: 1px solid var(--bd-border);
    border-radius: 8px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
    z-index: 50;
    min-width: 170px;
    overflow: hidden;
}

.bd-dropdown-menu.open,
.bd-shape-menu.open {
    display: block;
}

.bd-dropdown-menu div,
.bd-shape-menu div {
    padding: 9px 14px;
    font-size: 13px;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 8px;
}

.bd-menu-icon {
    width: 16px;
    height: 16px;
    fill: #666;
    flex-shrink: 0;
}

.bd-dropdown-menu div:hover,
.bd-shape-menu div:hover {
    background: #f0f4f9;
}

.bd-tool-btn-wrap {
    position: relative;
}

.bd-shape-menu {
    top: auto;
    left: 60px;
    bottom: 0;
}

/* Applied by positionShapeMenu() in banner-designer.js when the default
   rightward-opening position would clip off the viewport's right edge —
   mirrors the same button-relative gap, opening leftward instead. */
.bd-shape-menu.bd-open-left {
    left: auto;
    right: 60px;
}

/* Now 10 items (was 3, pre Wave 1 shapes) — anchored bottom:0 (grows
   upward from the Shape button), so on a shorter viewport or a button
   positioned further down the sidebar this can otherwise run off the
   top of the screen. Scrolls internally instead of ever doing that. */
.bd-shape-menu {
    max-height: min(360px, calc(100vh - 80px));
    overflow-y: auto;
}

/* ---------- Body layout ---------- */

.bd-body {
    display: flex;
    flex: 1;
    min-height: 0;
    overflow: hidden;
}

.bd-layers-panel {
    box-sizing: border-box;
    width: 220px;
    padding: 16px;
    background: var(--bd-bg-panel);
    border-right: 1px solid var(--bd-border);
    overflow-y: auto;
    flex: 0 0 220px;
    transition: width 160ms ease, flex-basis 160ms ease, padding 160ms ease;
}

.bd-panel-heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.bd-panel-toggle,
.bd-page-panel-toggle {
    box-sizing: border-box;
    width: 28px;
    height: 28px;
    border: 1px solid var(--bd-border);
    border-radius: 6px;
    background: #fff;
    color: #555;
    cursor: pointer;
    flex: 0 0 auto;
}

.bd-panel-toggle::before,
.bd-page-panel-toggle::before {
    content: '‹';
    font-size: 20px;
    line-height: 1;
}

.bd-layers-panel h4 {
    margin: 0 0 10px;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: #888;
}

#bd-layers-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.bd-layer-item {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 7px 8px;
    margin-bottom: 4px;
    background: #fff;
    border: 1px solid var(--bd-border);
    border-radius: 7px;
    cursor: pointer;
    font-size: 12.5px;
    user-select: none;
}

.bd-layer-item:hover {
    background: #f0f4f9;
}

.bd-layer-item.active {
    background: var(--bd-accent);
    color: #fff;
    border-color: var(--bd-accent);
}

.bd-layer-item.dragging {
    opacity: 0.4;
}

.bd-layer-item.drag-over {
    border-top: 2px solid var(--bd-accent);
}

.bd-layer-drag {
    cursor: grab;
    color: #aaa;
    display: inline-flex;
    align-items: center;
}

.bd-layer-item.active .bd-layer-drag {
    color: #dce9f5;
}

.bd-layer-vis,
.bd-layer-lock {
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 3px;
    border-radius: 4px;
    color: #666;
}

.bd-layer-item.active .bd-layer-vis,
.bd-layer-item.active .bd-layer-lock {
    color: #fff;
}

.bd-layer-lock svg,
.bd-layer-drag svg {
    fill: currentColor;
    display: block;
}

.bd-layer-vis svg {
    /* eye icon keeps its own blue/gray fill (set inline per state) instead of currentColor */
    display: block;
}

.bd-layer-vis:hover,
.bd-layer-lock:hover {
    background: rgba(0, 0, 0, 0.1);
}

.bd-layer-type-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    opacity: 0.75;
}

.bd-layer-item.active .bd-layer-type-icon {
    opacity: 1;
}

.bd-layer-item.active .bd-layer-type-icon svg {
    fill: #dce9f5;
}

/* --- Imported Corel logical tree ---------------------------------------
   The tree is rendered INSIDE its imported root's layer row. That row can be
   the active selection (the imported root is auto-selected right after
   import), and .bd-layer-item.active sets color:#fff on the accent
   background. Without its own colours the nested tree inherited that white
   text and rendered white-on-white — the "blank/broken rows" the user saw
   until they selected another object. Marking the host row lets it render
   IDENTICALLY whether or not it is active, so the first render matches every
   later render through the one canonical path. */
.bd-corel-host,
.bd-corel-host.active {
    display: block;
    background: #fff;
    color: inherit;
    border-color: var(--bd-border);
    cursor: default;
}
.bd-corel-host.active .bd-layer-vis,
.bd-corel-host.active .bd-layer-lock {
    color: #666;
}
.bd-corel-root-label {
    font-weight: 600;
}
.bd-corel-root-twist {
    margin-right: 4px;
}
.bd-corel-twist {
    display: inline-block;
    width: 12px;
    text-align: center;
    color: #888;
    cursor: pointer;
}
.bd-corel-row-meta {
    color: #6b7785;
}

/* --- Corel import preparation overlay ----------------------------------
   One blocking overlay from upload through layer synchronisation so the
   canvas never shows a confusing blank/intermediate state. Upload shows real
   byte progress; backend/client stages are honest indeterminate steps. */
.bd-corel-progress {
    position: fixed;
    inset: 0;
    z-index: 100000;
    /* Visibility is driven by .is-open, NOT the [hidden] attribute: this
       author display rule would override a UA [hidden]{display:none}, so
       toggling `hidden` alone left the modal painted on top forever. */
    display: none;
    align-items: center;
    justify-content: center;
    background: rgba(15, 23, 33, 0.45);
}
.bd-corel-progress.is-open {
    display: flex;
}
.bd-corel-progress-card {
    width: min(560px, 90vw);
    height: 600px;
    box-sizing: border-box;
    position: relative;
    background: #fff;
    border-radius: 12px;
    padding: 22px 24px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
    font-family: system-ui, sans-serif;
    border: 1px solid rgba(255,255,255,.65);
}
.bd-corel-progress-title {
    font-size: 15px;
    font-weight: 700;
    color: #1d2b3a;
    margin-bottom: 4px;
    letter-spacing: .01em;
}
.bd-corel-progress-msg {
    font-size: 13px;
    color: #5a6b7b;
    margin-bottom: 14px;
    min-height: 18px;
}
.bd-corel-progress-body {
    display: flex;
    flex-direction: column;
    height: 478px;
    min-height: 478px;
}
.bd-import-stage-list {
    height: 220px;
    flex: 0 0 220px;
    margin: 8px 0 14px;
    border: 1px solid #dbe3ea;
    border-radius: 8px;
    overflow: hidden;
}
.bd-import-stage-row {
    display: grid;
    grid-template-columns: 24px 1fr minmax(0, 1fr);
    align-items: center;
    gap: 8px;
    height: 44px;
    box-sizing: border-box;
    padding: 0 12px;
    border-bottom: 1px solid #edf1f4;
    color: #71808e;
    font-size: 13px;
}
.bd-import-stage-row:last-child { border-bottom: 0; }
.bd-import-stage-icon { width: 20px; text-align: center; font-size: 15px; }
.bd-import-stage-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bd-import-stage-detail { min-width: 0; color: #7a8794; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: right; font-size: 11px; }
.bd-import-stage-row.is-active { color: #1d2b3a; font-weight: 650; background: #f5f9fc; }
.bd-import-stage-row.is-active .bd-import-stage-icon { color: var(--bd-accent, #2271b1); animation: bd-import-activity-pulse 1.3s ease-in-out infinite; }
.bd-import-stage-row.is-complete .bd-import-stage-icon { color: #258a52; }
.bd-import-stage-row.is-failed { color: #b3261e; background: #fff7f6; }
.bd-import-stage-row.is-failed .bd-import-stage-icon { color: #b3261e; }
.bd-import-current { height: 38px; flex: 0 0 38px; box-sizing: border-box; color: #526474; font-size: 13px; line-height: 20px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bd-import-elapsed { height: 24px; flex: 0 0 24px; color: #7a8794; font-size: 12px; line-height: 24px; text-align: right; }
.bd-import-elapsed::before { content: 'Elapsed '; }
.bd-import-details-toggle { align-self: flex-start; height: 30px; flex: 0 0 30px; padding: 0; border: 0; background: transparent; color: var(--bd-accent, #2271b1); cursor: pointer; font-size: 12px; }
.bd-import-details-log { height: 98px; flex: 0 0 98px; box-sizing: border-box; overflow: auto; padding: 6px 8px; border: 1px solid #dbe3ea; border-radius: 6px; background: #f8fafc; color: #617181; font: 10px/15px ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; }
.bd-import-detail-row { white-space: pre-wrap; overflow-wrap: anywhere; }
@keyframes bd-import-activity-pulse { 0%, 100% { opacity: .45; } 50% { opacity: 1; } }
.bd-corel-progress-track {
    height: 8px;
    background: #e7edf3;
    border-radius: 999px;
    overflow: hidden;
}
.bd-corel-progress-bar {
    height: 100%;
    width: 0;
    background: var(--bd-accent, #2271b1);
    border-radius: 999px;
    transition: width 0.18s ease;
}
.bd-corel-progress-pct {
    font-size: 12px;
    color: #7a8794;
    margin-top: 8px;
    text-align: right;
    min-height: 16px;
}
.bd-corel-progress.is-indeterminate .bd-corel-progress-bar {
    width: 40% !important;
    animation: bd-corel-indeterminate 1.1s ease-in-out infinite;
}
@keyframes bd-corel-indeterminate {
    0% { margin-left: -40%; }
    100% { margin-left: 100%; }
}
/* Terminal error state: clear message + Retry/Close, never an indefinite modal. */
.bd-corel-progress-errmsg {
    font-size: 13px;
    color: #b3261e;
    margin-bottom: 14px;
}
.bd-corel-progress-card > .bd-corel-btn { position: absolute; left: 24px; bottom: 18px; }
.bd-corel-progress-error { position: absolute; left: 24px; right: 24px; bottom: 12px; min-height: 42px; box-sizing: border-box; background: #fff; }
.bd-import-queue { flex: 0 0 auto; height: auto; min-height: 0; max-height: 112px; box-sizing: border-box; margin-top: 4px; margin-bottom: 8px; padding: 8px 0; border-top: 1px solid var(--bd-border); border-bottom: 1px solid var(--bd-border); overflow-y: auto; text-align: left; }
.bd-import-queue-title { font-size: 12px; font-weight: 700; margin-bottom: 6px; }
.bd-import-queue-row { display: grid; grid-template-columns: 18px minmax(0, 1fr) auto; gap: 6px; align-items: center; padding: 3px 0; font-size: 12px; }
.bd-import-queue-row span:nth-child(2) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bd-import-queue-row.is-complete { color: #18794e; }
.bd-import-queue-row.is-failed { color: #b42318; }
.bd-import-queue-row.is-active { color: var(--bd-accent); font-weight: 600; }
.bd-import-queue-row.is-cancelled { color: #8a5a00; }
.bd-corel-progress-actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
}
.bd-corel-btn {
    font-size: 13px;
    padding: 7px 14px;
    border-radius: 7px;
    border: 1px solid var(--bd-border);
    background: #fff;
    color: #1d2b3a;
    cursor: pointer;
}
.bd-corel-btn-primary {
    background: var(--bd-accent, #2271b1);
    border-color: var(--bd-accent, #2271b1);
    color: #fff;
}

/* Ungroup affordance — a finite, subtle attention pulse (5 cycles, 15s),
   armed only when a group becomes selected. Never a continuous flash. */
.bd-ungroup-attention {
    animation: bd-ungroup-pulse 3s ease-in-out 5;
}
@keyframes bd-ungroup-pulse {
    0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(34, 113, 177, 0); }
    50% { transform: scale(1.14); box-shadow: 0 0 0 4px rgba(34, 113, 177, 0.35); }
}
@media (prefers-reduced-motion: reduce) {
    .bd-ungroup-attention { animation: none; outline: 2px solid rgba(34, 113, 177, 0.75); outline-offset: 2px; }
}

.bd-layer-name {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bd-layer-rename-input {
    box-sizing: border-box;
    flex: 1 1 auto;
    min-width: 0;
    width: 100%;
    padding: 1px 4px;
    border: 1px solid var(--bd-accent, #2271b1);
    border-radius: 3px;
    font: inherit;
    color: #1f2937;
    -webkit-text-fill-color: #1f2937;
    caret-color: #1f2937;
    background: #fff;
    user-select: text;
}
.bd-layer-origin {
    flex: 0 0 auto;
    width: 8px;
    height: 8px;
    margin: 0;
    border-radius: 50%;
    box-shadow: 0 0 0 1px rgba(0,0,0,.18);
}

.bd-layer-background {
    margin-top: 10px;
    border-top: 1px dashed var(--bd-border);
    padding-top: 10px;
    cursor: pointer;
}

.bd-layer-remove-bg {
    cursor: pointer;
    font-size: 12px;
    color: #999;
    padding: 2px 4px;
}

.bd-layer-remove-bg:hover {
    color: #d32f2f;
}

/* Canvas area with rulers */

.bd-canvas-area {
    position: relative;
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    background: #ececec;
    min-width: 0;
}

.bd-ruler-row {
    display: flex;
    height: 24px;
    flex-shrink: 0;
}

.bd-ruler-corner {
    width: 24px;
    height: 24px;
    background: #f5f5f5;
    border-right: 1px solid var(--bd-border);
    border-bottom: 1px solid var(--bd-border);
    flex-shrink: 0;
}

.bd-ruler-h-wrap {
    flex: 1;
    background: #f5f5f5;
    border-bottom: 1px solid var(--bd-border);
    overflow: hidden;
}

.bd-canvas-row {
    display: flex;
    flex: 1;
    min-height: 0;
}

.bd-ruler-v-wrap {
    width: 24px;
    background: #f5f5f5;
    border-right: 1px solid var(--bd-border);
    flex-shrink: 0;
    overflow: hidden;
    position: relative;
}

/* drawRulers() (banner-designer.js) sets this canvas's width/height
   ATTRIBUTES every time it redraws, to match .bd-canvas-scroll's current
   clientHeight for a crisp 1:1 pixel buffer. Left in normal flow, an
   in-flow <canvas> is sized from those same attributes by default, which
   fed that value straight back into .bd-ruler-v-wrap's own intrinsic
   height -- and since .bd-canvas-row stretches (default align-items) to
   its tallest child, that inflated height became the NEXT redraw's
   clientHeight reading, compounding without bound on every page switch.
   position:absolute + inset:0 removes the canvas from flow entirely, so
   it can no longer feed its own attribute size back into the parent's
   layout -- it just fills whatever height .bd-ruler-v-wrap is stretched
   to from .bd-canvas-scroll's real (now stable) content size. The pixel
   buffer (width/height attributes, set in JS) and the CSS display size
   (100% of the wrap here) end up equal once layout is stable, so the
   ruler still renders crisp, not stretched/blurred.
   cursor: ns-resize/ew-resize below (both rulers) hints the drag-a-
   guide-out gesture — a ruler always produces a guide PERPENDICULAR to
   itself, dragged along its own axis (horizontal ruler -> vertical
   guide, dragged left/right; vertical ruler -> horizontal guide, dragged
   up/down) — see bindRulerGuideCreation(). */
#bd-ruler-v {
    display: block;
    position: absolute;
    inset: 0;
    cursor: ns-resize;
}
#bd-ruler-h {
    cursor: ew-resize;
}

.bd-guide-distance-label {
    position: absolute;
    display: none;
    background: rgba(0, 188, 212, 0.92);
    color: #fff;
    padding: 3px 8px;
    border-radius: 4px;
    font-size: 11px;
    font-family: monospace;
    pointer-events: none;
    z-index: 46;
    white-space: nowrap;
}

/* Guide lines themselves — a standalone overlay covering the full
   #bd-canvas-scroll viewport (see drawRulerGuides()/
   getOrCreateGuideOverlayCanvas()), so a guide visually runs the whole
   way across the work area (print area + surrounding pasteboard) rather
   than stopping at the print area's own edge.
   position:absolute (not fixed) relative to #banner-designer-app — that
   element is what requestFullscreen() actually targets
   (bindZoomAndFullscreen()), and a position:fixed descendant of a
   fullscreened non-root element is a well-known cross-browser gray area
   (some browsers re-anchor "fixed" to the fullscreen element instead of
   the viewport once it's fullscreen, some don't) — position:absolute
   against an explicit positioned ancestor sidesteps that ambiguity
   entirely rather than depending on it working out. This overlay is
   also appended as a CHILD of #banner-designer-app itself (see
   getOrCreateGuideOverlayCanvas()), not document.body — content outside
   the fullscreen element's own subtree isn't painted at all while it's
   fullscreen, which was the actual cause of guides disappearing there. */
#bd-guide-overlay {
    position: absolute;
    pointer-events: none;
    z-index: 40;
}

.bd-canvas-scroll {
    flex: 1;
    overflow: auto;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 24px;
}

.bd-canvas-wrap {
    position: relative;
    box-shadow: 0 2px 16px rgba(0, 0, 0, 0.18);
    background: #fff;
    flex-shrink: 0;
}

.bd-soft-proof-v2-overlay {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    display: none;
    pointer-events: none;
    z-index: 4;
}

.bd-guide {
    position: absolute;
    pointer-events: none;
    box-sizing: border-box;
}

.bd-grid-overlay {
    position: absolute;
    left: 0;
    top: 0;
    pointer-events: none;
    box-sizing: border-box;
    z-index: 5;
}

/* Stage 3 Phase B2 — covers the WHOLE .bd-canvas-wrap (not JS-sized
   like .bd-grid-overlay above, which tracks zoom/pan for the printable
   area specifically) since it needs to block interaction with the
   canvas element itself regardless of current zoom. Inert (no pointer-
   events, invisible) until .locked is toggled on by
   setCanvasInteractionLocked(). Above the canvas AND the grid overlay,
   below the floating toolbar/HUDs (those only ever show for the
   controller's own selection, which can't exist while locked anyway). */
.bd-live-canvas-lock-overlay {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 6;
    cursor: default;
    border: 3px solid transparent;
    transition: border-color 0.3s, background 0.3s;
}

.bd-live-canvas-lock-overlay.locked {
    pointer-events: auto;
    cursor: not-allowed;
    border-color: #e8622c;
    background: rgba(232, 98, 44, 0.04);
    animation: bd-lock-pulse 2s ease-in-out infinite;
}

@keyframes bd-lock-pulse {
    0%, 100% { border-color: #e8622c; box-shadow: 0 0 0 0 rgba(232, 98, 44, 0.4); }
    50% { border-color: #c0392b; box-shadow: 0 0 0 8px rgba(232, 98, 44, 0); }
}

.bd-live-canvas-lock-icon {
    font-size: 16px;
}

.bd-guide-finished {
    border: 2px solid #2196f3;
    border-radius: 6px;
}

.bd-guide-bleed {
    border: 1.5px dashed #e11d2a;
    pointer-events: none;
    z-index: 3;
}

.bd-guide-safe {
    border: 2px dashed #43a047;
}

.bd-canvas-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 16px;
    background: #f5f5f5;
    border-top: 1px solid var(--bd-border);
    flex-shrink: 0;
}

.bd-camera-chrome {
    position: static;
    z-index: auto;
    display: flex;
    align-items: center;
    flex: 0 0 auto;
    box-sizing: border-box;
    min-width: 0;
    max-width: 100%;
    margin-left: auto;
    padding: 2px 4px;
    background: #fafafa;
    border: 1px solid var(--bd-border);
    border-radius: 8px;
}

.bd-soft-proof-v2-status {
    max-width: 320px;
    color: #334155;
    font-size: 11px;
    line-height: 1.3;
    text-align: center;
}

.bd-soft-proof-v2-status.is-error {
    color: #991b1b;
}

.bd-page-strip {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 16px;
    background: #f5f5f5;
    border-top: 1px solid var(--bd-border);
    flex-shrink: 0;
    overflow: hidden;
    min-height: 84px;
    transition: min-height 160ms ease, padding 160ms ease;
}

.bd-page-strip-status {
    display: none;
    flex: 0 0 auto;
    font-size: 11px;
    color: #555;
    white-space: nowrap;
}

.bd-page-strip-content {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 1 1 0;
    min-width: 0;
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scrollbar-width: thin;
}

.bd-camera-chrome .bd-zoom-controls {
    flex-wrap: nowrap;
    max-width: none;
    white-space: nowrap;
}

.bd-layers-panel.bd-panel-collapsed {
    width: 40px;
    flex-basis: 40px;
    padding: 8px 6px;
    overflow: hidden;
}

.bd-layers-panel.bd-panel-collapsed .bd-panel-heading {
    flex-direction: column;
}

.bd-layers-panel.bd-panel-collapsed h4 {
    writing-mode: vertical-rl;
    margin: 0;
}

.bd-layers-panel.bd-panel-collapsed #bd-layers-list {
    display: none;
}

.bd-layers-panel.bd-panel-collapsed .bd-panel-toggle::before,
.bd-page-strip.bd-panel-collapsed .bd-page-panel-toggle::before {
    content: '›';
}

.bd-page-strip.bd-panel-collapsed {
    min-height: 36px;
    height: 36px;
    padding: 0 10px;
}

.bd-page-strip.bd-panel-collapsed .bd-page-strip-status {
    display: block;
}

.bd-page-strip.bd-panel-collapsed .bd-page-strip-content {
    flex: 1 1 auto;
    overflow: hidden;
}

.bd-page-strip.bd-panel-collapsed .bd-camera-chrome {
    padding: 0;
    background: transparent;
    border-color: transparent;
    border-radius: 0;
}

.bd-page-strip.bd-panel-collapsed .bd-page-thumb:not(.active),
.bd-page-strip.bd-panel-collapsed .bd-page-copy-side {
    display: none;
}

.bd-page-strip.bd-panel-collapsed .bd-page-thumb-add {
    width: 28px;
    height: 28px;
    padding: 0;
    flex: 0 0 auto;
}

.bd-page-strip.bd-panel-collapsed .bd-page-thumb.active {
    width: auto;
}

.bd-page-strip.bd-panel-collapsed .bd-page-thumb.active .bd-page-thumb-img {
    display: none;
}

#banner-designer-app.bd-focus-canvas .bd-layers-panel {
    display: none !important;
}

#banner-designer-app.bd-focus-canvas .bd-page-strip {
    justify-content: flex-end;
}

#banner-designer-app.bd-focus-canvas .bd-page-strip .bd-page-panel-toggle,
#banner-designer-app.bd-focus-canvas .bd-page-strip .bd-page-strip-status,
#banner-designer-app.bd-focus-canvas .bd-page-strip .bd-page-strip-content {
    display: none;
}

@media (max-width: 760px) {
    .bd-page-strip {
        flex-wrap: wrap;
        row-gap: 4px;
        padding-block: 6px;
    }

    .bd-page-strip .bd-page-strip-content {
        order: 1;
        flex: 1 1 calc(100% - 40px);
    }

    .bd-page-strip .bd-camera-chrome {
        order: 2;
        flex: 1 0 100%;
        justify-content: flex-end;
    }

    .bd-camera-chrome .bd-zoom-controls {
        flex-wrap: wrap;
        justify-content: flex-end;
    }

    .bd-page-strip.bd-panel-collapsed {
        height: auto;
        min-height: 36px;
    }
}

.bd-page-thumb {
    position: relative;
    flex: none;
    width: 64px;
    cursor: pointer;
}

.bd-page-thumb-img {
    width: 64px;
    height: 64px;
    border: 2px solid var(--bd-border);
    border-radius: 6px;
    background: #fff;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}

.bd-page-thumb.active .bd-page-thumb-img {
    border-color: var(--bd-accent);
    box-shadow: 0 0 0 2px rgba(34, 113, 177, 0.2);
}

.bd-page-thumb-img img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}

.bd-page-thumb-label {
    display: block;
    text-align: center;
    font-size: 11px;
    color: #555;
    margin-top: 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.bd-page-thumb-actions {
    position: absolute;
    top: -8px;
    right: -8px;
    display: none;
    gap: 4px;
}

.bd-page-thumb:hover .bd-page-thumb-actions {
    display: flex;
}

.bd-page-thumb-dup,
.bd-page-thumb-del {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: 1px solid var(--bd-border);
    background: #fff;
    font-size: 11px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
}

.bd-page-thumb-del {
    color: #c62828;
}

.bd-page-thumb-add {
    flex: none;
    width: 64px;
    height: 64px;
    border: 2px dashed var(--bd-border);
    border-radius: 6px;
    background: #fff;
    color: #999;
    font-size: 22px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.bd-page-thumb-add:hover {
    border-color: var(--bd-accent);
    color: var(--bd-accent);
}

.bd-page-copy-side {
    flex: none;
    align-self: center;
    margin-left: 8px;
    padding: 6px 12px;
    border: 1px solid var(--bd-border);
    border-radius: 6px;
    background: #fff;
    color: #444;
    font-size: 12.5px;
    white-space: nowrap;
    cursor: pointer;
}

.bd-page-copy-side:hover {
    border-color: var(--bd-accent);
    color: var(--bd-accent);
}

.bd-legend {
    display: flex;
    gap: 16px;
    font-size: 12px;
    color: #555;
}

.bd-legend span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.bd-legend-swatch {
    width: 12px;
    height: 12px;
    border-radius: 3px;
    display: inline-block;
}

.bd-legend-finished {
    background: #2196f3;
}

.bd-legend-safe {
    background: #43a047;
}

.bd-zoom-controls {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    min-width: 0;
    max-width: 100%;
    gap: 6px;
    font-size: 12px;
    color: #555;
}

.bd-canvas-scroll:has(.bd-camera-panning),
.bd-canvas-scroll:has(.bd-camera-panning) .upper-canvas {
    cursor: grabbing;
}

/* Right sidebar tools */

.bd-tools-sidebar {
    width: 84px;
    padding: 14px 8px;
    background: var(--bd-bg-panel);
    border-left: 1px solid var(--bd-border);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    overflow-y: auto;
    container-type: size;
}

.bd-tool-btn {
    width: 100%;
    display: flex;
    flex: 0 0 auto;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 10px 4px;
    border: 1px solid transparent;
    background: transparent;
    border-radius: 8px;
    cursor: pointer;
    color: #444;
}

@container (max-height: 760px) {
    .bd-tools-sidebar {
        gap: 4px;
        padding-block: 10px;
    }

    .bd-tool-btn {
        gap: 2px;
        padding-block: 7px;
    }
}

@container (max-height: 580px) {
    .bd-tools-sidebar {
        gap: 2px;
        padding-block: 6px;
    }

    .bd-tool-btn {
        min-height: 44px;
        gap: 1px;
        padding-block: 3px;
    }

    .bd-tool-btn span {
        line-height: 11px;
    }
}

/* Stage 3 Phase B2 — real disabled attribute (see
   setCanvasInteractionLocked() in bd-live-help.js), not just a visual
   dim: buttons don't fire click at all while disabled, same native
   behavior that already blocks direct canvas interaction via the lock
   overlay's pointer-events. Without this, Add Text/Add Image etc. kept
   working for the locked-out side — creating objects that could never
   sync (sendLiveCanvasUpdate() itself already refuses to send unless
   liveIsController), silently diverging from what the controller sees. */
.bd-tool-btn:disabled {
    opacity: 0.35;
    cursor: not-allowed;
}

.bd-tool-btn svg {
    width: 22px;
    height: 22px;
    fill: currentColor;
}

.bd-tool-btn span {
    font-size: 10.5px;
}

.bd-tool-btn:hover {
    background: #eef2f7;
    color: var(--bd-accent);
}

.bd-tool-btn#bd-tool-shelf.active {
    background: var(--bd-accent);
    color: #fff;
}

/* Current-design font notifications are editor chrome, never Fabric/document
   geometry. The notice is fixed to the visible viewport and the drawer is a
   bounded sibling panel, so neither can change camera fit or page coordinates. */
#bd-tool-notifications { position: relative; }
.bd-notifications-badge {
    position: absolute; top: 2px; right: 3px; min-width: 15px; height: 15px;
    padding: 0 3px; border-radius: 8px; background: #d63638; color: #fff;
    font-size: 9px; line-height: 15px; text-align: center;
}
@keyframes bd-notifications-pulse {
    0%, 100% { transform: scale(1); }
    25%, 75% { transform: scale(1.12); box-shadow: 0 0 0 4px rgba(214,54,56,.18); }
    50% { transform: scale(1); box-shadow: none; }
}
.bd-notifications-pulse { animation: bd-notifications-pulse .8s ease-in-out 2; }
.bd-notifications-panel {
    position: absolute; right: 52px; top: 50%; z-index: 30; width: 300px;
    max-height: min(70vh, 480px); overflow: auto; padding: 14px;
    background: #fff; border: 1px solid var(--bd-border); border-radius: 8px;
    box-shadow: 0 8px 28px rgba(0,0,0,.16);
}
.bd-notifications-header { display:flex; align-items:center; justify-content:space-between; }
.bd-notifications-header h4 { margin: 0; }
.bd-notification-card { margin-top: 10px; padding: 10px; background: #f6f8fb; border-radius: 6px; }
.bd-notification-card p, .bd-font-substitution-notice p { margin: 6px 0; font-size: 12px; color: #50575e; }
.bd-notification-link { border: 0; padding: 0; background: none; color: var(--bd-accent); cursor: pointer; font-size: 12px; }
.bd-notification-card ul, .bd-font-substitution-notice ul { margin: 8px 0 0; padding-left: 18px; font-size: 12px; }
.bd-font-substitution-notice {
    position: fixed; left: 50%; top: 50%; z-index: 40; width: min(420px, calc(100vw - 40px));
    transform: translate(-50%, -50%); padding: 20px; background: #fff;
    border: 1px solid var(--bd-border); border-radius: 10px; box-shadow: 0 12px 36px rgba(0,0,0,.2);
}
.bd-font-substitution-dismiss { position:absolute; right:8px; top:6px; border:0; background:none; font-size:22px; cursor:pointer; color:#50575e; }
.bd-font-substitution-notice small { display:block; margin-top:12px; color:#6b7280; font-size:11px; }
@keyframes bd-font-notice-fly {
    to { opacity: 0; transform: translate(calc(50vw - 170px), calc(-50vh + 20px)) scale(.18); }
}
.bd-font-notice-flying { animation: bd-font-notice-fly .35s ease-in forwards; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .bd-notifications-pulse { animation: none; } }

/* ---------- Handle stack — the shared visual pill wrapping the Shelf
   handle and (when this product has any) the Templates handle above it.
   The two are fully independent controls (own click handler, own panel,
   own open/closed state — bindShelfPanel()/bindTemplatesPanel() in
   banner-designer.js never reference each other) that are only combined
   VISUALLY here, so they read as one narrow column split into sections
   rather than two separate tabs with a gap between them. This wrapper
   (not the individual handle buttons any more) owns the tinted
   background/border/rounded-corner shape and the align-self centering.
   Deliberately NOT overflow: hidden — each handle's own -arrow element
   pokes out past the LEFT edge via position:absolute + a negative left
   offset (unchanged, same mechanic as before this wrapper existed; see
   .bd-shelf-handle-arrow/.bd-templates-handle-arrow below), and hiding
   overflow here would clip that arrow clean off. It's not actually
   needed for the rounded-corner look either: both child buttons are
   transparent (background: none), so the wrapper's own rounded
   background already shows through their corners without clipping
   anything. */
.bd-handle-stack {
    flex: none;
    align-self: center;
    display: flex;
    flex-direction: column;
    background: #eaf2fa;
    border: 1px solid var(--bd-accent);
    border-radius: 6px 0 0 6px;
}

/* Divider between sections — keyed off DOM position (":not(:first-child)"),
   not a fixed count, so Shelf alone (no Templates for this product, see
   banner-designer.php's own conditional there) still renders as one
   clean, undivided section exactly as it did before Templates existed. */
.bd-handle-stack > *:not(:first-child) {
    border-top: 1px solid var(--bd-accent);
}

/* ---------- Shelf drawer handle — always visible regardless of panel
   state, a dedicated toggle separate from "Send to Shelf" (#bd-send-to-
   shelf sends a specific object; this only opens/closes the panel view).
   The chevron flips via .open (toggled in lockstep with .bd-shelf-panel
   .open by bindShelfPanel()'s setOpen()). ---------- */
.bd-shelf-handle {
    position: relative; /* anchors .bd-shelf-handle-arrow, which pokes out past this box's own left edge */
    width: 24px;
    padding: 14px 5px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--bd-accent);
    transition: background 0.15s ease;
}

.bd-shelf-handle:hover {
    background: rgba(34, 113, 177, 0.08);
}

.bd-shelf-handle-label {
    /* vertical-rl flows text top-to-bottom; the 180deg flip makes it
       read bottom-to-top instead, matching the reference screenshot. */
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 1px;
    text-transform: uppercase;
    white-space: nowrap;
}

/* The arrow is a visually separate "tab" that overlaps past the handle's
   own left edge (position: relative on the parent + overflow: visible,
   the default) so it reads as its own clickable affordance rather than a
   decorative icon inside one long strip — while still being a descendant
   of the same <button>, so clicking it (or hovering it) is exactly as
   valid as clicking anywhere else on the handle; no separate listener or
   nested <button> needed. */
.bd-shelf-handle-arrow {
    position: absolute;
    top: 50%;
    left: -14px;
    transform: translateY(-50%);
    width: 18px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #fff;
    border: 1px solid var(--bd-accent);
    border-right: none;
    border-radius: 6px 0 0 6px;
    box-shadow: -1px 0 3px rgba(0, 0, 0, 0.08);
    color: var(--bd-accent);
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease;
    z-index: 2;
}

.bd-shelf-handle-arrow:hover {
    background: var(--bd-accent);
    color: #fff;
    transform: translateY(-50%) scale(1.1);
}

.bd-shelf-handle-arrow svg {
    width: 12px;
    height: 12px;
    display: block;
    transition: transform 0.18s ease;
}

/* Closed -> ‹ (pull the panel in), open -> › (push it back out) — same
   direction logic as before the arrow moved into its own element, just
   re-scoped one level deeper. */
.bd-shelf-handle.open .bd-shelf-handle-arrow svg {
    transform: rotate(180deg);
}

/* One-time attention nudge on first load only — bindShelfPanel() gates
   this behind a localStorage flag so returning visitors never see it
   again. Plays after the panel/canvas have settled (0.6s delay) so it
   doesn't compete with the rest of the editor's own load. */
@keyframes bd-shelf-handle-attention {
    0%, 100% { transform: translateX(0); box-shadow: none; }
    20% { transform: translateX(-5px); box-shadow: -3px 0 8px rgba(34, 113, 177, 0.35); }
    40% { transform: translateX(0); box-shadow: none; }
    60% { transform: translateX(-4px); box-shadow: -3px 0 8px rgba(34, 113, 177, 0.35); }
    80% { transform: translateX(0); box-shadow: none; }
}

.bd-shelf-handle.bd-attention {
    animation: bd-shelf-handle-attention 1.1s ease-in-out 0.6s 1;
}

/* ---------- Shelf panel — slide-out, collapsed (width:0) by default so
   it never competes with canvas space when unused. A flex sibling of
   .bd-tools-sidebar (rightmost), not an overlay — the canvas area
   shrinks to make room while it's open, same as .bd-layers-panel
   already does on the left. ---------- */
.bd-shelf-panel {
    width: 0;
    overflow: hidden;
    background: var(--bd-bg-panel);
    border-left: 1px solid var(--bd-border);
    transition: width 0.18s ease;
    flex: none;
}

.bd-shelf-panel.open {
    width: 232px;
}

.bd-shelf-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 14px 0;
    white-space: nowrap;
}

.bd-shelf-header h4 {
    margin: 0;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: #888;
}

.bd-shelf-hint {
    margin: 8px 14px 12px;
    font-size: 11.5px;
    line-height: 1.5;
    color: #8a93a6;
    white-space: normal;
    width: 200px;
}

.bd-shelf-items {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    padding: 0 14px 14px;
    overflow-y: auto;
}

.bd-shelf-item {
    position: relative;
    border: 1px solid var(--bd-border);
    border-radius: 8px;
    background: #fff;
    padding: 6px;
    cursor: grab;
    text-align: center;
    user-select: none;
}

.bd-shelf-item:hover {
    border-color: var(--bd-accent);
}

.bd-shelf-item.dragging {
    opacity: 0.4;
}

.bd-shelf-item img {
    display: block;
    width: 100%;
    height: 72px;
    object-fit: contain;
    /* Faint checkerboard so a transparent-background thumbnail (almost
       every shelved object — see shelveObject()'s toDataURL() call) is
       visibly distinct from the panel's own white background. */
    background-image:
        linear-gradient(45deg, #eee 25%, transparent 25%), linear-gradient(-45deg, #eee 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, #eee 75%), linear-gradient(-45deg, transparent 75%, #eee 75%);
    background-size: 10px 10px;
    background-position: 0 0, 0 5px, 5px -5px, -5px 0px;
    border-radius: 4px;
    margin-bottom: 4px;
    pointer-events: none; /* let the click/drag land on the card itself, not the image */
}

.bd-shelf-item-name {
    font-size: 10.5px;
    color: #667085;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: none;
}

.bd-shelf-item-delete {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 18px;
    height: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.92);
    border: 1px solid var(--bd-border);
    border-radius: 50%;
    cursor: pointer;
    color: #a33;
    font-size: 12px;
    line-height: 1;
    opacity: 0;
    transition: opacity 0.12s ease;
}

.bd-shelf-item:hover .bd-shelf-item-delete {
    opacity: 1;
}

/* Explicit, single-click restore — the guaranteed-reliable path back to
   the canvas alongside drag-to-canvas and double-click; see
   bindShelfPanel() in banner-designer.js. */
.bd-shelf-item-restore {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 18px;
    height: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.92);
    border: 1px solid var(--bd-border);
    border-radius: 50%;
    cursor: pointer;
    color: var(--bd-accent);
    font-size: 11px;
    line-height: 1;
    opacity: 0;
    transition: opacity 0.12s ease;
}

.bd-shelf-item:hover .bd-shelf-item-restore {
    opacity: 1;
}

.bd-shelf-empty {
    display: none;
    margin: 0 14px 14px;
    padding: 20px 10px;
    text-align: center;
    font-size: 12px;
    color: #b0b7c3;
    border: 1px dashed var(--bd-border);
    border-radius: 8px;
}

.bd-shelf-panel.is-empty .bd-shelf-empty {
    display: block;
}

/* ---------- Templates panel — a second, separate drawer from Shelf
   above (own handle, own state, never conflated with it — see the
   .bd-handle-stack comment further up for how the two handles share one
   visual pill while staying functionally independent), same width-
   transition slide-out shape, only ever emitted server-side when
   templates actually exist for this size (see render_iframe_document()'s
   own comment on $templates_panel_templates). ---------- */
.bd-templates-handle {
    position: relative;
    width: 24px;
    padding: 14px 5px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--bd-accent);
    transition: background 0.15s ease;
}

.bd-templates-handle:hover {
    background: rgba(34, 113, 177, 0.08);
}

.bd-templates-handle-label {
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 1px;
    text-transform: uppercase;
    white-space: nowrap;
}

.bd-templates-handle-arrow {
    position: absolute;
    top: 50%;
    left: -14px;
    transform: translateY(-50%);
    width: 18px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #fff;
    border: 1px solid var(--bd-accent);
    border-right: none;
    border-radius: 6px 0 0 6px;
    box-shadow: -1px 0 3px rgba(0, 0, 0, 0.08);
    color: var(--bd-accent);
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease;
    z-index: 2;
}

.bd-templates-handle-arrow:hover {
    background: var(--bd-accent);
    color: #fff;
    transform: translateY(-50%) scale(1.1);
}

.bd-templates-handle-arrow svg {
    width: 12px;
    height: 12px;
    display: block;
    transition: transform 0.18s ease;
}

.bd-templates-handle.open .bd-templates-handle-arrow svg {
    transform: rotate(180deg);
}

/* ---------- Live Design Help handle (Stage 3 Phase B1) — same shape/
   mechanics as the other drawer handles above, own class so its
   click/state stay fully independent. ---------- */
.bd-live-help-handle {
    position: relative;
    width: 24px;
    padding: 14px 5px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--bd-accent);
    transition: background 0.15s ease;
}

.bd-live-help-handle:hover {
    background: rgba(34, 113, 177, 0.08);
}

/* One-time attention pulse — see #bd-live-help-pulse-dot's own comment
   in banner-designer.php for why this only ever renders on the
   customer entry point, and showLiveHelpHint() in banner-designer.js
   for the localStorage-gated one-time show + dismiss-on-click-or-
   timeout logic (same "once, ever" pattern as BD_PEN_HINT_SEEN_KEY).
   Soft "radar ping" style — expanding, fading ring — deliberately
   gentle, same non-jarring intent as the connecting-dots animation
   above (.bd-live-help-connecting-dots). */
.bd-live-help-pulse-dot {
    position: absolute;
    top: 6px;
    right: 3px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: #e74c3c;
    animation: bd-live-help-pulse 1.8s ease-in-out infinite;
}

@keyframes bd-live-help-pulse {
    0% { transform: scale(0.85); box-shadow: 0 0 0 0 rgba(231, 76, 60, 0.5); }
    70% { transform: scale(1.05); box-shadow: 0 0 0 6px rgba(231, 76, 60, 0); }
    100% { transform: scale(0.85); box-shadow: 0 0 0 0 rgba(231, 76, 60, 0); }
}

.bd-live-help-handle-label {
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 1px;
    text-transform: uppercase;
    white-space: nowrap;
}

.bd-live-help-handle-arrow {
    position: absolute;
    top: 50%;
    left: -14px;
    transform: translateY(-50%);
    width: 18px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #fff;
    border: 1px solid var(--bd-accent);
    border-right: none;
    border-radius: 6px 0 0 6px;
    box-shadow: -1px 0 3px rgba(0, 0, 0, 0.08);
    color: var(--bd-accent);
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease;
    z-index: 2;
}

.bd-live-help-handle-arrow:hover {
    background: var(--bd-accent);
    color: #fff;
    transform: translateY(-50%) scale(1.1);
}

.bd-live-help-handle-arrow svg {
    width: 12px;
    height: 12px;
    display: block;
    transition: transform 0.18s ease;
}

.bd-live-help-handle.open .bd-live-help-handle-arrow svg {
    transform: rotate(180deg);
}

/* ---------- "Invite Designer" button in the header (right side, under
   the canvas size selector) — same accent colour as the Live Help handle
   but styled as a compact inline button, not a vertical tab. ---------- */
.bd-invite-designer-wrap {
    display: flex;
    justify-content: flex-end;
    width: 100%;
    margin-top: 6px;
}

.bd-invite-designer-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 10px;
    background: var(--bd-accent);
    color: #fff;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.3px;
    white-space: nowrap;
    transition: background 0.15s ease, transform 0.1s ease;
}
.bd-invite-designer-btn:hover {
    background: var(--bd-accent-hover, #1a5a8a);
}
.bd-invite-designer-btn:active {
    transform: scale(0.97);
}
.bd-invite-designer-btn svg {
    flex: none;
}

/* Phase D1 — pulse animation on the Invite Designer button to signal
   designer availability at a glance. Green pulse = at least one designer
   is online right now; amber pulse = no one is online, but the button
   is still there to invite by email (async). Both use the same gentle
   box-shadow pulse so the visual language is consistent — only the hue
   changes. */
@keyframes bd-pulse-green {
    0%   { box-shadow: 0 0 0 0 rgba(0, 200, 83, 0.8); }
    50%  { box-shadow: 0 0 0 10px rgba(0, 200, 83, 0); }
    100% { box-shadow: 0 0 0 0 rgba(0, 200, 83, 0); }
}
@keyframes bd-pulse-amber {
    0%   { box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.7); }
    50%  { box-shadow: 0 0 0 10px rgba(255, 193, 7, 0); }
    100% { box-shadow: 0 0 0 0 rgba(255, 193, 7, 0); }
}
.bd-invite-designer-btn.bd-invite-has-online {
    animation: bd-pulse-green 1.5s ease-in-out infinite;
}
.bd-invite-designer-btn.bd-invite-no-online {
    animation: bd-pulse-amber 1.5s ease-in-out infinite;
}

.bd-live-help-panel {
    width: 0;
    overflow: hidden;
    background: var(--bd-bg-panel);
    border-left: 1px solid var(--bd-border);
    transition: width 0.18s ease;
    flex: none;
    display: flex;
    flex-direction: column;
}

.bd-live-help-panel.open {
    width: 280px;
}

.bd-live-help-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 14px 0;
    white-space: nowrap;
}

.bd-live-help-header h4 {
    margin: 0;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: #888;
}

.bd-live-help-customer,
.bd-live-help-designer {
    padding: 8px 14px 14px;
    overflow-y: auto;
}

.bd-live-help-hint {
    margin: 0 0 12px;
    font-size: 11.5px;
    line-height: 1.5;
    color: #8a93a6;
    white-space: normal;
}

.bd-live-help-hint-subdued {
    margin-top: 8px;
    margin-bottom: 0;
    font-size: 11px;
    color: #aab0bd;
}

.bd-live-help-section-title {
    margin: 0 0 4px;
    font-size: 13px;
    font-weight: 700;
    color: #222;
}

.bd-live-help-presence-status {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 10px;
    font-size: 11.5px;
    font-weight: 600;
}

.bd-live-help-presence-status.bd-live-help-presence-online {
    color: #1e9e57;
}

.bd-live-help-presence-status.bd-live-help-presence-offline {
    color: #8a93a6;
}

.bd-presence-dot-inline {
    width: 7px;
    height: 7px;
    flex: none;
    border-radius: 50%;
    background: #c2c8d0;
}

.bd-live-help-presence-online .bd-presence-dot-inline {
    background: #2ecc71;
    box-shadow: 0 0 0 2px rgba(46, 204, 113, 0.2);
}

.bd-live-help-divider {
    display: flex;
    align-items: center;
    margin: 18px 0;
    color: #b2b8c4;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.bd-live-help-divider::before,
.bd-live-help-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--bd-border);
}

.bd-live-help-divider span {
    padding: 0 10px;
}

.bd-live-help-status {
    margin: 0;
    font-size: 12.5px;
    line-height: 1.5;
    color: #444;
    /* Phase D2 — bdFadeSwapText() toggles opacity around a text swap
       instead of a hard textContent replace; this is what makes that
       actually fade rather than jump. */
    transition: opacity 0.15s ease;
}

#bd-live-help-description,
#bd-live-help-name {
    width: 100%;
    box-sizing: border-box;
    padding: 8px 10px;
    margin-bottom: 10px;
    border: 1px solid var(--bd-border);
    border-radius: 6px;
    font-size: 12.5px;
    font-family: inherit;
    resize: vertical;
}

#bd-live-help-claimed-controls {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 10px;
}

/* Stage 3 Phase B2 — connection/control status block, shared by both
   roles (see #bd-live-help-connection in banner-designer.php). */
.bd-live-help-connection {
    padding: 10px 14px;
    margin: 0 14px 10px;
    background: #f5f6f8;
    border: 1px solid var(--bd-border);
    border-radius: 6px;
}

.bd-live-help-connection .bd-live-help-status {
    font-weight: 600;
}

.bd-live-help-status-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.bd-live-help-status-row .bd-live-help-status {
    margin: 0;
}

/* Compact bilateral connection indicator — two endpoint dots (client/
   designer) joined by a short line, per the same design language as the
   presence dots above (#2ecc71 = online/success). Kept tiny and inline
   next to the status text on purpose (not a large badge) — see
   updateLiveStatusUI() in bd-live-help.js for the JS state machine that
   toggles is-live / is-reconnecting, driven by the SAME
   livePeerConnected/liveHasEverConnected values the status text already
   uses, not a second presence system. */
.bd-live-indicator {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    line-height: 1;
}

.bd-live-indicator-svg {
    display: block;
    overflow: visible;
}

.bd-live-indicator-line {
    stroke: #c7cbd4;
    stroke-width: 1.5;
    transition: stroke 0.2s ease;
}

.bd-live-indicator-dot {
    fill: #c7cbd4;
    transition: fill 0.2s ease;
}

.bd-live-indicator-pulse {
    fill: #7be3a6;
    opacity: 0;
}

.bd-live-indicator-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #8a93a6;
}

/* Connected — healthy/success green, same #2ecc71 as the presence dots. */
.bd-live-indicator.is-live .bd-live-indicator-line { stroke: #2ecc71; }
.bd-live-indicator.is-live .bd-live-indicator-dot { fill: #2ecc71; }
.bd-live-indicator.is-live .bd-live-indicator-label { color: #1f8a4c; }
.bd-live-indicator.is-live .bd-live-indicator-pulse {
    animation: bd-live-indicator-pulse-travel 1.8s linear infinite;
}

/* Temporarily lost — muted/dashed, same attention-orange already used by
   .bd-live-help-sync-status above. Auto-reverts to is-live the instant
   updateLiveStatusUI() sees the peer again — no separate timer here. */
.bd-live-indicator.is-reconnecting .bd-live-indicator-line { stroke: #d9a86c; stroke-dasharray: 2 2; }
.bd-live-indicator.is-reconnecting .bd-live-indicator-dot { fill: #d9a86c; opacity: 0.7; }
.bd-live-indicator.is-reconnecting .bd-live-indicator-label { color: #b5720a; }

@keyframes bd-live-indicator-pulse-travel {
    0% { cx: 5; opacity: 0; }
    8% { opacity: 1; }
    92% { opacity: 1; }
    100% { cx: 25; opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .bd-live-indicator.is-live .bd-live-indicator-pulse { animation: none; opacity: 0; }
}

.bd-live-help-controller-status {
    margin: 4px 0 0;
    font-size: 12px;
    line-height: 1.5;
    color: #666;
    transition: opacity 0.15s ease;
}

.bd-live-help-ping {
    margin: 4px 0 0;
    font-size: 11px;
    line-height: 1.4;
    color: #8a93a6;
}

.bd-live-help-sync-status {
    margin: 4px 0 0;
    font-size: 12px;
    line-height: 1.5;
    color: #b5720a;
    font-style: italic;
}

#bd-live-help-force-control-btn {
    margin-top: 10px;
}

/* Phase D1 — designer roster on the customer's "Invite a Designer" tab.
   Purely informational (see #bd-live-help-designer-list's own comment
   in banner-designer.php) — no click handler, no selection state. */
.bd-live-help-designer-list {
    list-style: none;
    /* Now rendered AFTER the Invite button (see #bd-live-help-start in
       banner-designer.php) — spacing flipped to sit above the list
       instead of below it. */
    margin: 12px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.bd-live-help-designer-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border: 1px solid var(--bd-border);
    border-radius: 6px;
    background: #fafbfc;
}

/* Generic initial-in-a-circle avatar — no upload/storage, just a bit of
   visual variety via a deterministic name->hue hash (see
   bdApplyDesignerAvatarColors() in banner-designer.js). Falls back to a
   neutral grey if JS never runs (no-JS/slow-load first paint). */
.bd-live-help-designer-avatar {
    width: 24px;
    height: 24px;
    flex: none;
    border-radius: 50%;
    background: #9aa5b1;
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    display: flex;
    align-items: center;
    justify-content: center;
}

.bd-live-help-designer-name {
    flex: 1;
    font-size: 12.5px;
    color: #333;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bd-designer-presence-dot {
    width: 8px;
    height: 8px;
    flex: none;
    border-radius: 50%;
    transition: background-color 0.2s ease;
}

.bd-designer-presence-dot.bd-designer-presence-offline {
    background: #c2c8d0;
}

.bd-designer-presence-dot.bd-designer-presence-online {
    background: #2ecc71;
    box-shadow: 0 0 0 2px rgba(46, 204, 113, 0.2);
}

/* Phase D2 — "…" while waiting for the first peer_present/peer_connected
   (see #bd-live-help-connecting-dots's own comment in banner-designer.php
   for why this is a sibling, not nested inside the status text). */
.bd-live-help-connecting-dots {
    display: inline-flex;
    gap: 3px;
    margin-left: 4px;
    vertical-align: middle;
}

.bd-live-help-connecting-dots span {
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: #8a93a6;
    animation: bd-live-help-connecting-blink 1.2s infinite ease-in-out both;
}

.bd-live-help-connecting-dots span:nth-child(2) { animation-delay: 0.15s; }
.bd-live-help-connecting-dots span:nth-child(3) { animation-delay: 0.3s; }

@keyframes bd-live-help-connecting-blink {
    0%, 80%, 100% { opacity: 0.25; }
    40% { opacity: 1; }
}

/* Stage 3 Phase C — chat, shared by both roles (see #bd-live-help-chat
   in banner-designer.php). Messages column + input row, with
   own/peer instead of user/assistant since either side could be viewing
   as client or designer. */
.bd-live-help-chat {
    display: flex;
    flex-direction: column;
    margin: 0 14px 10px;
    border: 1px solid var(--bd-border);
    border-radius: 6px;
    max-height: 260px;
}

.bd-live-help-chat-messages {
    flex: 1;
    overflow-y: auto;
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-height: 200px;
}

.bd-live-help-chat-message {
    display: flex;
    flex-direction: column;
    max-width: 90%;
}

.bd-live-help-chat-message-peer {
    align-self: flex-start;
    align-items: flex-start;
}

.bd-live-help-chat-message-own {
    align-self: flex-end;
    align-items: flex-end;
}

.bd-live-help-chat-name {
    font-size: 10.5px;
    color: #8a93a6;
    margin: 0 3px 2px;
}

.bd-live-help-chat-bubble {
    padding: 7px 10px;
    border-radius: 12px;
    font-size: 12px;
    line-height: 1.45;
    white-space: pre-line;
    word-break: break-word;
}

.bd-live-help-chat-message-peer .bd-live-help-chat-bubble {
    background: #eef2f6;
    color: #333;
    border-bottom-left-radius: 4px;
}

.bd-live-help-chat-message-own .bd-live-help-chat-bubble {
    background: #2271b1;
    color: #fff;
    border-bottom-right-radius: 4px;
}

.bd-live-help-chat-typing {
    margin: 0;
    padding: 0 12px 6px;
    font-size: 11px;
    line-height: 1.4;
    color: #8a93a6;
    font-style: italic;
    flex: none;
}

.bd-live-help-chat-form {
    display: flex;
    gap: 8px;
    padding: 8px 10px;
    border-top: 1px solid var(--bd-border);
    flex: none;
}

.bd-live-help-chat-form input {
    flex: 1;
    min-width: 0;
    padding: 7px 9px;
    border: 1px solid var(--bd-border);
    border-radius: 6px;
    font-size: 12px;
    font-family: inherit;
}

.bd-live-help-chat-mute-btn {
    flex: none;
    width: 30px;
    height: 30px;
    color: #8a93a6;
}

/* Muted state — toggled by bindLiveChatSoundToggle() in
   banner-designer.js. Shows the slash, hides the sound-wave arc. */
.bd-live-help-chat-mute-btn.bd-muted {
    color: #c0392b;
}

.bd-live-help-chat-mute-btn.bd-muted .bd-mute-slash {
    display: block !important;
}

.bd-live-help-chat-mute-btn.bd-muted .bd-sound-wave {
    display: none;
}

.bd-templates-panel {
    width: 0;
    overflow: hidden;
    background: var(--bd-bg-panel);
    border-left: 1px solid var(--bd-border);
    transition: width 0.18s ease;
    flex: none;
}

.bd-templates-panel.open {
    width: 232px;
}

.bd-templates-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 14px 0;
    white-space: nowrap;
}

.bd-templates-header h4 {
    margin: 0;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: #888;
}

.bd-templates-hint {
    margin: 8px 14px 12px;
    font-size: 11.5px;
    line-height: 1.5;
    color: #8a93a6;
    white-space: normal;
    width: 200px;
}

.bd-templates-items {
    padding: 0 14px 14px;
    overflow-y: auto;
}

.bd-templates-category-label {
    margin: 10px 0 8px;
    font-size: 10.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: #a0a8b8;
}

.bd-templates-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-bottom: 4px;
}

.bd-templates-item {
    border: 1px solid var(--bd-border);
    border-radius: 8px;
    background: #fff;
    padding: 6px;
    cursor: pointer;
    text-align: center;
    user-select: none;
}

.bd-templates-item:hover {
    border-color: var(--bd-accent);
}

.bd-templates-item img {
    display: block;
    width: 100%;
    height: 72px;
    object-fit: contain;
    border-radius: 4px;
    margin-bottom: 4px;
    pointer-events: none;
}

.bd-templates-item-noimg {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 72px;
    font-size: 10.5px;
    color: #b0b7c3;
    margin-bottom: 4px;
}

.bd-templates-item-name {
    font-size: 10.5px;
    color: #667085;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: none;
}

/* Ghost preview that follows the cursor while dragging a shelf item back
   toward the canvas (see bindShelfDrag() in banner-designer.js) — a
   plain floating <img>, not a native HTML5 drag image, matching this
   app's existing custom mouse-based drag pattern (ruler guides). */
#bd-shelf-drag-ghost {
    position: fixed;
    z-index: 100000;
    width: 64px;
    height: 64px;
    object-fit: contain;
    pointer-events: none;
    opacity: 0.85;
    filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.35));
    display: none;
}

/* Drop-target affordance — the canvas area highlights while a shelf item
   is being dragged over it, and the shelf panel itself highlights while
   a CANVAS object is being dragged toward it (see the mouse:move
   handlers in bindShelfDrag()/bindShelfDropTarget()). */
.bd-canvas-area.bd-shelf-drop-target,
.bd-shelf-panel.bd-shelf-drop-target {
    outline: 2px dashed var(--bd-accent);
    outline-offset: -2px;
}

/* Draw is the only sidebar tool that's a persistent toggle rather than a
   one-shot "add an object" action (see isDrawMode in banner-designer.js)
   — needs an "engaged" look the other buttons never do. */
.bd-tool-btn.active {
    background: var(--bd-accent);
    color: #fff;
}

.bd-tool-btn-wrap {
    width: 100%;
    position: relative;
}

/* Footer */

.bd-footer {
    padding: 14px 16px;
    background: #fff;
    border-top: 1px solid var(--bd-border);
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 10px;
}

/* Watermark "Print & Banner Studio" between Export and Save buttons —
   centred in the available space, reads as a subtle brand imprint rather
   than an interactive control. Clicking opens coredevil.com in a new tab. */
.bd-footer-watermark {
    text-align: center;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: #c0c4cc;
    opacity: 0.7;
    white-space: nowrap;
    text-decoration: none;
    transition: opacity 0.15s ease, color 0.15s ease;
    cursor: pointer;
}

.bd-footer-watermark:hover {
    opacity: 1;
    color: #2271b1;
}

/* Right column in the footer grid — wraps Save buttons so they align
   to the right edge, keeping the watermark perfectly centred between
   Export (left) and Save (right). */
.bd-footer-right {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 10px;
}

/* Floating mini toolbar above selected object */

.bd-floating-toolbar {
    position: absolute;
    display: none;
    gap: 4px;
    background: #222;
    border-radius: 8px;
    padding: 4px;
    transform: translateX(-50%);
    z-index: 40;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
}

.bd-floating-toolbar button {
    width: 30px;
    height: 30px;
    border: none;
    background: transparent;
    border-radius: 5px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.bd-floating-toolbar button svg {
    width: 16px;
    height: 16px;
    fill: #fff;
}

.bd-floating-toolbar button:hover {
    background: rgba(255, 255, 255, 0.15);
}

/* Transform HUD */

#bd-transform-hud {
    position: absolute;
    display: none;
    background: rgba(0, 0, 0, 0.75);
    color: #fff;
    padding: 4px 10px;
    border-radius: 6px;
    font-size: 12px;
    font-family: monospace;
    transform: translate(-50%, -50%);
    pointer-events: none;
    z-index: 45;
    white-space: nowrap;
}

/* Color picker popup */

.bd-popup {
    display: none;
    position: fixed;
    z-index: 100;
    background: #fff;
    border: 1px solid var(--bd-border);
    border-radius: 10px;
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.18);
    padding: 14px;
    width: 260px;
}

.bd-effects-popup {
    width: 250px;
}

.bd-clip-shape-popup {
    width: 190px;
    padding: 4px;
}

.bd-clip-shape-popup div {
    padding: 9px 12px;
    font-size: 13px;
    cursor: pointer;
    border-radius: 6px;
}

.bd-clip-shape-popup div:hover {
    background: #f0f4f9;
}

.bd-export-popup {
    width: 220px;
    padding: 4px;
}

.bd-export-popup div {
    padding: 9px 12px;
    font-size: 13px;
    cursor: pointer;
    border-radius: 6px;
}

.bd-export-popup div:hover {
    background: #f0f4f9;
}

.bd-effects-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
}

.bd-popup-section-sep {
    border-top: 1px solid var(--bd-border);
    margin: 12px 0;
}

.bd-popup-label {
    font-size: 11px;
    text-transform: uppercase;
    color: #888;
    margin-bottom: 6px;
}

.bd-hex-input {
    flex: 1;
    padding: 8px;
    border: 1px solid var(--bd-border);
    border-radius: 6px;
    font-size: 13px;
    font-family: monospace;
}

/* ---------- Draggable modals/popups (shared by all of them — see
   bdMakeDraggable() in banner-designer.js) ---------- */

.bd-drag-handle {
    cursor: grab;
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
}

.bd-drag-handle.bd-dragging {
    cursor: grabbing;
}

/* Small grip bar auto-inserted as the first child of any popup/modal
   that has no .bd-modal-header of its own to grab (color picker,
   effects, clip-shape, export, confirm). */
.bd-drag-grip {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 14px;
}

.bd-drag-grip::before {
    content: '';
    width: 34px;
    height: 4px;
    border-radius: 2px;
    background: rgba(0, 0, 0, 0.15);
    transition: background 0.15s;
}

.bd-drag-grip:hover::before,
.bd-drag-grip.bd-dragging::before {
    background: rgba(0, 0, 0, 0.3);
}

/* Layer context menu (right click) */

.bd-context-menu {
    display: none;
    position: fixed;
    z-index: 200;
    background: #fff;
    border: 1px solid var(--bd-border);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
    min-width: 170px;
    overflow: hidden;
}

.bd-context-menu.open {
    display: block;
}

.bd-context-menu div {
    padding: 9px 14px;
    font-size: 13px;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 8px;
}

.bd-context-menu div:hover {
    background: #f0f4f9;
}

.bd-context-menu-sep {
    height: 1px;
    background: var(--bd-border);
    margin: 4px 0;
}

/* ---------- Modal overlay (shared by Image Library, Barcode, Image Editor) ---------- */

.bd-modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 300;
    align-items: center;
    justify-content: center;
}

.bd-modal-overlay.open {
    display: flex;
}

.bd-modal {
    background: #fff;
    border-radius: 12px;
    width: 90%;
    max-width: 640px;
    max-height: 85vh;
    display: flex;
    flex-direction: column;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}

.bd-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px;
    border-bottom: 1px solid var(--bd-border);
}

.bd-modal-header h3 {
    margin: 0;
    font-size: 16px;
}

.bd-modal-body {
    padding: 20px;
    overflow-y: auto;
    flex: 1;
}

.bd-modal-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 20px;
    border-top: 1px solid var(--bd-border);
}

/* Image library */

.bd-library-hint {
    font-size: 12.5px;
    color: #888;
    margin-bottom: 14px;
}

.bd-library-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: 12px;
}

.bd-library-empty {
    grid-column: 1 / -1;
    text-align: center;
    color: #999;
    padding: 40px 0;
    font-size: 13px;
}

.bd-library-cell {
    position: relative;
    aspect-ratio: 1;
    border: 2px solid var(--bd-border);
    border-radius: 8px;
    overflow: hidden;
    cursor: pointer;
    background: repeating-conic-gradient(#f0f0f0 0% 25%, #fff 0% 50%) 50% / 16px 16px;
}

.bd-library-cell img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.bd-library-cell.selected {
    border-color: var(--bd-accent);
    box-shadow: 0 0 0 2px rgba(34, 113, 177, 0.25);
}

/* Marks a premium-gated feature (export menu rows, sidebar tool buttons,
   header toolbar icon buttons) — shown alongside the normal label rather
   than hiding/removing it, per this app's "show what's behind the
   paywall" freemium convention (see requirePremium() in
   banner-designer.js). */
.bd-pro-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 8.5px;
    font-weight: 700;
    letter-spacing: 0.03em;
    color: #fff;
    background: var(--bd-accent);
    border-radius: 4px;
    padding: 1px 4px;
    line-height: 1.4;
    margin-left: 5px;
}

.bd-tool-btn .bd-pro-badge {
    margin-left: 0;
    margin-top: -2px;
}

.bd-lowres-badge {
    position: absolute;
    bottom: 4px;
    left: 4px;
    right: 4px;
    background: rgba(211, 47, 47, 0.9);
    color: #fff;
    font-size: 9.5px;
    padding: 2px 4px;
    border-radius: 4px;
    text-align: center;
}

/* Placeholder shown from the instant a file is selected until it's
   actually decoded/rendered — for a normal image this is only visible
   briefly, but for a PDF (page.render() has no incremental progress
   signal to show a real percentage for) it can be the only feedback for
   several seconds, so the status text is deliberately staged wording,
   never a fabricated percentage. */
.bd-library-cell.pending {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 10px;
    cursor: default;
    background: #fff;
}

.bd-library-cell-spinner {
    width: 22px;
    height: 22px;
    border: 2.5px solid var(--bd-border);
    border-top-color: var(--bd-accent);
    border-radius: 50%;
    animation: bd-library-spin 0.8s linear infinite;
}

@keyframes bd-library-spin {
    to { transform: rotate(360deg); }
}

.bd-library-cell-status {
    font-size: 10.5px;
    color: #666;
    text-align: center;
    line-height: 1.3;
}

.bd-library-remove {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 18px;
    height: 18px;
    background: rgba(0, 0, 0, 0.6);
    color: #fff;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    cursor: pointer;
}

.bd-library-remove:hover {
    background: #d32f2f;
}

/* Barcode modal */

.bd-barcode-body {
    display: flex;
    gap: 20px;
}

.bd-barcode-form {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.bd-barcode-form label {
    font-size: 12px;
    color: #666;
    margin-top: 8px;
}

.bd-barcode-hint {
    font-size: 11.5px;
    color: #999;
    margin-top: 4px;
}

.bd-barcode-preview-wrap {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #fafafa;
    border: 1px solid var(--bd-border);
    border-radius: 8px;
    min-height: 180px;
    padding: 10px;
}

.bd-barcode-preview-wrap canvas {
    max-width: 100%;
}

/* Image editor modal */

.bd-modal-fullscreen {
    width: 95vw;
    height: 90vh;
    max-width: none;
    max-height: none;
}

.bd-image-editor-modal .bd-image-editor-tabs {
    display: flex;
    gap: 6px;
    padding: 10px 20px;
    border-bottom: 1px solid var(--bd-border);
    flex-shrink: 0;
}

.bd-image-editor-body {
    display: flex;
    gap: 20px;
    align-items: stretch;
    flex: 1;
    min-height: 0;
}

.bd-image-editor-canvas-wrap {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    background: repeating-conic-gradient(#f0f0f0 0% 25%, #fff 0% 50%) 50% / 20px 20px;
    border: 1px solid var(--bd-border);
    border-radius: 8px;
    overflow: hidden;
    min-height: 0;
}

#bd-image-editor-canvas {
    display: block;
}

.bd-image-editor-panel {
    width: 240px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.bd-image-editor-panel label {
    font-size: 12px;
    color: #666;
    margin-top: 10px;
}

.bd-checkbox-label {
    display: flex;
    align-items: center;
    gap: 8px;
}

.bd-editor-hint {
    font-size: 12.5px;
    color: #777;
    line-height: 1.5;
    margin: 0;
}

.bd-image-editor-footer {
    justify-content: flex-end;
    gap: 10px;
}

.bd-magic-editor-modal { width: 96vw; height: 94vh; max-width: none; max-height: none; background: #111827; color: #e5edf5; }
.bd-magic-editor-modal .bd-modal-header { min-height: 62px; background: #172536; border-bottom: 1px solid #2b4057; display: flex; align-items: center; gap: 12px; }
.bd-magic-editor-modal .bd-modal-header h3 { margin-right: 0; color: #f1f5f9; }
.bd-magic-editor-modal .bd-modal-footer { display: none; }
.bd-magic-editor-header-status { color: #91a4b8; font-size: 12px; white-space: nowrap; }
.bd-magic-editor-header-actions { display: flex; align-items: center; gap: 6px; margin-left: 12px; }
.bd-magic-editor-header-actions .bd-btn, .bd-magic-editor-header-actions .bd-btn-primary { min-height: 36px; }
.bd-magic-editor-body { display: flex; flex: 1; align-items: stretch; gap: 0; min-height: 0; overflow: hidden; background: #0f1722; }
.bd-magic-editor-canvas-wrap { position: relative; flex: 1; min-width: 0; min-height: 0; display: flex; align-items: center; justify-content: center; overflow: hidden; background: #0f1722; }
.bd-magic-editor-canvas-wrap.is-checkerboard { background-color: #172333; background-image: linear-gradient(45deg, #223247 25%, transparent 25%), linear-gradient(-45deg, #223247 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #223247 75%), linear-gradient(-45deg, transparent 75%, #223247 75%); background-size: 18px 18px; background-position: 0 0, 0 9px, 9px -9px, -9px 0; }
#bd-magic-editor-canvas { display: block; width: 100%; height: 100%; touch-action: none; cursor: crosshair; }
.bd-magic-editor-panel { width: 292px; flex: 0 0 292px; overflow-y: auto; display: flex; flex-direction: column; gap: 0; border-left: 1px solid #2b4057; background: #172536; color: #e5edf5; }
.bd-magic-editor-tools, .bd-magic-editor-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.bd-magic-editor-tools button, .bd-magic-editor-actions button { min-height: 38px; border: 1px solid #2b4057; background: #1e3044; color: #aebed0; border-radius: 7px; padding: 7px 9px; cursor: pointer; font-size: 12px; transition: .15s ease; }
.bd-magic-editor-tools button:hover, .bd-magic-editor-actions button:hover { border-color: var(--bd-accent); color: #fff; background: #243b55; }
.bd-magic-editor-tools button.active { border-color: var(--bd-accent); background: #22547e; color: #fff; box-shadow: inset 0 0 0 1px rgba(73,160,222,.25); }
.bd-magic-editor-tools button:disabled { opacity: .5; cursor: not-allowed; }
.bd-magic-editor-view-buttons { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
.bd-magic-editor-view-buttons button { min-height: 34px; border: 1px solid #2b4057; background: #1e3044; color: #aebed0; border-radius: 7px; padding: 7px 8px; cursor: pointer; font-size: 11px; }
.bd-magic-editor-view-buttons button:hover, .bd-magic-editor-view-buttons button.active { border-color: var(--bd-accent); background: #22547e; color: #fff; }
.bd-magic-editor-magic-status { display: flex; flex-direction: column; gap: 5px; margin-top: 10px; padding: 9px; border: 1px solid #2b4057; border-radius: 7px; background: #142335; color: #d8e6f3; font-size: 11px; }
.bd-magic-editor-magic-status[hidden] { display: none; }
.bd-magic-editor-magic-status span { color: #91a4b8; }
.bd-magic-editor-magic-progress { height: 4px; overflow: hidden; border-radius: 99px; background: #2b4057; }
.bd-magic-editor-magic-progress span { display: block; width: 0; height: 100%; background: var(--bd-accent); transition: width .15s linear; }
.bd-magic-editor-magic-status button { align-self: flex-start; min-height: 28px; border: 1px solid #42617f; border-radius: 6px; background: #1e3044; color: #d8e6f3; cursor: pointer; padding: 4px 9px; font-size: 11px; }
.bd-magic-editor-panel > label, .bd-magic-editor-section { padding: 12px 16px 0; }
.bd-magic-editor-panel > select, .bd-magic-editor-panel > input { margin: 6px 16px 0; }
.bd-magic-editor-section { border-top: 1px solid #2b4057; padding-bottom: 14px; }
.bd-magic-editor-section-title { color: #91a4b8; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; margin-bottom: 10px; }
.bd-magic-editor-panel output { float: right; color: #c7d5e3; font-weight: 600; }
.bd-magic-editor-panel input[type="range"] { width: 100%; accent-color: var(--bd-accent); }
.bd-magic-editor-panel select { border: 1px solid #2b4057; background: #1e3044; color: #e5edf5; border-radius: 6px; padding: 8px; }
.bd-magic-editor-status { position: absolute; left: 50%; top: 24px; transform: translateX(-50%); max-width: 80%; padding: 9px 14px; border: 1px solid #42617f; border-radius: 7px; background: rgba(23,37,54,.96); color: #d8e6f3; box-shadow: 0 5px 18px rgba(0,0,0,.28); text-align: center; z-index: 4; }
.bd-magic-editor-status.is-busy::before { content: ''; display: inline-block; width: 12px; height: 12px; margin-right: 8px; border: 2px solid #42617f; border-top-color: var(--bd-accent); border-radius: 50%; animation: bd-library-spin .8s linear infinite; vertical-align: -2px; }
.bd-magic-editor-loading { position: absolute; inset: 0; z-index: 5; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; background: rgba(15,23,34,.92); color: #d8e6f3; text-align: center; }
.bd-magic-editor-loading[hidden] { display: none; }
.bd-magic-editor-loading > span:not(.bd-magic-editor-spinner) { color: #91a4b8; font-size: 12px; }
.bd-magic-editor-spinner { width: 30px; height: 30px; border: 3px solid #2b4057; border-top-color: var(--bd-accent); border-radius: 50%; animation: bd-library-spin .8s linear infinite; }
.bd-magic-editor-progress { width: min(300px, 60%); height: 6px; overflow: hidden; border-radius: 99px; background: #2b4057; }
.bd-magic-editor-progress[hidden] { display: none; }
.bd-magic-editor-progress span { display: block; width: 0; height: 100%; background: var(--bd-accent); transition: width .15s linear; }
.bd-magic-editor-viewport-controls { position: absolute; left: 50%; bottom: 18px; transform: translateX(-50%); z-index: 3; display: flex; align-items: center; gap: 4px; padding: 5px; border: 1px solid #2b4057; border-radius: 10px; background: rgba(23,37,54,.96); box-shadow: 0 8px 25px rgba(0,0,0,.32); }
.bd-magic-editor-viewport-controls button { min-width: 30px; height: 28px; border: 0; border-radius: 6px; background: transparent; color: #d8e6f3; cursor: pointer; font-size: 12px; }
.bd-magic-editor-viewport-controls button:hover { background: #243b55; }
.bd-magic-editor-viewport-controls span { min-width: 48px; color: #91a4b8; font-size: 11px; text-align: center; }
.bd-magic-editor-cursor { position: fixed; z-index: 10000; pointer-events: none; transform: translate(-50%, -50%); border: 1px solid #07111d; box-shadow: 0 0 0 1px rgba(255,255,255,.92); border-radius: 50%; }
.bd-magic-editor-cursor-core { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); border: 1px solid rgba(255,255,255,.9); box-shadow: 0 0 0 1px rgba(7,17,29,.85); border-radius: 50%; }



.bd-tab-btn {
    padding: 7px 14px;
    border: 1px solid var(--bd-border);
    background: #fff;
    border-radius: 7px;
    font-size: 13px;
    cursor: pointer;
}

.bd-tab-btn.active {
    background: var(--bd-accent);
    color: #fff;
    border-color: var(--bd-accent);
}

/* Custom confirm modal */

.bd-confirm-modal {
    max-width: 380px;
    padding: 28px 24px 22px;
    text-align: center;
    align-items: center;
}

.bd-confirm-icon {
    font-size: 34px;
    margin-bottom: 10px;
}

.bd-confirm-title {
    font-size: 16px;
    font-weight: 600;
    margin-bottom: 8px;
}

/* Save-in-progress overlay — same spinner keyframe as the library-upload
   placeholder (bd-library-spin), just sized for a modal instead of a grid
   cell. No fake percentage — see bd-save-progress-status's staged/counted
   text in banner-designer.js. */
.bd-save-progress-modal {
    max-width: 340px;
    padding: 32px 28px;
    text-align: center;
    align-items: center;
}

.bd-save-progress-spinner {
    width: 32px;
    height: 32px;
    border: 3px solid var(--bd-border);
    border-top-color: var(--bd-accent);
    border-radius: 50%;
    animation: bd-library-spin 0.8s linear infinite;
    margin-bottom: 16px;
}

.bd-save-progress-status {
    font-size: 14px;
    color: #333;
    line-height: 1.5;
}

.bd-progress-track {
    position: relative;
    display: block;
    width: min(280px, 100%);
    height: 8px;
    margin-top: 16px;
    overflow: hidden;
    border-radius: 999px;
    background: #e5e7eb;
    z-index: 1;
}

.bd-progress-bar {
    display: block;
    width: 0;
    height: 100%;
    border-radius: inherit;
    background: var(--bd-accent, #2271b1);
    transition: width 120ms linear;
}

.bd-progress-track.indeterminate .bd-progress-bar {
    width: 38%;
    animation: bd-progress-indeterminate 1.15s ease-in-out infinite;
}

@keyframes bd-progress-indeterminate {
    0% { transform: translateX(-115%); }
    50% { transform: translateX(165%); }
    100% { transform: translateX(285%); }
}

.bd-confirm-message {
    font-size: 13.5px;
    color: #666;
    line-height: 1.5;
    margin-bottom: 20px;
    white-space: pre-line;
    text-align: left;
}

.bd-confirm-actions {
    display: flex;
    gap: 10px;
    justify-content: center;
}

.bd-confirm-actions button {
    flex: 1;
}

/* Large template preview — same .bd-modal-overlay/.bd-modal base as the
   confirm modal above, own content only (see the Templates panel block
   further up for the drawer/card side of this feature). */
.bd-template-preview-modal {
    position: relative;
    max-width: 480px;
    padding: 20px;
    text-align: center;
    align-items: center;
}

.bd-template-preview-close {
    position: absolute;
    top: 10px;
    right: 10px;
}

#bd-template-preview-img {
    max-width: 100%;
    max-height: 55vh;
    object-fit: contain;
    border-radius: 8px;
    border: 1px solid var(--bd-border);
    margin-bottom: 12px;
}

.bd-template-preview-name {
    font-size: 15px;
    font-weight: 600;
    margin-bottom: 16px;
}

.bd-template-preview-actions {
    display: flex;
    gap: 10px;
    justify-content: center;
    width: 100%;
}

.bd-template-preview-actions button {
    flex: 1;
}

/* PSD import: font detection/fallback report */

.bd-font-report-list {
    list-style: none;
    margin: 0;
    padding: 0;
    max-height: 320px;
    overflow-y: auto;
}

.bd-font-report-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 0;
    border-bottom: 1px solid var(--bd-border);
    font-size: 13.5px;
    line-height: 1.4;
}

.bd-font-report-row:last-child {
    border-bottom: none;
}

.bd-font-report-status {
    flex: none;
    width: 20px;
    text-align: center;
    font-weight: 700;
}

.bd-font-report-ok {
    color: #2e7d32;
}

.bd-font-report-warn {
    color: #b26a00;
}

.bd-font-report-missing {
    color: #c62828;
}

/* "Open as-is" coachmark — layers .bd-coachmark on top of the shared
   .bd-tooltip-popover base class (bd-admin-design-system.css, already
   loaded in this iframe document) rather than redefining the dark-
   popover look from scratch. */
.bd-coachmark {
    max-width: 230px;
    text-align: center;
}

.bd-coachmark::before {
    content: '';
    position: absolute;
    top: -6px;
    left: 50%;
    transform: translateX(-50%);
    border-left: 6px solid transparent;
    border-right: 6px solid transparent;
    border-bottom: 6px solid #1e2330;
}

/* "Fit to print area" button + hint — shown while a PSD "Open as-is"
   import is selected (see showFitToAreaOverlay() in banner-designer.js).
   Positioned via JS (getBoundingClientRect of bd-guide-finished), not
   here — these rules are just the visual treatment. */

.bd-fit-to-area-btn {
    display: none;
    position: absolute;
    z-index: 45;
    align-items: center;
    padding: 7px 12px;
    background: #2196f3;
    color: #fff;
    border: none;
    border-radius: 7px;
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    box-shadow: 0 4px 14px rgba(33, 150, 243, 0.35);
}

.bd-fit-to-area-btn:hover {
    background: #1976d2;
}

.bd-fit-to-area-hint {
    max-width: 260px;
    position: relative;
    padding-right: 24px;
}

.bd-fit-to-area-hint-close {
    position: absolute;
    top: 2px;
    right: 4px;
    background: transparent;
    border: none;
    color: #fff;
    opacity: 0.7;
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    padding: 2px;
}

.bd-fit-to-area-hint-close:hover {
    opacity: 1;
}

/* PSD import: Fit / Stretch / Open as-is chooser */

.bd-psd-fit-modal {
    max-width: 720px; /* wide enough for 3 option cards side by side, not just the original 2 */
}

.bd-psd-fit-hint {
    font-size: 13px;
    color: #555;
    margin: 0 0 4px;
}

.bd-psd-fit-options {
    display: flex;
    gap: 14px;
    margin-top: 14px;
}

.bd-psd-fit-option {
    flex: 1;
    display: block;
    border: 1.5px solid var(--bd-border);
    border-radius: 10px;
    padding: 14px;
    background: #fff;
    cursor: pointer;
    text-align: center;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.bd-psd-fit-option:hover {
    border-color: var(--bd-accent);
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
}

.bd-psd-fit-preview {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 90px;
    margin-bottom: 10px;
    background: var(--bd-bg-panel);
    border-radius: 6px;
    color: var(--bd-border);
}

.bd-psd-fit-option-title {
    display: block;
    font-weight: 600;
    font-size: 13px;
    margin-bottom: 4px;
    color: #222;
}

.bd-psd-fit-option small {
    display: block;
    color: #888;
    font-size: 11px;
    line-height: 1.4;
}

/* ---------- Comments (canvas annotation pins) — same handle/panel
   pattern as Live Help/Shelf above (own vertical tab, own slide-in
   panel), so it inherits this editor's --bd-accent instead of a
   hardcoded brand color: this stylesheet is shared by every white-label
   install of the plugin, not just CoreDevil's own Shopify deployment. */
.bd-comments-handle {
    position: relative;
    width: 24px;
    padding: 14px 5px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--bd-accent);
    transition: background 0.15s ease;
}

.bd-comments-handle:hover {
    background: rgba(34, 113, 177, 0.08);
}

.bd-comments-handle-label {
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 1px;
    text-transform: uppercase;
    white-space: nowrap;
}

.bd-comments-badge {
    position: absolute;
    top: 6px;
    right: 2px;
    min-width: 16px;
    height: 16px;
    padding: 0 3px;
    background: var(--bd-accent);
    color: #fff;
    border-radius: 50%;
    font-size: 10px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
}

.bd-comments-badge:empty {
    display: none;
}

.bd-comments-handle-arrow {
    position: absolute;
    top: 50%;
    left: -14px;
    transform: translateY(-50%);
    width: 18px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #fff;
    border: 1px solid var(--bd-accent);
    border-right: none;
    border-radius: 6px 0 0 6px;
    cursor: pointer;
    color: var(--bd-accent);
    transition: background 0.15s ease, transform 0.15s ease;
}

.bd-comments-handle-arrow:hover {
    background: var(--bd-accent);
    color: #fff;
    transform: translateY(-50%) scale(1.1);
}

.bd-comments-handle-arrow svg {
    width: 12px;
    height: 12px;
    display: block;
    transition: transform 0.18s ease;
}

.bd-comments-handle.open .bd-comments-handle-arrow svg {
    transform: rotate(180deg);
}

.bd-comments-panel {
    width: 0;
    overflow: hidden;
    background: var(--bd-bg-panel);
    border-left: 1px solid var(--bd-border);
    transition: width 0.18s ease;
    flex: none;
    display: flex;
    flex-direction: column;
}

.bd-comments-panel.open {
    width: 280px;
}

.bd-comments-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 14px 14px 10px;
    white-space: nowrap;
}

.bd-comments-panel-header h4 {
    margin: 0;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: #888;
}

.bd-comment-mode-toggle {
    padding: 5px 10px;
    background: var(--bd-accent);
    color: #fff;
    border: none;
    border-radius: 6px;
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}

.bd-comment-mode-toggle.active {
    background: #e8622c;
}

.bd-comment-instructions {
    margin: 0 14px 10px;
    padding: 8px 10px;
    background: #fff3e8;
    border-radius: 6px;
    font-size: 12px;
    color: #b5590a;
}

.bd-comments-list {
    overflow-y: auto;
    padding: 0 14px 14px;
    flex: 1;
}

.bd-comments-empty {
    color: #888;
    font-size: 12px;
    text-align: center;
    padding: 24px 8px;
}

.bd-comment-item {
    border-bottom: 1px solid var(--bd-border);
    padding: 12px 0;
    transition: background 0.3s ease;
}

.bd-comment-item:last-child {
    border-bottom: none;
}

.bd-comment-item-flash {
    background: #fff3e8;
}

.bd-comment-item-row {
    display: flex;
    align-items: flex-start;
    gap: 8px;
}

.bd-comment-item-badge {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--bd-accent);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.bd-comment-item-badge.resolved {
    background: #27ae60;
}

.bd-comment-item-body {
    flex: 1;
    min-width: 0;
}

.bd-comment-item-meta {
    font-size: 11px;
    color: #888;
    margin-bottom: 3px;
}

.bd-comment-item-text {
    font-size: 12.5px;
    color: #222;
    line-height: 1.4;
}

.bd-comment-reply {
    margin-top: 6px;
    padding: 6px 8px;
    background: #fff;
    border: 1px solid var(--bd-border);
    border-radius: 6px;
    font-size: 11.5px;
    line-height: 1.4;
}

.bd-comment-item-actions {
    display: flex;
    gap: 6px;
    margin-top: 8px;
}

.bd-comment-action-btn {
    font-size: 11px;
    padding: 3px 8px;
    border: 1px solid var(--bd-border);
    background: #fff;
    border-radius: 4px;
    cursor: pointer;
    color: #444;
}

.bd-comment-resolve-btn {
    border-color: #27ae60;
    color: #27ae60;
}

.bd-comment-resolved-label {
    font-size: 11px;
    color: #27ae60;
    display: inline-flex;
    align-items: center;
}

/* Click-capture layer over the canvas (see #bd-comment-click-overlay's
   own comment in banner-designer.php) — inert until #bd-canvas-wrap
   gets .bd-comment-mode, same mechanism as .bd-live-canvas-lock-overlay. */
.bd-comment-click-overlay {
    position: absolute;
    inset: 0;
    z-index: 7;
    pointer-events: none;
}

#bd-canvas-wrap.bd-comment-mode .bd-comment-click-overlay {
    pointer-events: all;
    cursor: crosshair;
}

.bd-comment-pin {
    position: absolute;
    transform: translate(-50%, -50%);
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: #e8622c;
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 50;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
    border: 2px solid #fff;
    pointer-events: all;
    transition: transform 0.2s;
}

.bd-comment-pin:hover {
    transform: translate(-50%, -50%) scale(1.2);
}

.bd-comment-pin.resolved {
    background: #27ae60;
}

.bd-comment-modal {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: #fff;
    border-radius: 12px;
    padding: 20px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
    z-index: 10000;
    width: 320px;
}

.bd-comment-modal h3 {
    margin: 0 0 12px;
    font-size: 15px;
    color: #222;
}

.bd-comment-modal textarea {
    width: 100%;
    height: 80px;
    padding: 8px;
    border: 1px solid var(--bd-border);
    border-radius: 6px;
    font-size: 13px;
    resize: none;
    box-sizing: border-box;
    font-family: inherit;
}

.bd-comment-modal-actions {
    display: flex;
    gap: 8px;
    margin-top: 12px;
    justify-content: flex-end;
}
