/**
 * Replicate Upload Interface - Combined Styles
 * Version: 3.7.2
 * Dark theme styled to match Realistec brand: violet gradient CTAs
 * (#8b5cf6 → #6366f1), Space Grotesk display type, deep cosmic surfaces.
 *
 * Brand fonts (Space Grotesk, Inter, JetBrains Mono) are loaded site-
 * wide via wp_enqueue_style() in the child theme's font-loading-snippet.php
 * Code Snippet — see style.css for the matching note. This file does NOT
 * @import them; it just references the theme's --rt-font-* tokens (with
 * hardcoded fallbacks).
 *
 * Structure:
 *   1. Layout overrides & theme refinements (originally loaded in <head>)
 *   2. Base styles (originally inline in <body>, takes final precedence)
 */

/* =============================================================
   SECTION 1: LAYOUT OVERRIDES & THEME REFINEMENTS
   (Original upload-interface.css — loaded first, lower precedence)
   ============================================================= */

/* =============================================
   UPLOAD INTERFACE - BASE STYLES
   ============================================= */

/* Fix: Center the individual frames in Standard Image side-by-side preview */

/* Center the frame cards within the previews list */
.realistec-stereo-frame-previews-list {
    justify-content: center;
}

/* Allow frame cards to grow and fill available space */
.realistec-stereo-frame-preview-item {
    flex: 1 1 0;
    min-width: 150px;
    max-width: 300px;
}

/* Let images fill the frame and dictate height.
   Higher specificity to override shortcode height: 180px. */
.realistec-stereo-frame-previews-list .realistec-stereo-frame-preview-item .realistec-stereo-frame-image {
    height: auto;
    padding: 0;
}

.realistec-stereo-frame-previews-list .realistec-stereo-frame-preview-item .realistec-stereo-frame-image img {
    width: 100%;
    height: auto;
    object-fit: cover;
}

/* =============================================
   STEREO SPLIT FRAMES - FILL WIDTH
   ============================================= */

.realistec-stereo-stereo-split-frames .realistec-stereo-split-frame {
    flex: 1;
    min-width: 0;
}

.realistec-stereo-stereo-split-frames .realistec-stereo-split-frame img {
    max-width: 100%;
    max-height: none;
    width: 100%;
    height: auto;
}

/* =============================================
   COMPARE & SELECT BUTTON
   ============================================= */

/* Override realistec-stereo-crop-description padding to align with match-color elements */
p.realistec-stereo-crop-description {
    padding: 4px 0 0 0;
}

/* Position realistec-stereo-crop-indicator under realistec-stereo-crop-description, on a line of its own.
   Mirrors the margin used by .realistec-stereo-match-color-selection-label (10px 0 0 28px)
   so when both indicators appear together in the same upload area they
   align consistently under the description.

   inline-flex (not inline-block) is required because the main
   .realistec-stereo-crop-indicator rule below uses gap and align-items to lay out its
   icon + text contents — overriding display here without using a flex
   value would erase that layout. Higher specificity than the main
   rule, but kept to display + margin only so the visual styling
   (background, padding, color, etc.) cascades from the main rule
   without duplication. */
.realistec-stereo-custom-crop-option .realistec-stereo-crop-indicator,
.realistec-stereo-stereo-crop-option .realistec-stereo-crop-indicator {
    display: inline-flex;
    margin: 10px 0 0 28px;
}

/* Also reposition the edit button onto the same line as the indicator */
.realistec-stereo-custom-crop-option .realistec-stereo-edit-crop-btn,
.realistec-stereo-stereo-crop-option .realistec-stereo-edit-stereo-crop-btn {
    margin-left: 8px;
}

.realistec-stereo-match-color-compare-btn {
    /* Mirrors the Immersity plugin's .realistec-mono-edit-crop-btn — a
       small outlined action button with a 1px border, square 4px corners,
       dark surface, light text, and brand violet on hover. Properties
       and order follow that reference verbatim so the two buttons stay
       visually identical and easy to keep in sync. */
    margin-left: 8px;
    padding: 4px 12px;
    background: var(--realistec-surface-2, #14112e);
    color: var(--realistec-text, #f5f3ff);
    border: 1px solid var(--realistec-border, #1f1b3a);
    border-radius: 4px;
    font-size: 12px;
    cursor: pointer;
    transition: background 0.2s, border-color 0.2s;
}

.realistec-stereo-match-color-compare-btn:hover {
    background: #1f1b3a;
    border-color: var(--realistec-primary, #8b5cf6);
}

.realistec-stereo-match-color-selection-label {
    display: none;
    align-items: center;
    /* gap handles spacing between the check icon and the label text;
       the JS no longer prepends a Unicode glyph so we don't need an
       inline space character anymore. */
    gap: 4px;
    margin: 10px 0 0 28px;
    padding: 4px 12px;
    background: var(--realistec-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    color: white;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 500;
}

/* Icon inside the match-color selection-label pill — scaled to the 12px
   pill text. The default .realistec-stereo-msi size (18px) would overflow the
   pill's vertical padding. Same approach used by .realistec-stereo-crop-indicator
   .realistec-stereo-msi for the equivalent crop-mode pill. Reset the
   margin-right and vertical-align that .realistec-stereo-msi applies in
   label-paired contexts — flex `gap: 4px` on the parent handles
   spacing here, and the flex alignment handles centering. */
.realistec-stereo-match-color-selection-label .realistec-stereo-msi {
    font-size: 14px;
    margin-right: 0;
    vertical-align: baseline;
}

/* =============================================
   HISTOGRAM COMPARISON MODAL
   ============================================= */

.realistec-stereo-hist-modal {
    /* Modal-scoped variable layer — mirrors the .realistec-stereo-crop-modal declaration
       further up this file. The histogram modal is portaled to <body>
       at runtime, which puts it outside .realistec-stereo-upload-interface
       and means the plugin's --realistec-* tokens don't reach here.
       Each --modal-* token aliases a theme --rt-* token (so a palette
       change in style.css propagates) with a hardcoded fallback after
       the comma for the case where the theme isn't loaded.

       Mapping (kept aligned with .realistec-stereo-crop-modal except for --modal-bg):
       --modal-bg              -> --rt-bg       (modal body — DEEPEST cosmic
                                                  backdrop. Differs from .realistec-stereo-crop-modal
                                                  which uses --rt-bg-2 here, because
                                                  the histogram canvas needs maximum
                                                  contrast for its drawn lines and
                                                  Immersity's reference modal does
                                                  the same. Result: the modal body
                                                  reads a step DEEPER than the header,
                                                  giving the modal a clear horizontal
                                                  seam between header and body.)
       --modal-surface         -> --rt-bg-3     (header / elevated areas)
       --modal-border          -> #1f1b3a       (hardcoded — theme's --rt-border is rgba)
       --modal-text            -> --rt-text
       --modal-text-secondary  -> --rt-text-muted
       --modal-accent          -> --rt-violet
       --modal-gradient        -> --rt-gradient (CTA buttons)
       --modal-gradient-hover  -> --rt-gradient-hover */
    --modal-bg: var(--rt-bg, #07060f);
    --modal-surface: var(--rt-bg-3, #14112e);
    --modal-border: #1f1b3a;
    --modal-text: var(--rt-text, #f5f3ff);
    --modal-text-secondary: var(--rt-text-muted, #a8a3c9);
    --modal-accent: var(--rt-violet, #8b5cf6);
    --modal-gradient: var(--rt-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    --modal-gradient-hover: var(--rt-gradient-hover, linear-gradient(135deg, #a78bfa 0%, #818cf8 100%));

    display: none;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.8);
    z-index: 999999;
    overflow-y: auto;
    padding: 20px;
    box-sizing: border-box;
    opacity: 0;
    transition: opacity 0.3s ease;
}

.realistec-stereo-hist-modal.active {
    display: flex;
    justify-content: center;
    align-items: center;
    opacity: 1;
}

.realistec-stereo-hist-modal-content {
    /* Mirrors Immersity's #realistec-mono-color-filter-modal .realistec-stereo-hist-modal-content
       layering: deepest cosmic backdrop (--modal-bg = --rt-bg) for the
       modal body, with the header above stepping up to --modal-surface.
       Was previously --realistec-surface (= --rt-bg-2), which made body
       and header identical and removed the visual seam. Now also uses
       the violet glow shadow Immersity uses, so both modals' shells
       read with the same brand language. */
    background: var(--modal-bg, #07060f);
    border: 1px solid var(--modal-border, #1f1b3a);
    border-radius: 12px;
    width: 95vw;
    max-width: 1200px;
    height: 90vh;
    max-height: 800px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    box-shadow:
        0 20px 60px rgba(0, 0, 0, 0.5),
        0 0 0 1px rgba(139, 92, 246, 0.08);
    transform: scale(0.95) translateY(-20px);
    transition: transform 0.3s ease;
    margin: auto;
    position: relative;
}

.realistec-stereo-hist-modal.active .realistec-stereo-hist-modal-content {
    transform: scale(1) translateY(0);
}

/* Header */
.realistec-stereo-hist-modal-header {
    /* --modal-surface (= --rt-bg-3) is one step lighter than --modal-bg
       (= --rt-bg) so a horizontal seam appears between header and body.
       Was previously --realistec-surface which equaled the body color
       and erased the seam. Border-bottom keeps the seam crisp at any
       backdrop. Mirrors the Immersity realistec-stereo-hist-modal-header rule. */
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 20px 24px;
    background: var(--modal-surface, #14112e);
    border-bottom: 1px solid var(--modal-border, #1f1b3a);
}

.realistec-stereo-hist-modal-header h3 {
    margin: 0;
    font-size: 20px;
    font-weight: 600;
    color: var(--realistec-text, #f5f3ff);
    /* Display font — references the theme's --rt-font-display token so a
       site-wide font change propagates here too. The modal is portaled
       to <body> at runtime, so it sits outside .realistec-stereo-upload-interface
       and doesn't inherit the display-font rule scoped to that selector.
       Setting the font explicitly on the modal's heading keeps Color
       Comparison's title aligned with the brand display family. */
    font-family: var(--rt-font-display, 'Space Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
    letter-spacing: -0.01em;
}

.realistec-stereo-hist-close-btn {
    background: none;
    border: none;
    font-size: 24px;
    color: var(--realistec-text-secondary, #a8a3c9);
    cursor: pointer;
    padding: 0;
    line-height: 1;
    transition: color 0.2s;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
}

.realistec-stereo-hist-close-btn:hover {
    color: var(--realistec-error, #ef4444);
    background: rgba(239, 68, 68, 0.1);
}

/* Body — flex row: main content left, sidebar right */
.realistec-stereo-hist-modal-body {
    display: flex;
    flex: 1;
    min-height: 0;
    overflow: hidden;
}

/* ---- Sidebar ---- */
.realistec-stereo-hist-sidebar {
    /* Right-hand controls panel. Uses --modal-surface (= --rt-bg-3) so
       the sidebar reads one step LIGHTER than the deeper --modal-bg
       body — the layering visible in the Immersity reference: deep body
       around the histogram canvas, lighter sidebar on the right, lighter
       header on top. An earlier revision routed this to --modal-bg to
       try to unify body and sidebar, but that erased the visible
       separation between the histogram area and the controls. */
    width: 200px;
    flex-shrink: 0;
    background: var(--modal-surface, #14112e);
    border-left: 1px solid var(--modal-border, #1f1b3a);
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    overflow-x: hidden;
    order: 1;
}

.realistec-stereo-hist-sidebar::-webkit-scrollbar { width: 6px; }
.realistec-stereo-hist-sidebar::-webkit-scrollbar-track { background: transparent; }
.realistec-stereo-hist-sidebar::-webkit-scrollbar-thumb { background: var(--modal-border, #1f1b3a); border-radius: 3px; }
.realistec-stereo-hist-sidebar::-webkit-scrollbar-thumb:hover { background: var(--modal-text-secondary, #a8a3c9); }

.realistec-stereo-hist-sidebar-section {
    padding: 16px;
    border-bottom: 1px solid var(--modal-border, #1f1b3a);
}

.realistec-stereo-hist-sidebar-section:last-child {
    border-bottom: none;
}

.realistec-stereo-hist-sidebar-section-title {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--realistec-text-secondary, #a8a3c9);
    margin: 0 0 12px 0;
}

/* Filter Strength label — matches realistec-stereo-hist-sidebar-section-title exactly */
.realistec-stereo-hist-sidebar-control-label {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--realistec-text-secondary, #a8a3c9);
    margin: 0 0 12px 0;
    display: block;
}

/* Filter strength control group */
.realistec-stereo-hist-filter-strength-group {
    width: 100%;
}

/* Slider + value on the same row */
.realistec-stereo-hist-filter-strength-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 8px;
    width: 100%;
}

.realistec-stereo-hist-filter-strength-row input[type="range"] {
    flex: 1;
    min-width: 0;
    height: 6px;
    -webkit-appearance: none;
    appearance: none;
    background: linear-gradient(
        to right,
        var(--realistec-primary, #8b5cf6) 0%,
        var(--realistec-primary-hover, #6366f1) var(--range-pct, 100%),
        rgba(139, 92, 246, 0.2) var(--range-pct, 100%),
        rgba(139, 92, 246, 0.2) 100%
    );
    border-radius: 4px;
    outline: none;
    cursor: pointer;
    margin: 0;
}

.realistec-stereo-hist-filter-strength-row input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--realistec-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    cursor: pointer;
    border: 2px solid white;
    box-shadow: 0 2px 6px rgba(139, 92, 246, 0.5), 0 1px 3px rgba(0, 0, 0, 0.2);
}

.realistec-stereo-hist-filter-strength-row input[type="range"]::-moz-range-thumb {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--realistec-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    cursor: pointer;
    border: 2px solid white;
    box-shadow: 0 2px 6px rgba(139, 92, 246, 0.5), 0 1px 3px rgba(0, 0, 0, 0.2);
}

#hist-filter-strength-value {
    flex-shrink: 0;
    min-width: 34px;
    text-align: right;
    font-size: 12px;
    color: var(--realistec-text-secondary, #a8a3c9);
}

.realistec-stereo-hist-sidebar-control-group {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
}

.realistec-stereo-hist-sidebar-control-group select {
    width: 100%;
    padding: 6px 8px;
    border: 1px solid var(--realistec-border, #1f1b3a);
    border-radius: 6px;
    font-size: 13px;
    background: var(--realistec-surface, #0d0b1f);
    /* Same color/color-scheme/accent-color treatment as the Aspect Ratio
       dropdown above — keeps both selects consistent with the Immersity
       plugin's dropdown styling. See that block for full rationale. */
    color: var(--realistec-text, #f5f3ff);
    font-family: inherit;
    cursor: pointer;
    accent-color: var(--rt-violet, #8b5cf6);
    color-scheme: dark;
}

.realistec-stereo-hist-sidebar-control-group select option {
    background-color: #14112b;
    color: #f5f3ff;
}

.realistec-stereo-hist-sidebar-control-group select option:checked,
.realistec-stereo-hist-sidebar-control-group select option:hover {
    background-color: #2a2454;
    color: #ffffff;
}

.realistec-stereo-hist-sidebar-control-group select:focus {
    outline: none;
    border-color: var(--realistec-primary, #8b5cf6);
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.15);
}

/* ---- Main content area ---- */
.realistec-stereo-hist-main {
    flex: 1;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: 24px;
    overflow-y: auto;
    /* Belt-and-suspenders backdrop. The parent .realistec-stereo-hist-modal-content already
       sets the deep --modal-bg, so this would technically inherit. Setting
       it explicitly here defends against any future intermediate wrapper
       being added between content and main, AND makes the deep-backdrop
       intent obvious to anyone reading just this rule. Same color value
       as the parent — no double-painting concern, just redundancy. */
    background: var(--modal-bg, #07060f);
}

/* ---- Loading overlay — covers the entire realistec-stereo-hist-modal-content during filter computation ---- */
.realistec-stereo-hist-loading-overlay {
    display: none;
    position: absolute;
    inset: 0;
    background: rgba(128, 128, 128, 0.5);
    z-index: 9999;
    align-items: center;
    justify-content: center;
    border-radius: 12px;
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
}

.realistec-stereo-hist-spinner {
    width: 44px;
    height: 44px;
    border: 4px solid rgba(139, 92, 246, 0.25);
    border-top-color: var(--realistec-primary, #8b5cf6);
    border-radius: 50%;
    animation: hist-spin 0.75s linear infinite;
    box-shadow: 0 2px 12px rgba(139, 92, 246, 0.3);
}

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

/* Compare Container — now shows histograms as primary */
.realistec-stereo-hist-compare-container {
    position: relative;
    /* Deep dark backdrop for the histogram canvas. Was originally #1a1a1a
       in the pre-restyle plugin (a near-black). The bulk hex-to-token
       substitution mapped it to --realistec-text by mistake — the color
       happened to fall in the script's "dark-text-on-light-bg" map even
       though the role here was "dark-background-on-dark-theme". The
       resulting near-white background was the brightest surface in the
       whole modal and made the histogram data lines (white at low alpha
       with a black drop-shadow, optimized for a DARK backdrop) almost
       invisible. Using --realistec-bg (the deepest --rt-bg cosmic backdrop)
       restores the intended contrast. */
    background: var(--realistec-bg, #07060f);
    border-radius: 8px;
    overflow: hidden;
    cursor: col-resize;
    user-select: none;
    -webkit-user-select: none;
    flex: 1;
    min-height: 0;
    margin-bottom: 20px;
}

/* Tonal zone labels — five evenly-spaced guides at the top of the histogram.
   Mirrors .realistec-stereo-film-color-zone-labels / .realistec-stereo-film-color-zone-label exactly. */
.realistec-stereo-hist-compare-container .realistec-stereo-hist-tone-labels {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    display: flex;
    justify-content: space-between;
    pointer-events: none;
    z-index: 1;
    padding: 0 2px;
}

.realistec-stereo-hist-compare-container .realistec-stereo-hist-tone-label {
    flex: 1;
    text-align: center;
    font-size: 10px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.55);
    padding: 5px 2px 4px;
    letter-spacing: 0.3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
}

.realistec-stereo-hist-compare-container .realistec-stereo-hist-tone-label:first-child { text-align: left;  padding-left:  10px; }
.realistec-stereo-hist-compare-container .realistec-stereo-hist-tone-label:last-child  { text-align: right; padding-right: 10px; }

#hist-compare-canvas {
    display: block;
    width: 100%;
    height: auto;
}

.realistec-stereo-hist-slider-line {
    /* Vertical divider line down the histogram comparator. Was a flat
       white line at 0.7 alpha — readable but generic. Brand-tinted
       version uses the violet accent at moderate alpha so the divider
       reads as part of the modal's brand language while still standing
       out against the dark histogram backdrop. */
    position: absolute;
    top: 0;
    bottom: 0;
    left: 50%;
    width: 2px;
    background: rgba(139, 92, 246, 0.65);
    box-shadow: 0 0 6px rgba(0, 0, 0, 0.5);
    pointer-events: none;
    z-index: 2;
}

.realistec-stereo-hist-slider-handle {
    /* Drag handle on the comparator divider. Uses --modal-surface (= --rt-bg-3)
       so the handle reads as a recessed surface against the modal body,
       plus a 1px violet border so the affordance is visible without being
       loud. Was --realistec-surface (no border) — that token isn't
       defined inside the portaled .realistec-stereo-hist-modal scope so it was falling
       back to the hardcoded value, and the lack of border made the
       handle blend into the comparator backdrop at certain split positions. */
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 36px;
    height: 36px;
    background: var(--modal-surface, #14112e);
    border: 1px solid var(--modal-accent, #8b5cf6);
    border-radius: 50%;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.4),
                0 0 0 4px rgba(139, 92, 246, 0.12);
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    z-index: 3;
}

.realistec-stereo-hist-slider-arrows {
    /* Triangle arrows ◀ ▶ inside the comparator handle. Two issues this
       rule addresses:

       1. Color: was --realistec-text (near-white) but the arrows appear
          default-blue on macOS/iOS because U+25C0 (BLACK LEFT-POINTING
          TRIANGLE) and U+25B6 (BLACK RIGHT-POINTING TRIANGLE) default to
          EMOJI presentation on those systems — the OS renders them as
          colorful glyphs that ignore CSS `color`. Forcing text presentation
          (see #2) lets the violet color win.

       2. Presentation: font-variant-emoji: text declaratively requests
          text-style rendering for these codepoints. Browser support is
          uneven — Firefox 108+ and Chrome 131+ honor it, Safari doesn't
          yet — so the JS markup also appends \uFE0E (variation selector
          for text presentation) after each glyph as a belt-and-suspenders
          fix. Either approach alone covers most browsers; together they
          cover everything modern.

       Color is --modal-text (the histogram modal's --modal-* scope, set
       on .realistec-stereo-hist-modal). Resolves to --rt-text via the modal layer —
       slightly off-white, reads as "subtle UI affordance" against the
       dark handle circle without competing with the histogram canvas. */
    font-size: 10px;
    color: var(--modal-text, #f5f3ff);
    letter-spacing: 2px;
    font-variant-emoji: text;
    /* Sans-serif keeps the triangles geometric — some serif fallbacks
       on Windows render U+25C0/25B6 with subtle outlines that look off
       at this size. */
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI Symbol', 'Helvetica Neue', Arial, sans-serif;
    user-select: none;
}

.realistec-stereo-hist-img-label {
    position: absolute;
    bottom: 10px;
    padding: 4px 12px;
    background: rgba(0, 0, 0, 0.6);
    color: white;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 600;
    pointer-events: none;
    z-index: 1;
}

.realistec-stereo-hist-label-left {
    left: 12px;
}

.realistec-stereo-hist-label-right {
    right: 12px;
}

/* Image Previews — secondary view below histograms */
.realistec-stereo-hist-image-previews {
    display: flex;
    flex-direction: column;
    gap: 10px;
    flex: 1;
    min-height: 0;
}

.realistec-stereo-hist-image-previews-header {
    margin: 0;
    font-size: 12px;
    font-weight: 500;
    color: var(--realistec-text-secondary, #a8a3c9);
    text-align: center;
    flex-shrink: 0;
}

.realistec-stereo-hist-image-panels-row {
    display: flex;
    flex: 1;
    min-height: 0;
    /* 24px gap matches .realistec-stereo-hist-main's padding-left and padding-right, so
       the spacing AROUND the two panels (left of left panel, right of
       right panel) and the spacing BETWEEN them reads as a single
       consistent border. Was previously gap: 0 — the panels were flush
       against each other to give the now-removed .realistec-stereo-hist-or-badge a visual
       slot to sit in. With the badge gone the panels collapsed flush
       against each other, which made the inner border look thicker than
       the outer borders and broke the visual rhythm. */
    gap: 24px;
    align-items: stretch;
    position: relative;
}

.realistec-stereo-hist-image-panel {
    /* Thumbnail card. Was --realistec-surface (a plugin-scoped token that
       doesn't reach this portaled modal — fell back to its hardcoded
       value). Switching to --modal-surface keeps the card visually
       elevated above the deeper --modal-bg body, gives the user a clear
       "selectable card on a backdrop" affordance, and references the
       modal's own variable scope. The selected-vs-resting distinction is
       carried by the violet border + glow rather than by alternating
       surface tones, so resting and selected states share one background
       — same brand pattern used by .realistec-stereo-type-card elsewhere. */
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    background: var(--modal-surface, #14112e);
    border: 2px solid var(--modal-border, #1f1b3a);
    border-radius: 8px;
    padding: 8px 8px 6px;
    overflow: hidden;
    cursor: pointer;
    transition: border-color 0.2s, box-shadow 0.2s;
}

.realistec-stereo-hist-image-panel:hover {
    border-color: var(--modal-accent, #8b5cf6);
}

.realistec-stereo-hist-image-panel.realistec-stereo-hist-panel-selected {
    border-color: var(--modal-accent, #8b5cf6);
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.2);
    /* Resting and selected cards share a single background (--modal-surface)
       — the selection state is signaled by the violet ring above. The
       previous version flipped to --realistec-surface-2 on selection,
       which produced two card tones that looked nearly identical (because
       both fallback values were close on the cosmic palette) and the
       selection state read mostly through the border anyway. */
    background: var(--modal-surface, #14112e);
}

.realistec-stereo-hist-image-panel img {
    width: 100%;
    flex: 1;
    min-height: 0;
    object-fit: contain;
    border-radius: 4px;
    /* Letterbox color — transparent so the parent panel's surface shows
       through the negative space left by `object-fit: contain`. Was
       previously --realistec-text (near-white), which read as a hard
       light-theme rectangle around portrait/non-square images on the
       dark UI. Using transparent also means the selected-state surface
       change (--realistec-surface → --realistec-surface-2 on the parent)
       shows through the letterbox area, so a selected panel and its
       letterbox stay visually unified. */
    background: transparent;
}

.realistec-stereo-hist-frame-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--realistec-text-secondary, #a8a3c9);
    text-transform: uppercase;
    letter-spacing: 0.4px;
    flex-shrink: 0;
}

.realistec-stereo-hist-panel-selected .realistec-stereo-hist-frame-label {
    color: var(--realistec-primary, #8b5cf6);
}

/* Footer */
.realistec-stereo-hist-modal-footer {
    /* Same surface tone as the header and sidebar (--modal-surface =
       --rt-bg-3) so the modal's "elevated chrome" — header, sidebar,
       footer, thumbnail cards — all read as one consistent layer
       sitting above the deep --modal-bg body. Was previously the
       plugin-scoped --realistec-surface, which falls back to --rt-bg-2
       outside the .realistec-stereo-upload-interface scope: subtly different
       from --modal-surface and broke the unified-elevation effect. */
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding: 12px 20px;
    background: var(--modal-surface, #14112e);
    border-top: 1px solid var(--modal-border, #1f1b3a);
    flex-shrink: 0;
}

.realistec-stereo-hist-modal-footer-actions {
    display: flex;
    gap: 10px;
}

.realistec-stereo-hist-btn-primary {
    /* Mirrors Immersity's #realistec-mono-color-filter-modal .realistec-stereo-hist-btn-primary.
       Was previously a SOLID --realistec-link (#a78bfa, the LIGHTER violet)
       at rest, then darkened to --realistec-primary (#8b5cf6) on hover —
       which produced an inverted "press makes it look pressed-out" feel.
       The brand pattern is gradient → lighter gradient: violet→indigo at
       rest, lighter violet→indigo on hover, plus a soft drop shadow that
       grows to signal interactivity. */
    padding: 8px 20px;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s;
    border: none;
    font-family: inherit;
    background: var(--modal-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    color: white;
    box-shadow: 0 2px 8px rgba(139, 92, 246, 0.25);
}

.realistec-stereo-hist-btn-primary:hover {
    background: var(--modal-gradient-hover, linear-gradient(135deg, #a78bfa 0%, #818cf8 100%));
    box-shadow: 0 4px 14px rgba(139, 92, 246, 0.4);
}

/* Suppress the browser-default focus outline on click. The theme's
   style.css applies `outline: 2px solid var(--rt-violet)` to every
   button:focus globally (line 196 of style.css), and that rule has no
   carve-out for plugin modals — so clicking the Apply Changes button
   was painting a hard 2px ring on every press, which read as a border
   flash because the click + focus + transition stack rendered a single
   frame of the ring before the click released. Same fix pattern Immersity
   uses on its modal-close button (which has the same root cause).

   :focus alone covers mouse clicks (which shouldn't show a ring);
   :focus-visible adds a keyboard-only ring back, so accessibility is
   preserved. Specificity (0,2,0) beats the theme's button:focus
   (0,1,1) without needing !important. The keyboard ring uses a soft
   violet box-shadow rather than outline so it animates with the
   button's existing `transition: all 0.2s`. */
.realistec-stereo-hist-btn-primary:focus {
    outline: none;
}

.realistec-stereo-hist-btn-primary:focus-visible {
    outline: none;
    box-shadow: 0 4px 14px rgba(139, 92, 246, 0.4),
                0 0 0 3px rgba(139, 92, 246, 0.35);
}

.realistec-stereo-hist-btn-secondary {
    /* Mirrors Immersity's #realistec-mono-color-filter-modal .realistec-stereo-hist-btn-secondary.
       Was previously border: none with no border-color shift on hover —
       the button blended into the surrounding modal footer surface. The
       brand pattern is solid surface-2 background with a 1px border that
       shifts to brand violet on hover, so the button reads as "outlined
       button" rather than "blob on a panel". */
    padding: 8px 20px;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s;
    border: 1px solid var(--modal-border, #1f1b3a);
    font-family: inherit;
    background: var(--modal-surface, #14112e);
    color: var(--modal-text, #f5f3ff);
}

.realistec-stereo-hist-btn-secondary:hover {
    background: var(--modal-border, #1f1b3a);
    border-color: var(--modal-accent, #8b5cf6);
    /* Preserve resting text color — without this, the theme's button:hover
       rule (style.css line 660) would set color:#fff !important. That's
       fine here since the bg is also dark, but explicit is safer in case
       the theme rule's specificity changes. Same trick the Immersity
       reference uses (with the same comment). */
    color: var(--modal-text, #f5f3ff);
}

/* Same click-flash suppression as .realistec-stereo-hist-btn-primary above — see that
   block for the full rationale. The keyboard ring uses a violet
   box-shadow that respects the secondary button's resting border, so
   the ring sits OUTSIDE the existing 1px border without erasing it
   (unlike `outline` which would draw on top). */
.realistec-stereo-hist-btn-secondary:focus {
    outline: none;
}

.realistec-stereo-hist-btn-secondary:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.30);
}

.realistec-stereo-hist-btn-reference {
    padding: 10px 20px;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s;
    border: 2px solid var(--realistec-primary, #8b5cf6);
    background: var(--realistec-surface, #0d0b1f);
    color: var(--realistec-primary, #8b5cf6);
}

.realistec-stereo-hist-btn-reference:hover {
    background: var(--realistec-primary, #8b5cf6);
    color: white;
}

.realistec-stereo-hist-btn-reference:active {
    transform: scale(0.97);
}

/* =============================================
   CUSTOM CROP OPTION
   ============================================= */

.realistec-stereo-custom-crop-option {
    margin: 20px 0;
    padding: 15px;
    background: var(--realistec-surface, #0d0b1f);
    border: 1px solid var(--realistec-border, #1f1b3a);
    border-radius: 8px;
    display: none; /* Hidden by default, shown when standard type selected */
}

.realistec-stereo-standard-upload ~ .realistec-stereo-custom-crop-option,
.realistec-stereo-upload-interface[data-upload-type="standard"] .realistec-stereo-custom-crop-option {
    display: block;
}

.realistec-stereo-custom-crop-option.enabled {
    background: var(--realistec-surface-2, #14112e);
    border-color: var(--realistec-link, #a78bfa);
}

.realistec-stereo-custom-crop-option label {
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    font-weight: 500;
}

.realistec-stereo-custom-crop-option input[type="checkbox"] {
    width: 18px;
    height: 18px;
    cursor: pointer;
}

.realistec-stereo-crop-description {
    margin-top: 8px;
    font-size: 13px;
    color: var(--realistec-text-secondary, #a8a3c9);
    margin-left: 28px;
}

.realistec-stereo-crop-indicator {
    display: inline-block;
    margin-left: 15px;
    padding: 4px 10px;
    background: var(--realistec-success, #10b981);
    color: white;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 500;
}

.realistec-stereo-edit-crop-btn {
    margin-left: 10px;
    padding: 4px 12px;
    background: var(--realistec-surface-2, #14112e);
    color: white;
    border: none;
    border-radius: 4px;
    font-size: 12px;
    cursor: pointer;
    transition: background 0.2s;
}

.realistec-stereo-edit-crop-btn:hover {
    background: var(--realistec-border, #1f1b3a);
}

/* =============================================
   MATCH COLOR OPTION - NEW
   ============================================= */

.realistec-stereo-match-color-option {
    margin: 20px 0;
    padding: 15px;
    background: var(--realistec-surface, #0d0b1f);
    border: 1px solid var(--realistec-border, #1f1b3a);
    border-radius: 8px;
    display: none; /* Hidden by default, shown via JS when files uploaded */
}

.realistec-stereo-match-color-option.enabled {
    /* Amber warning tint stays hardcoded — there's no theme token for
       a warning/caution color. Background uses the dark amber tint
       (#3a2a1a) already used elsewhere in the file for the same
       purpose, so it reads on the dark cosmic surfaces. */
    background: #3a2a1a;
    border-color: #e67e22;
}

.realistec-stereo-match-color-label {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
}

.realistec-stereo-match-color-title {
    font-weight: 600;
    font-size: 14px;
    color: var(--realistec-text, #f5f3ff);
}

.realistec-stereo-match-color-help {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    background: var(--realistec-surface-2, #14112e);
    color: white;
    border-radius: 50%;
    font-size: 11px;
    font-weight: bold;
    cursor: help;
    transition: background 0.2s;
}

.realistec-stereo-match-color-help:hover {
    /* Was --realistec-text (near-white) which made the white "?" glyph
       invisible against the hover background. Same kind of light-theme
       leak as the histogram comparator — bulk substitution mapped a
       hover-color hex to a text token by mistake. Use the brand violet
       at low alpha so the hover state reads as "interactive" while
       keeping the white glyph readable. */
    background: rgba(139, 92, 246, 0.4);
}

.realistec-stereo-match-color-selector {
    display: flex;
    gap: 15px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}

.realistec-stereo-match-color-radio {
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    padding: 8px 14px;
    background: var(--realistec-surface, #0d0b1f);
    border: 1px solid var(--realistec-border, #1f1b3a);
    border-radius: 6px;
    transition: all 0.2s;
}

.realistec-stereo-match-color-radio:hover {
    border-color: var(--realistec-text-secondary, #a8a3c9);
    background: var(--realistec-surface, #0d0b1f);
}

.realistec-stereo-match-color-radio input[type="radio"] {
    width: 16px;
    height: 16px;
    margin: 0;
    cursor: pointer;
}

.realistec-stereo-match-color-radio input[type="radio"]:checked + .realistec-stereo-radio-label {
    font-weight: 600;
    color: #e67e22;
}

.realistec-stereo-match-color-radio:has(input[type="radio"]:checked) {
    border-color: #e67e22;
    background: #3a2a1a;
}

.realistec-stereo-radio-label {
    font-size: 13px;
    color: var(--realistec-text, #f5f3ff);
    white-space: nowrap;
}

.realistec-stereo-match-color-description {
    font-size: 12px;
    color: var(--realistec-text-secondary, #a8a3c9);
    margin: 0;
    line-height: 1.5;
}

/* Match Color Indicator when enabled */
.realistec-stereo-match-color-option.enabled .realistec-stereo-match-color-label::after {
    /* Material Symbols 'check' ligature replaces the previous Unicode ✓
       for consistency with the rest of the plugin's icon family. The
       font-family declaration activates the Material Symbols font on this
       pseudo-element only — same approach used by .realistec-stereo-previews-hint::before
       and .realistec-stereo-upload-header h3::before. The ligature feature is
       enabled explicitly so 'check' is substituted for the icon glyph
       rather than rendered as the literal text "check" on browsers that
       don't honor 'liga' by default. The amber background stays
       hardcoded — there's no theme token for warning amber and the
       existing dark-theme-amber-tint pattern (#e67e22 / #3a2a1a) is
       used elsewhere in this file for the same purpose. */
    content: 'check';
    font-family: 'Material Symbols Outlined';
    font-weight: normal;
    font-style: normal;
    text-transform: none;
    letter-spacing: normal;
    font-feature-settings: 'liga';
    -webkit-font-feature-settings: 'liga';
    font-variant-ligatures: common-ligatures;
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    background: #e67e22;
    color: white;
    border-radius: 50%;
    /* 14px glyph in a 20px container reads cleanly without crowding the
       circle's edge — Material Symbols' default font-size: 24 would
       overflow the circle bounds. */
    font-size: 14px;
    margin-left: auto;
}

/* =============================================
   CROP MODAL OVERLAY
   ============================================= */

.realistec-stereo-crop-modal {
    /* Modal-scoped variable layer — mirrors the Immersity plugin's
       `.realistec-mono-modal` declarations so the Crop modal and the
       Immersity Edit Depth modal stay visually identical. Each --modal-*
       token aliases a theme `--rt-*` token (so a palette change in
       style.css propagates here automatically) with a hardcoded fallback
       after the comma for the case where the theme is unavailable.

       Mapping (kept aligned with Immersity for cross-plugin consistency):
       --modal-bg      -> --rt-bg-2   (modal body, sidebar, footer)
       --modal-surface -> --rt-bg-3   (header, slightly elevated areas)
       --modal-border  -> #1f1b3a     (hardcoded — theme's --rt-border is rgba)
       --modal-text    -> --rt-text
       --modal-text-secondary -> --rt-text-muted
       --modal-accent  -> --rt-violet (solid violet for handles, indicators)
       --modal-gradient        -> --rt-gradient (CTA buttons)
       --modal-gradient-hover  -> --rt-gradient-hover */
    --modal-bg: var(--rt-bg-2, #0d0b1f);
    --modal-surface: var(--rt-bg-3, #14112e);
    --modal-border: #1f1b3a;
    --modal-text: var(--rt-text, #f5f3ff);
    --modal-text-secondary: var(--rt-text-muted, #a8a3c9);
    --modal-accent: var(--rt-violet, #8b5cf6);
    --modal-gradient: var(--rt-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    --modal-gradient-hover: var(--rt-gradient-hover, linear-gradient(135deg, #a78bfa 0%, #818cf8 100%));

    display: none;
    position: fixed;
    inset: 0;
    z-index: 999999;
    background: rgba(0, 0, 0, 0.8);
    backdrop-filter: blur(4px);
    align-items: center;
    justify-content: center;
    overflow-y: auto;
    box-sizing: border-box;
    opacity: 0;
    transition: opacity 0.3s ease;
}

.realistec-stereo-crop-modal.active {
    display: flex;
    opacity: 1;
    align-items: center;
    justify-content: center;
}

.realistec-stereo-crop-modal-content {
    /* Modal body uses --modal-bg (= --rt-bg-2) — the deeper of the two
       modal surface tokens. Sub-regions like the header use the lighter
       --modal-surface (= --rt-bg-3) to create vertical separation. */
    background: var(--modal-bg, #0d0b1f);
    border-radius: 12px;
    width: 95vw;
    max-width: 1200px;
    height: 90vh;
    max-height: 800px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    transform: scale(0.95) translateY(-20px);
    transition: transform 0.3s ease;
    flex-shrink: 0;
}

.realistec-stereo-crop-modal.active .realistec-stereo-crop-modal-content {
    transform: scale(1) translateY(0);
}

/* ---- Header ---- */
.realistec-stereo-crop-modal-header {
    /* Mirrors the Immersity .realistec-mono-modal-header — uses
       --modal-surface (= --rt-bg-3) so the header sits a step lighter
       than the modal body (--modal-bg = --rt-bg-2). Was previously bound
       to --realistec-surface (= --rt-bg-2), which made the header and
       body identical and removed the visual separation. */
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 14px 20px;
    background: var(--modal-surface, #14112e);
    border-bottom: 1px solid var(--modal-border, #1f1b3a);
    flex-shrink: 0;
    gap: 12px;
    position: relative;
}

.realistec-stereo-crop-modal-header-left {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: 1;
    min-width: 0;
}

.realistec-stereo-crop-modal-header h3 {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
    color: var(--modal-text, #f5f3ff);
    white-space: nowrap;
    /* Display font — see .realistec-stereo-hist-modal-header h3 above for the rationale
       (portaled modal, doesn't inherit the .realistec-upload-interface-
       scoped display-font rule). */
    font-family: var(--rt-font-display, 'Space Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
    letter-spacing: -0.01em;
}

/* Mode tabs — pill group matching film plugin exactly */
.realistec-stereo-crop-mode-tabs {
    display: flex;
    gap: 4px;
    background: var(--realistec-surface-2, #14112e);
    border-radius: 8px;
    padding: 3px;
}

.realistec-stereo-crop-mode-tab {
    padding: 6px 16px;
    font-size: 13px;
    font-weight: 500;
    color: var(--realistec-text-secondary, #a8a3c9);
    background: transparent;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    transition: all 0.2s ease;
    white-space: nowrap;
    font-family: inherit;
}

.realistec-stereo-crop-mode-tab:hover {
    color: var(--realistec-text, #f5f3ff);
    background: rgba(139, 92, 246, 0.1);
}

/* Suppress the browser-default focus outline on click. The outline was
   producing a brief white flash because outline doesn't participate in
   the tab's `transition: all 0.2s ease` and renders before the .active
   class is applied via JS — same bug class fixed on .realistec-stereo-type-options
   earlier in this file. The mobile blue tap-highlight is handled by the
   global -webkit-tap-highlight-color reset elsewhere. */
.realistec-stereo-crop-mode-tab:focus {
    outline: none;
}

/* Keyboard-only focus indicator — implemented as box-shadow rather than
   outline so it animates with the tab's existing transition and matches
   the .active state's violet language. :focus-visible only triggers on
   keyboard navigation, not mouse clicks, so this is the correct
   accessibility behavior — mouse users don't see a focus ring on click. */
.realistec-stereo-crop-mode-tab:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.25);
}

.realistec-stereo-crop-mode-tab.active {
    color: white;
    background: var(--realistec-primary, #8b5cf6);
}

/* When a tab is both focused AND active, layer a slightly stronger
   focus ring on top of the active state so the focus indicator stays
   distinguishable from the selected state for keyboard users. */
.realistec-stereo-crop-mode-tab.active:focus-visible {
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.4);
}

.realistec-stereo-crop-close-btn {
    background: none;
    border: none;
    font-size: 24px;
    color: var(--realistec-text-secondary, #a8a3c9);
    cursor: pointer;
    padding: 0;
    line-height: 1;
    transition: color 0.2s;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
}

.realistec-stereo-crop-close-btn:hover {
    color: var(--realistec-error, #ef4444);
    background: rgba(239, 68, 68, 0.1);
}

/* ---- Body: viewport + sidebar ---- */
.realistec-stereo-crop-modal-body {
    display: flex;
    flex: 1;
    min-height: 0;
    overflow: hidden;
}

.realistec-stereo-crop-editor-viewport {
    flex: 1;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: 16px;
    gap: 0;
    overflow: hidden;
    position: relative;
}

/* ---- Canvas Container — position:relative for realistec-stereo-crop-box handles ---- */
.realistec-stereo-crop-canvas-container {
    position: relative;
    display: flex;
    justify-content: center;
    align-items: flex-start;
    border-radius: 8px;
    padding: 10px;
    min-height: 200px;
    flex: none;
    width: 100%;
    box-sizing: border-box;
    border: 1px solid var(--realistec-surface-2, #14112e);
    overflow: hidden;
    /* Checkerboard pattern — dark cosmic tones, matching the Immersity
       plugin's canvas wrapper. Was originally a light gray-on-gray
       checker (#d5d8dc on #e8eaed) which the bulk color substitution
       mapped to surface tokens that read as light lavender. Hardcoded
       here because there are no theme tokens for "alpha-channel grid
       darker stripe / lighter base" and the values need to be tuned
       together as a pair. */
    background-image:
        linear-gradient(45deg, #161a26 25%, transparent 25%),
        linear-gradient(-45deg, #161a26 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, #161a26 75%),
        linear-gradient(-45deg, transparent 75%, #161a26 75%);
    background-color: #12151f;
    background-size: 20px 20px;
    background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
}

#crop-canvas {
    display: block;
    max-width: 100%;
    border-radius: 4px;
}

/* ---- Align panel: always show border-bottom ---- */
#crop-align-panel {
    border-bottom: 1px solid var(--realistec-border, #1f1b3a);
}

/* ---- Crop panel: always show border-bottom ---- */
#crop-crop-panel {
    border-bottom: 1px solid var(--realistec-border, #1f1b3a);
}

/* ---- Frame scrubber group: border-bottom divider ---- */
.realistec-stereo-frame-scrubber-group {
    border-bottom: 1px solid var(--realistec-border, #1f1b3a);
    padding-bottom: 12px;
}

/* ---- Close button ---- */
.realistec-stereo-crop-close-btn-abs {
    flex-shrink: 0;
}

/* ---- Sidebar ---- */
.realistec-stereo-crop-editor-sidebar {
    /* Mirrors the Immersity .realistec-mono-editor-sidebar — uses
       --modal-bg (= --rt-bg-2) so the sidebar matches the modal body's
       deeper surface. The header (above) uses --modal-surface so the
       horizontal band between header and sidebar reads as a step change.
       Was previously --realistec-surface (also --rt-bg-2 in the resolved
       value) but bound to the plugin scope; switching to --modal-bg
       keeps the variable reference consistent with the Immersity plugin. */
    width: 260px;
    flex-shrink: 0;
    background: var(--modal-bg, #0d0b1f);
    border-left: 1px solid var(--modal-border, #1f1b3a);
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    overflow-x: hidden;
}

.realistec-stereo-crop-editor-sidebar::-webkit-scrollbar { width: 6px; }
.realistec-stereo-crop-editor-sidebar::-webkit-scrollbar-track { background: transparent; }
.realistec-stereo-crop-editor-sidebar::-webkit-scrollbar-thumb { background: var(--modal-border, #1f1b3a); border-radius: 3px; }
.realistec-stereo-crop-editor-sidebar::-webkit-scrollbar-thumb:hover { background: var(--modal-text-secondary, #a8a3c9); }

.realistec-stereo-crop-sidebar-section {
    padding: 16px;
    border-bottom: 1px solid var(--realistec-border, #1f1b3a);
}

.realistec-stereo-crop-sidebar-section:last-child {
    border-bottom: none;
}

.realistec-stereo-crop-sidebar-section-title {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--realistec-text-secondary, #a8a3c9);
    margin: 0 0 12px 0;
}

/* Controls inside sidebar stack vertically */
.realistec-stereo-crop-editor-sidebar .realistec-stereo-crop-control-group {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    margin-bottom: 12px;
}

.realistec-stereo-crop-editor-sidebar .realistec-stereo-crop-control-group:last-child {
    margin-bottom: 0;
}

.realistec-stereo-crop-editor-sidebar .realistec-stereo-crop-control-group label,
.realistec-stereo-crop-editor-sidebar .realistec-stereo-crop-control-group .realistec-stereo-crop-frame-label-right {
    font-size: 12px;
    font-weight: 500;
    color: var(--realistec-text-secondary, #a8a3c9);
    white-space: nowrap;
}

.realistec-stereo-crop-editor-sidebar .realistec-stereo-crop-control-group select {
    /* Mirrors the Immersity .realistec-mono-crop-control-group select.
       Three notable differences vs. a default <select>:

       1. text-overflow: ellipsis — selects don't ellipsize by default
          when the selected option's text is wider than the control.
          Without this, long labels (e.g. "21:9 (Cinematic Ultrawide)")
          render their tail clipped behind the OS down-caret. The
          ellipsis makes the truncation visible and readable.

       2. flex/min-width: 0 — lets the select shrink inside its flex
          parent (.realistec-stereo-crop-control-group) so the ellipsis actually
          activates. Without min-width: 0 the select would refuse to
          shrink below its content width and overflow the panel.

       3. appearance: auto — explicit so the OS-native caret renders.
          Some user agents inherit appearance: none from cascade and
          would drop the caret entirely; setting it explicitly here
          locks in the expected widget chrome.

       Variable references match the modal scope declared on .realistec-stereo-crop-modal
       (--modal-surface, --modal-border, --modal-text, --modal-accent)
       so the dropdown stays in sync with the rest of the modal. */
    flex: 1;
    min-width: 0;
    max-width: 100%;
    width: 100%;
    padding: 6px 8px;
    border: 1px solid var(--modal-border, #1f1b3a);
    border-radius: 6px;
    font-size: 13px;
    background: var(--modal-surface, #14112e);
    color: var(--modal-text, #f5f3ff);
    font-family: inherit;
    cursor: pointer;
    transition: border-color 0.2s ease;
    appearance: auto;
    text-overflow: ellipsis;
    /* accent-color retints the OS-rendered option list highlight in
       modern Chromium so the selected/hovered row uses brand violet
       instead of system blue. Older browsers ignore it gracefully.
       References --rt-violet (theme :root token) so a palette change
       in the theme propagates here automatically. */
    accent-color: var(--rt-violet, #8b5cf6);
    /* color-scheme: dark hints the UA to render its own form controls
       (chevron, popup chrome) in dark mode where supported, which
       prevents the popup from rendering with a hard light background. */
    color-scheme: dark;
}

/* Option list theming. <option> elements only respect a small subset of
   CSS — Chrome and Firefox honor background-color and color, Safari
   doesn't (it uses OS chrome regardless). These rules give the popup a
   dark surface with brand text in supporting browsers. Hardcoded values
   are used because var() is not honored on <option> in some browsers. */
.realistec-stereo-crop-editor-sidebar .realistec-stereo-crop-control-group select option {
    background-color: #14112b;
    color: #f5f3ff;
}

.realistec-stereo-crop-editor-sidebar .realistec-stereo-crop-control-group select option:checked,
.realistec-stereo-crop-editor-sidebar .realistec-stereo-crop-control-group select option:hover {
    /* Selected/hovered option — brand violet at low alpha so the row
       reads as highlighted without overpowering the popup. Matches the
       Immersity option:checked/option:hover treatment. */
    background-color: #2a1f5a;
    color: #f5f3ff;
}

.realistec-stereo-crop-editor-sidebar .realistec-stereo-crop-control-group select:focus {
    outline: none;
    border-color: var(--modal-accent, #8b5cf6);
    /* Brand violet focus ring — matches the focus treatment used
       elsewhere in the plugin and on the Immersity reference. */
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.20);
}

.realistec-stereo-crop-editor-sidebar .realistec-stereo-crop-control-group input[type="range"] {
    width: 100%;
    cursor: pointer;
}

#crop-opacity-value {
    font-size: 12px;
    color: var(--realistec-text-secondary, #a8a3c9);
}

/* Opacity control: slider + value on the same row */
.realistec-stereo-crop-opacity-row {
    flex-direction: row !important;
    align-items: center !important;
    gap: 8px !important;
    margin-bottom: 0 !important;
}

.realistec-stereo-crop-opacity-row input[type="range"] {
    flex: 1;
    min-width: 0;
    /* Brand-violet track + thumb — without this, the browser falls back
       to the default OS slider styling (light blue track, light gray
       thumb) which clashes with the dark cosmic surface. Mirrors the
       gradient track used by the alignment sliders elsewhere in the file. */
    height: 6px;
    -webkit-appearance: none;
    appearance: none;
    background: linear-gradient(
        to right,
        var(--realistec-primary, #8b5cf6) 0%,
        var(--realistec-primary-hover, #6366f1) var(--range-pct, 50%),
        rgba(139, 92, 246, 0.2) var(--range-pct, 50%),
        rgba(139, 92, 246, 0.2) 100%
    );
    border-radius: 4px;
    outline: none;
    cursor: pointer;
    margin: 0;
}

.realistec-stereo-crop-opacity-row input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--realistec-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    cursor: pointer;
    border: 2px solid white;
    box-shadow: 0 2px 6px rgba(139, 92, 246, 0.5), 0 1px 3px rgba(0, 0, 0, 0.2);
}

.realistec-stereo-crop-opacity-row input[type="range"]::-moz-range-thumb {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--realistec-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    cursor: pointer;
    border: 2px solid white;
    box-shadow: 0 2px 6px rgba(139, 92, 246, 0.5), 0 1px 3px rgba(0, 0, 0, 0.2);
}

.realistec-stereo-crop-opacity-row #crop-opacity-value {
    flex-shrink: 0;
    min-width: 32px;
    text-align: right;
}

/* ---- Crop Box ---- */
.realistec-stereo-crop-box {
    position: absolute;
    border: 2px solid var(--realistec-primary, #8b5cf6);
    box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0);
    cursor: move;
    display: none;
}

/* ---- Rule of thirds ---- */
.realistec-stereo-crop-box::before {
    content: '';
    position: absolute;
    top: 33.33%;
    left: 0;
    right: 0;
    height: 1px;
    background: rgba(255, 255, 255, 0.4);
}

.realistec-stereo-crop-box::after {
    content: '';
    position: absolute;
    top: 66.66%;
    left: 0;
    right: 0;
    height: 1px;
    background: rgba(255, 255, 255, 0.4);
}

.realistec-stereo-crop-box .realistec-stereo-crop-thirds-v1,
.realistec-stereo-crop-box .realistec-stereo-crop-thirds-v2 {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 1px;
    background: rgba(255, 255, 255, 0.4);
}

.realistec-stereo-crop-box .realistec-stereo-crop-thirds-v1 { left: 33.33%; }
.realistec-stereo-crop-box .realistec-stereo-crop-thirds-v2 { left: 66.66%; }

/* ---- Handles ---- */
.realistec-stereo-crop-handle {
    /* Mirrors the Immersity .realistec-mono-crop-handle — a small white
       square with a 2px violet border. The white center is intentional
       (Immersity uses a literal `white`): handles need to be visible
       against ANY canvas content (light photo, dark photo, alpha-checker
       background) and a brand-tinted dark fill would disappear against
       low-key images. The violet border ties them to the brand and
       makes them readable against bright/light photos.

       Hardcoded `white` and the violet hex are kept identical to the
       Immersity reference so the handles look the same in both modals.
       The violet uses --modal-accent (= --rt-violet) so a theme palette
       change still propagates. */
    position: absolute;
    width: 12px;
    height: 12px;
    background: white;
    border: 2px solid var(--modal-accent, #8b5cf6);
    border-radius: 2px;
    pointer-events: auto;
    z-index: 11;
    /* Prevent browser gestures on handles when dragging on touch
       devices — same defensive declaration Immersity uses. */
    touch-action: none;
}

.realistec-stereo-crop-handle-nw { top: -6px; left: -6px; cursor: nw-resize; }
.realistec-stereo-crop-handle-n  { top: -6px; left: 50%; transform: translateX(-50%); cursor: n-resize; }
.realistec-stereo-crop-handle-ne { top: -6px; right: -6px; cursor: ne-resize; }
.realistec-stereo-crop-handle-e  { top: 50%; right: -6px; transform: translateY(-50%); cursor: e-resize; }
.realistec-stereo-crop-handle-se { bottom: -6px; right: -6px; cursor: se-resize; }
.realistec-stereo-crop-handle-s  { bottom: -6px; left: 50%; transform: translateX(-50%); cursor: s-resize; }
.realistec-stereo-crop-handle-sw { bottom: -6px; left: -6px; cursor: sw-resize; }
.realistec-stereo-crop-handle-w  { top: 50%; left: -6px; transform: translateY(-50%); cursor: w-resize; }

/* ---- Crop info bar ---- */
.realistec-stereo-crop-info {
    display: flex;
    justify-content: center;
    gap: 30px;
    font-size: 13px;
    color: var(--realistec-text-secondary, #a8a3c9);
}

.realistec-stereo-crop-info span {
    padding: 5px 10px;
    background: var(--realistec-surface-2, #14112e);
    border-radius: 4px;
}

/* ---- Reset strip — sits between sidebar and footer, always full width ---- */
.realistec-stereo-crop-reset-strip {
    flex-shrink: 0;
    padding: 10px 20px;
    background: var(--realistec-surface, #0d0b1f);
    border-top: 1px solid var(--realistec-border, #1f1b3a);
}

/* Strip only appears on mobile — desktop uses the sidebar Reset section */
@media (min-width: 769px) {
    .realistec-stereo-crop-reset-strip {
        display: none !important;
    }
}

.realistec-stereo-crop-reset-btn-full {
    width: 100%;
    text-align: center;
}

/* ---- Footer ---- */
.realistec-stereo-crop-modal-footer {
    /* Mirrors the Immersity .realistec-mono-modal-footer — uses
       --modal-bg (= --rt-bg-2) so the footer matches the modal body
       and sidebar's deeper surface, with --modal-border on the top edge
       to separate it from the canvas/sidebar above. The resolved color
       was already correct (--realistec-surface and --modal-bg both
       point to --rt-bg-2), but the variable reference is updated to
       --modal-* for consistency with the rest of the modal scope. */
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 20px;
    background: var(--modal-bg, #0d0b1f);
    border-top: 1px solid var(--modal-border, #1f1b3a);
    flex-shrink: 0;
}

.realistec-stereo-crop-info-footer {
    display: flex;
    align-items: center;
    gap: 16px;
    font-size: 12px;
    color: var(--modal-text-secondary, #a8a3c9);
    font-variant-numeric: tabular-nums;
}

#crop-dimensions,
#crop-coordinates {
    display: inline;
}

.realistec-stereo-crop-modal-footer-actions {
    display: flex;
    gap: 10px;
}

.realistec-stereo-crop-btn-primary,
.realistec-stereo-crop-btn-secondary {
    padding: 8px 20px;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s;
    border: none;
    font-family: inherit;
}

.realistec-stereo-crop-btn-primary {
    background: var(--realistec-link, #a78bfa);
    color: white;
}

.realistec-stereo-crop-btn-primary:hover {
    background: var(--realistec-primary, #8b5cf6);
}

.realistec-stereo-crop-btn-secondary {
    /* Modal-footer variant — properties match the main .realistec-stereo-crop-btn-secondary
       rule further down in section 2 of this file (which wins on cascade
       order). Mirrors the Immersity .realistec-mono-modal-btn-secondary
       exactly, using the modal-scoped variables declared on .realistec-stereo-crop-modal:
         background      -> --modal-surface  (= --rt-bg-3)
         color           -> --modal-text     (= --rt-text)
         border          -> --modal-border
         hover bg        -> --modal-border
         hover color     -> --modal-text-secondary  (theme button:hover
                            otherwise sets color:#fff !important which
                            reads poorly on the dark hover background) */
    background: var(--modal-surface, #14112e);
    color: var(--modal-text, #f5f3ff);
    border: 1px solid var(--modal-border, #1f1b3a);
}

.realistec-stereo-crop-btn-secondary:hover {
    background: var(--modal-border, #1f1b3a);
    color: var(--modal-text-secondary, #a8a3c9);
}

/* Click-flash suppression — same pattern as .realistec-stereo-hist-btn-primary /
   .realistec-stereo-hist-btn-secondary in the histogram modal. The theme's global
   `button:focus` rule (style.css line 196) paints a 2px violet outline
   on every button focus, including ours, which reads as a border
   flash on click. :focus removes the ring for mouse clicks;
   :focus-visible restores it for keyboard navigation only. */
.realistec-stereo-crop-btn-primary:focus,
.realistec-stereo-crop-btn-secondary:focus {
    outline: none;
}

.realistec-stereo-crop-btn-primary:focus-visible {
    outline: none;
    /* Primary uses a stronger ring (matches its filled-gradient weight)
       layered on top of the resting drop shadow. The shadow stack mirrors
       what .realistec-stereo-hist-btn-primary uses on hover so the focus state and hover
       state read as related-but-distinct affordances. */
    box-shadow: 0 4px 14px rgba(139, 92, 246, 0.4),
                0 0 0 3px rgba(139, 92, 246, 0.35);
}

.realistec-stereo-crop-btn-secondary:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.30);
}

/* =============================================
   RESPONSIVE ADJUSTMENTS
   ============================================= */

@media (max-width: 768px) {
    .realistec-stereo-crop-modal-header,
    .realistec-stereo-crop-modal-footer {
        padding: 12px 16px;
    }

    /* Adopt the same approach as the FILM plugin which works correctly on mobile:
       - Modal overlay aligns to flex-start so content sits at top, not centred
       - Modal content uses height:auto + max-height, growing to fit content
         rather than forcing content to fill a fixed container
       - Body scrolls internally with overflow-y:auto
       - Viewport uses flex-shrink:0 + min-height so the JS canvas measurement works */

    .realistec-stereo-crop-modal.active {
        align-items: flex-start;
        padding: 10px;
    }

    .realistec-stereo-crop-modal-content {
        position: static;
        width: 100%;
        max-width: none;
        height: auto;
        max-height: calc(100dvh - 20px);
        border-radius: 8px;
        margin: 10px auto;
        overflow: visible;
        transform: none !important;
    }

    .realistec-stereo-crop-modal-body {
        display: flex;
        flex: 1;
        min-height: 0;
        flex-direction: column;
        overflow-y: auto;
        overflow-x: hidden;
        -webkit-overflow-scrolling: touch;
    }

    /* Hide the desktop sidebar Reset section on mobile — strip handles it */
    .realistec-stereo-crop-reset-desktop {
        display: none !important;
    }

    .realistec-stereo-crop-editor-sidebar {
        display: flex;
        width: 100%;
        border-left: none;
        border-top: 1px solid var(--realistec-border, #1f1b3a);
        flex-direction: row;
        flex-wrap: wrap;
        flex-shrink: 0;
        overflow: visible;
    }

    /* Each sidebar section: label left, control right on one row */
    .realistec-stereo-crop-sidebar-section {
        display: flex;
        flex-direction: row;
        align-items: center;
        gap: 10px;
        padding: 10px 16px;
        flex: 1;
        min-width: 160px;
        border-bottom: none;
        border-right: 1px solid var(--realistec-border, #1f1b3a);
    }

    .realistec-stereo-crop-sidebar-section:last-child {
        border-right: none;
    }

    /* Section title sits left, no bottom margin */
    .realistec-stereo-crop-sidebar-section > .realistec-stereo-crop-sidebar-section-title {
        margin: 0;
        white-space: nowrap;
        flex-shrink: 0;
    }

    /* Hide the "Frame" title — Left/Right Frame labels already describe the scrubber */
    #crop-crop-panel > .realistec-stereo-crop-sidebar-section-title:first-child {
        display: none;
    }

    /* Aspect Ratio title sits inline — hide the one inside crop-crop-panel
       and rely on the section-level title treatment above */
    #crop-crop-panel .realistec-stereo-crop-sidebar-section-title[style*="margin-top"] {
        margin: 0;
        white-space: nowrap;
        flex-shrink: 0;
    }

    /* Control groups fill the remaining row width */
    .realistec-stereo-crop-sidebar-section .realistec-stereo-crop-control-group {
        flex: 1;
        min-width: 0;
        margin-bottom: 0;
    }

    /* Opacity row already flex-row — ensure it fills its space */
    .realistec-stereo-crop-opacity-row {
        width: 100%;
    }

    /* Select fills its control group */
    .realistec-stereo-crop-sidebar-section .realistec-stereo-crop-control-group select {
        width: 100%;
    }

    /* crop-crop-panel: grid pairs siblings into two inline rows —
       row 1: Frame title (hidden) + scrubber spanning full width
       row 2: Aspect Ratio title (left) + select (right)
       10px row-gap adds breathing room between the two rows */
    #crop-crop-panel {
        display: grid;
        grid-template-columns: auto 1fr;
        align-items: center;
        column-gap: 10px;
        row-gap: 10px;
    }

    /* Frame title hidden — scrubber spans full width */
    #crop-crop-panel > .realistec-stereo-crop-sidebar-section-title:first-child {
        display: none;
    }

    #crop-crop-panel > .realistec-stereo-frame-scrubber-group {
        grid-column: 1 / -1;
        display: flex;
        flex-direction: row;
        align-items: center;
        gap: 6px;
        margin-bottom: 0;
        border-bottom: none;
        padding-bottom: 0;
    }

    /* Aspect Ratio title: left cell */
    #crop-crop-panel > .realistec-stereo-crop-sidebar-section-title[style*="margin-top"] {
        grid-column: 1;
        margin: 0;
        white-space: nowrap;
        flex-shrink: 0;
    }

    /* Aspect Ratio select: right cell */
    #crop-crop-panel > .realistec-stereo-crop-control-group:last-child {
        grid-column: 2;
        display: flex;
        align-items: center;
        margin-bottom: 0;
        min-width: 0;
    }

    #crop-crop-panel > .realistec-stereo-crop-control-group:last-child select {
        width: 100%;
    }

    .realistec-stereo-crop-editor-viewport {
        flex: none;
        height: auto;
        overflow: visible;
        padding: 16px;
    }

    .realistec-stereo-crop-canvas-container {
        overflow: hidden;
        justify-content: center;
    }

    /* On mobile the v-column overlaps inside the canvas right edge (positioned by JS)
       rather than sitting outside it, so it stays within the viewport. */
    
    .realistec-stereo-crop-info {
        flex-direction: column;
        gap: 10px;
        align-items: center;
    }
    
    .realistec-stereo-crop-modal-footer {
        flex-wrap: wrap;
        flex-shrink: 0;
    }

    .realistec-stereo-crop-info-footer {
        width: 100%;
        padding-bottom: 10px;
    }

    .realistec-stereo-crop-modal-footer-actions {
        width: 100%;
        justify-content: flex-end;
    }
    
    .realistec-stereo-crop-btn-primary,
    .realistec-stereo-crop-btn-secondary {
        flex: 1;
        min-width: 100px;
    }
    
    .realistec-stereo-custom-crop-option {
        padding: 12px;
    }
    
    .realistec-stereo-crop-description {
        margin-left: 0;
        margin-top: 10px;
    }
    
    /* Match Color responsive */
    .realistec-stereo-match-color-option {
        padding: 12px;
    }
    
    .realistec-stereo-match-color-selector {
        flex-direction: column;
        gap: 10px;
    }
    
    .realistec-stereo-match-color-radio {
        width: 100%;
        justify-content: flex-start;
    }

    /* Compare & Select button responsive */
    .realistec-stereo-match-color-compare-btn {
        margin-left: 0;
    }
    
    /* Fix 1: Align match-color elements under description on mobile,
       matching the realistec-stereo-crop-indicator/realistec-stereo-edit-crop-btn pattern.
       Description stays at margin-left:28px (PHP base wins on load order),
       so indicator and label must also use 28px. */
    .realistec-stereo-match-color-selector-wrap {
        margin: 10px 0 0 28px;
    }
    
    .realistec-stereo-match-color-selection-label {
        margin-left: 0;
        margin-top: 0;
    }
    
    .realistec-stereo-match-color-compare-btn {
        margin-left: 8px;
        margin-top: 0;
    }

    /* Histogram modal responsive */
    .realistec-stereo-hist-modal {
        padding: 10px;
    }

    .realistec-stereo-hist-modal-content {
        margin: 10px auto;
        height: auto;
        max-height: calc(100vh - 20px);
        overflow: visible;
    }

    .realistec-stereo-hist-modal-header,
    .realistec-stereo-hist-modal-footer {
        padding: 12px 16px;
    }

    /* Stack sidebar above main content on narrow screens */
    .realistec-stereo-hist-modal-body {
        flex-direction: column;
        overflow-y: auto;
        overflow-x: hidden;
        -webkit-overflow-scrolling: touch;
    }

    .realistec-stereo-hist-sidebar {
        width: 100%;
        flex-shrink: 0;
        border-left: none;
        border-bottom: 1px solid var(--modal-border, #1f1b3a);
        flex-direction: column;
        overflow-y: visible;
        order: 0;
    }

    .realistec-stereo-hist-sidebar-section {
        width: 100%;
        border-bottom: 1px solid var(--modal-border, #1f1b3a);
        border-right: none;
        /* Inline layout: label left, control right */
        display: flex;
        flex-direction: row;
        align-items: center;
        gap: 10px;
        padding: 10px 16px;
    }

    .realistec-stereo-hist-sidebar-section:last-child {
        border-bottom: none;
    }

    /* Label sits on the left, no bottom margin */
    .realistec-stereo-hist-sidebar-section-title,
    .realistec-stereo-hist-sidebar-control-label {
        margin: 0;
        white-space: nowrap;
        flex-shrink: 0;
    }

    /* Control group takes remaining space on the right */
    .realistec-stereo-hist-sidebar-section .realistec-stereo-hist-sidebar-control-group {
        flex: 1;
        min-width: 0;
        margin: 0;
    }

    /* Dropdowns fill the control group width */
    .realistec-stereo-hist-sidebar-section .realistec-stereo-hist-sidebar-control-group select {
        width: 100%;
    }

    /* Strength group: label + [slider + value] all on one row */
    .realistec-stereo-hist-filter-strength-group {
        flex: 1;
        min-width: 0;
        margin: 0;
        display: flex;
        flex-direction: row;
        align-items: center;
        gap: 10px;
    }

    .realistec-stereo-hist-filter-strength-group .realistec-stereo-hist-sidebar-control-label {
        margin: 0;
        flex-shrink: 0;
    }

    .realistec-stereo-hist-filter-strength-row {
        flex: 1;
        min-width: 0;
    }

    .realistec-stereo-hist-compare-container {
        flex: none;
        height: 160px;
    }

    .realistec-stereo-hist-main {
        padding: 16px;
        overflow-y: visible;
    }

    .realistec-stereo-hist-image-previews {
        gap: 8px;
        flex: 0 0 auto;
    }

    .realistec-stereo-hist-image-panels-row {
        flex: 0 0 auto;
    }

    .realistec-stereo-hist-image-panel img {
        max-height: 120px;
        flex: none;
    }

    .realistec-stereo-hist-modal-footer {
        flex-wrap: wrap;
    }

    .realistec-stereo-hist-modal-footer-actions {
        width: 100%;
        justify-content: flex-end;
    }

    .realistec-stereo-hist-btn-primary,
    .realistec-stereo-hist-btn-secondary {
        flex: 1;
        min-width: 100px;
        text-align: center;
    }
}

@media (max-width: 600px) {
    .realistec-stereo-crop-modal-header {
        flex-wrap: wrap;
        gap: 8px;
        padding: 12px 16px;
        position: relative;
    }

    .realistec-stereo-crop-modal-header-left {
        width: 100%;
        flex-direction: column;
        align-items: flex-start;
        gap: 8px;
        padding-right: 40px;
    }

    .realistec-stereo-crop-mode-tabs {
        width: 100%;
        justify-content: flex-start;
    }

    .realistec-stereo-crop-mode-tab {
        flex: 1;
        text-align: center;
    }

    .realistec-stereo-crop-close-btn-abs {
        position: absolute;
        top: 12px;
        right: 16px;
    }

    .realistec-stereo-crop-modal-footer {
        flex-wrap: wrap;
        padding: 12px 16px;
    }

    .realistec-stereo-crop-modal-footer-actions {
        width: 100%;
        justify-content: flex-end;
    }

    .realistec-stereo-crop-btn-primary,
    .realistec-stereo-crop-btn-secondary {
        flex: 1;
        min-width: 100px;
        text-align: center;
    }
}

@media (max-width: 480px) {
    .realistec-stereo-crop-modal-header h3 {
        font-size: 18px;
    }
    
    .realistec-stereo-crop-handle {
        width: 16px;
        height: 16px;
    }
    
    .realistec-stereo-crop-handle-nw { top: -8px; left: -8px; }
    .realistec-stereo-crop-handle-n { top: -8px; }
    .realistec-stereo-crop-handle-ne { top: -8px; right: -8px; }
    .realistec-stereo-crop-handle-e { right: -8px; }
    .realistec-stereo-crop-handle-se { bottom: -8px; right: -8px; }
    .realistec-stereo-crop-handle-s { bottom: -8px; }
    .realistec-stereo-crop-handle-sw { bottom: -8px; left: -8px; }
    .realistec-stereo-crop-handle-w { left: -8px; }
}

/* NOTE — A `@media (prefers-color-scheme: dark)` block was previously
   here. It was a holdover from when the plugin shipped a light theme as
   default and inverted to dark on user OS preference. The plugin now
   ships dark-by-default to match the brand, so a prefers-color-scheme
   override would either be a no-op (if it inverted to dark) or actively
   harmful (if it inverted to light). The block has been removed; do
   not reintroduce one without rethinking the theming model. */

/* realistec-stereo-crop-modal animation — handled in main definition above */

/* Match Color animation */
.realistec-stereo-match-color-option {
    transition: all 0.3s ease;
}

.realistec-stereo-match-color-radio {
    transition: all 0.2s ease;
}

/* =============================================================
   SECTION 2: BASE STYLES
   (Migrated from upload-shortcode.php inline <style> block)
   (Comes second to preserve original load order: <head> then <body>)
   ============================================================= */

/* =============================================
   BASE STYLES
   ============================================= */
.realistec-stereo-upload-interface {
    /* Brand palette — coupled to the site theme's design tokens (see
       style.css :root) so a palette change in the theme propagates here
       automatically. Fallback values after the comma keep the plugin
       functional if loaded on a site that doesn't define --rt-* tokens
       (e.g. during development or if the theme is swapped). Variables
       that have no theme equivalent — or where the plugin needs a
       different value than the theme provides — stay hardcoded and are
       called out with a comment. */
    --realistec-primary: var(--rt-violet, #8b5cf6);              /* gradient start, also used solid */
    --realistec-primary-hover: var(--rt-indigo, #6366f1);        /* gradient end, also used solid */
    --realistec-gradient: var(--rt-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    --realistec-gradient-hover: var(--rt-gradient-hover, linear-gradient(135deg, #a78bfa 0%, #818cf8 100%));
    --realistec-link: var(--rt-violet-bright, #a78bfa);          /* lighter accent for icons/links */
    --realistec-success: var(--rt-success, #10b981);
    --realistec-error: var(--rt-error, #ef4444);
    --realistec-bg: var(--rt-bg, #07060f);                       /* page background */
    --realistec-surface: var(--rt-bg-2, #0d0b1f);                /* elevated panel surface */
    --realistec-surface-2: var(--rt-bg-3, #14112e);              /* nested surface */
    /* Border stays hardcoded — theme's --rt-border is an rgba value
       designed for thin overlay borders; plugin needs a solid violet-
       tinted color for its 2px panel borders. */
    --realistec-border: #1f1b3a;
    --realistec-text: var(--rt-text, #f5f3ff);
    --realistec-text-secondary: var(--rt-text-muted, #a8a3c9);
    --realistec-text-dim: var(--rt-text-dim, #6b6794);

    background: var(--realistec-bg);
    border: 2px solid var(--realistec-border);
    border-radius: 12px;
    padding: 25px;
    margin: 20px 0;
    color: var(--realistec-text);
    font-family: var(--rt-font-body, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
}

/* Display font on plugin headings and card titles — references the
   theme's --rt-font-display token so a site-wide font change propagates
   automatically. Body copy stays on the body font set above. */
.realistec-stereo-upload-interface h3,
.realistec-stereo-upload-interface h4,
.realistec-stereo-upload-interface .realistec-stereo-type-label {
    font-family: var(--rt-font-display, 'Space Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
    letter-spacing: -0.01em;
}

/* =============================================
   MATERIAL SYMBOLS — inline icon spans
   =============================================
   Mirrors Immersity's .realistec-mono-msi pattern. Use as:
     <span class="realistec-stereo-msi material-symbols-outlined">aspect_ratio</span>
   The Material Symbols font is loaded site-wide by functions.php (see
   the wp_enqueue_style for 'material-symbols-outlined'). The font is
   only loaded on product/cart pages where the plugin lives, so adding
   icons to other plugin views requires extending that enqueue
   condition.

   .realistec-stereo-msi is plugin-scoped so we can target our icons without
   affecting other Material Symbols spans elsewhere on the page. */
.realistec-stereo-msi {
    font-size: 18px;
    line-height: 1;
    color: inherit;
    vertical-align: middle;
    /* Center the glyph in icon-button slots — Material Symbols glyphs
       vary in optical size, so vertical-align: middle alone can leave a
       baseline offset relative to adjacent text labels. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Material Symbols ligatures are CASE-SENSITIVE: the font maps the
       lowercase string "opacity" to the opacity glyph, but "OPACITY"
       doesn't match any substitution rule and renders as plain text.
       The .realistec-stereo-crop-sidebar-section-title and .realistec-stereo-hist-sidebar-section-title
       both apply text-transform: uppercase to their labels, which would
       otherwise reach the ligature span and break icon rendering.
       Reset both transform and letter-spacing here, and force the
       'liga' OpenType feature on for older browsers. */
    text-transform: none;
    letter-spacing: normal;
    font-feature-settings: 'liga';
    -webkit-font-feature-settings: 'liga';
    font-variant-ligatures: common-ligatures;
    /* If the font fails to load, the ligature names ('opacity',
       'aspect_ratio') would otherwise show as fallback text. The
       `display=block` query parameter on the font URL (set in
       functions.php) blanks the text until the font arrives. */
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
}

/* Inline icons paired with a label/text in the sidebar (Opacity,
   Aspect Ratio, Channel, Color Filter, Filter Strength). The default
   18px MSI is too dominant next to 11–13px text; match the icon to
   the surrounding font size and add a small right-gap so the glyph
   doesn't collide with the label text. */
.realistec-stereo-crop-sidebar-section-title .realistec-stereo-msi,
.realistec-stereo-crop-editor-sidebar .realistec-stereo-crop-control-group label .realistec-stereo-msi,
.realistec-stereo-hist-sidebar-section-title .realistec-stereo-msi,
.realistec-stereo-hist-sidebar-control-label .realistec-stereo-msi {
    font-size: 14px;
    margin-right: 4px;
    /* Nudge down a hair so the optical center matches the text's
       x-height — Material Symbols' default baseline tends to sit
       slightly above where the eye expects it next to short caps. */
    vertical-align: -2px;
}

.realistec-stereo-upload-header h3 {
    margin-top: 0;
    color: var(--realistec-text, #f5f3ff);
    font-size: 20px;
    display: flex;
    align-items: center;
    gap: 10px;
}

.realistec-stereo-upload-header h3::before {
    /* Replaces the previous 🖼️ frame emoji with the Material Symbols
       'upload' ligature for visual consistency with the icon-paired
       labels elsewhere in the plugin. The font-family declaration
       activates the Material Symbols font on this pseudo-element only —
       the rest of the H3 keeps the display font set on its parent.
       Includes the same ligature-feature settings used by .realistec-stereo-msi
       so the substitution fires reliably across browsers.

       Sizing: 24px so the icon reads as comparable visual weight to the
       20px display-font heading (Material Symbols glyphs visually weigh
       ~85% of an equivalent uppercase letterform, so a small scale-up
       balances them). Color inherits from the H3 — currently
       --realistec-text. */
    content: 'upload';
    font-family: 'Material Symbols Outlined';
    font-weight: normal;
    font-style: normal;
    font-size: 24px;
    line-height: 1;
    color: var(--realistec-primary, #8b5cf6);
    text-transform: none;
    letter-spacing: normal;
    font-feature-settings: 'liga';
    -webkit-font-feature-settings: 'liga';
    font-variant-ligatures: common-ligatures;
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
}

.realistec-stereo-description {
    color: var(--realistec-text-secondary, #a8a3c9);
    font-size: 14px;
    line-height: 1.6;
    margin-bottom: 20px;
}

/* =============================================
   UPLOAD TYPE SELECTOR (with proper label/input)
   ============================================= */
.realistec-stereo-upload-type-selector {
    margin-bottom: 24px;
}

.realistec-stereo-upload-type-selector h4 {
    margin: 0 0 12px 0;
    font-size: 14px;
    color: var(--realistec-text, #f5f3ff);
}

.realistec-stereo-type-options {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
}

.realistec-stereo-type-option {
    flex: 1;
    min-width: 200px;
    position: relative;
}

.realistec-stereo-type-option input[type="radio"] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.realistec-stereo-type-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 20px;
    background: var(--realistec-surface, #0d0b1f);
    border: 2px solid var(--realistec-border, #1f1b3a);
    border-radius: 12px;
    transition: all 0.2s ease;
    text-align: center;
    cursor: pointer;
}

.realistec-stereo-type-option input[type="radio"]:checked + .realistec-stereo-type-card {
    border-color: var(--realistec-primary, #8b5cf6);
    background: rgba(139, 92, 246, 0.05);
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.1);
}

/* Suppress the browser-default focus outline on click. The outline was
   producing a brief white flash because outline doesn't participate in
   the card's transition — same bug class fixed in the Immersity plugin's
   type-options cards. The mobile blue tap-highlight is handled by the
   global -webkit-tap-highlight-color reset elsewhere. */
.realistec-stereo-type-option input[type="radio"]:focus + .realistec-stereo-type-card {
    outline: none;
}

/* Keyboard-only focus indicator — implemented as box-shadow rather than
   outline so it animates with the card's existing `transition: all 0.2s
   ease` and matches the :checked state's visual language (also a violet
   ring). :focus-visible only triggers on keyboard navigation, not mouse
   clicks, so this is the correct accessibility behavior — mouse users
   don't see a focus ring on click. */
.realistec-stereo-type-option input[type="radio"]:focus-visible + .realistec-stereo-type-card {
    outline: none;
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.25);
}

/* When a card is both focused AND checked, layer a slightly stronger
   focus ring on top of the checked state so the focus indicator stays
   distinguishable from the selected state for keyboard users. */
.realistec-stereo-type-option input[type="radio"]:focus-visible:checked + .realistec-stereo-type-card {
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.35);
}

.realistec-stereo-type-card:hover {
    border-color: var(--realistec-primary, #8b5cf6);
}

.realistec-stereo-type-icon {
    color: var(--realistec-primary, #8b5cf6);
    margin-bottom: 12px;
    /* Center the icon in case the card's flex layout doesn't already
       — defensive against future layout changes. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Material Symbols glyph inside the type-card icon wrapper. Sized to
   match the original SVG dimensions (32×32). The variable font's `opsz`
   (optical size) axis covers 20..48 per the wp_enqueue_style URL in
   functions.php, so the browser auto-tunes the glyph for this size.
   The wrapper's color (var(--realistec-primary)) cascades down — no
   need to set color here. The .realistec-stereo-msi base class also applies
   margin-right: 4px and vertical-align: -2px in some contexts (those
   are scoped to label-paired icons via the .realistec-stereo-crop-sidebar-section-title
   selector); reset both here so the card icon sits cleanly centered. */
.realistec-stereo-type-icon .realistec-stereo-msi {
    font-size: 32px;
    margin-right: 0;
    vertical-align: baseline;
}

.realistec-stereo-type-label {
    font-weight: 600;
    color: var(--realistec-text, #f5f3ff);
    font-size: 15px;
    margin-bottom: 4px;
}

.realistec-stereo-type-desc {
    font-size: 12px;
    color: var(--realistec-text-secondary, #a8a3c9);
}

/* =============================================
   UPLOAD AREA (clickable dropzone)
   ============================================= */
.realistec-stereo-upload-section {
    margin: 20px 0;
}

.realistec-stereo-upload-area {
    border: 2px dashed var(--realistec-border, #1f1b3a);
    border-radius: 12px;
    padding: 48px 24px;
    text-align: center;
    background: var(--realistec-surface, #0d0b1f);
    cursor: pointer;
    transition: all 0.3s ease;
    position: relative;
}

.realistec-stereo-upload-area:hover,
.realistec-stereo-upload-area.realistec-stereo-drag-over {
    border-color: var(--realistec-primary, #8b5cf6);
    background: rgba(139, 92, 246, 0.05);
}

.realistec-stereo-upload-area.realistec-stereo-drag-over {
    transform: scale(1.01);
}

.realistec-stereo-upload-area.uploading {
    opacity: 0.7;
    pointer-events: none;
}

.realistec-stereo-upload-icon {
    color: var(--realistec-primary, #8b5cf6);
    margin-bottom: 16px;
    /* Center the icon — defensive against future layout changes. */
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Material Symbols glyph inside the upload-area icon wrapper. Sized
   to match the original SVG dimensions (48×48). Same `opsz`-aware
   sizing approach as the type-card icon above; see that rule for the
   full rationale and the reset of base-class margins/vertical-align. */
.realistec-stereo-upload-icon .realistec-stereo-msi {
    font-size: 48px;
    margin-right: 0;
    vertical-align: baseline;
}

.realistec-stereo-upload-text {
    font-size: 16px;
    font-weight: 500;
    color: var(--realistec-text, #f5f3ff);
    margin: 0 0 8px 0;
}

.realistec-stereo-upload-hint {
    font-size: 13px;
    color: var(--realistec-text-secondary, #a8a3c9);
    margin: 0;
}

/* =============================================
   FORMAT BADGES (upload areas)
   =============================================
   Mirrors Immersity's .realistec-mono-format-badges / -badge pattern.
   Sits on its own row between the drag prompt and the size hint, so the
   list of supported file formats reads as a quick visual scan rather
   than a wall of comma-separated text. The flex container handles
   layout (centered, wrapping, 6px gap); each .realistec-stereo-format-badge
   is a small uppercase pill in the brand violet at low alpha — matches
   the "subtle but on-brand affordance" treatment used elsewhere for
   secondary affordances. */
.realistec-stereo-format-badges {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0 0 10px 0;
}

.realistec-stereo-format-badge {
    display: inline-block;
    padding: 3px 10px;
    /* Translucent violet wash on the panel surface — keeps the badges
       readable on the upload area's dark cosmic background while
       picking up the brand color language. The hardcoded rgba uses the
       same #8b5cf6 base as --realistec-primary; we keep it as a literal
       rgba (rather than rgb-from-token) because CSS variables can't
       be used inside rgba() syntax across all browsers. */
    background: rgba(139, 92, 246, 0.1);
    color: var(--realistec-primary, #8b5cf6);
    border: 1px solid rgba(139, 92, 246, 0.25);
    border-radius: 999px; /* fully rounded — pill shape regardless of text length */
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    line-height: 1.4;
    /* tabular-nums keeps mixed-case format names like "WebP" or "HEIC"
       sitting visually consistent with the all-uppercase ones if they
       get added later. */
    font-feature-settings: "tnum";
}

/* Hidden file input - positioned off-screen */
.realistec-stereo-file-input-hidden {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    opacity: 0;
}

/* =============================================
   FRAME PREVIEWS - ORIGINAL CARD STYLE
   ============================================= */
.realistec-stereo-frame-previews-container {
    background: var(--realistec-surface, #0d0b1f);
    border: 2px solid var(--realistec-primary, #8b5cf6);
    border-radius: 12px;
    padding: 20px;
    margin-top: 20px;
}

.realistec-stereo-frame-previews-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--realistec-border, #1f1b3a);
    flex-wrap: wrap;
    gap: 12px;
}

.realistec-stereo-frame-previews-info {
    display: flex;
    align-items: center;
    gap: 12px;
}

.realistec-stereo-previews-title {
    font-weight: 600;
    font-size: 15px;
    color: var(--realistec-text, #f5f3ff);
}

.realistec-stereo-previews-hint {
    font-size: 12px;
    color: var(--realistec-text-secondary, #a8a3c9);
    display: flex;
    align-items: center;
    gap: 5px;
}

.realistec-stereo-previews-hint::before {
    /* Replaces the previous Unicode arrow (↔) with the Material Symbols
       'swap_horiz' ligature for visual consistency with the other
       icon-paired labels in the plugin. The font-family declaration
       activates the Material Symbols font on this pseudo-element only
       — the rest of the .realistec-stereo-previews-hint span keeps the body font. The
       ligature feature is enabled explicitly so 'swap_horiz' is
       substituted for the icon glyph rather than rendered as text on
       browsers that don't honor 'liga' by default.

       Sizing: 14px to match the surrounding 12px label text without
       overpowering it; vertical-align: -2px nudges the glyph's optical
       center to the label's x-height (same offset used by .realistec-stereo-msi
       inline icons elsewhere). */
    content: 'swap_horiz';
    font-family: 'Material Symbols Outlined';
    font-weight: normal;
    font-style: normal;
    font-size: 14px;
    line-height: 1;
    text-transform: none;
    letter-spacing: normal;
    font-feature-settings: 'liga';
    -webkit-font-feature-settings: 'liga';
    font-variant-ligatures: common-ligatures;
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
    vertical-align: -2px;
}

.realistec-stereo-frame-previews-actions {
    display: flex;
    gap: 8px;
}

.realistec-stereo-frame-previews-list {
    display: flex;
    gap: 15px;
    flex-wrap: wrap;
    justify-content: center;
    min-height: 120px;
}

/* Individual Frame Preview - Original Style */
.realistec-stereo-frame-preview-item {
    position: relative;
    flex: 1 1 0;
    min-width: 150px;
    max-width: 300px;
    background: var(--realistec-surface, #0d0b1f);
    border: 2px solid var(--realistec-surface-2, #14112e);
    border-radius: 10px;
    padding: 10px;
    cursor: grab;
    transition: all 0.2s ease;
    user-select: none;
}

.realistec-stereo-frame-preview-item:hover {
    border-color: var(--realistec-primary, #8b5cf6);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.realistec-stereo-frame-preview-item.dragging {
    opacity: 0.5;
    border-style: dashed;
    cursor: grabbing;
}

.realistec-stereo-frame-preview-item.drag-over {
    border-color: var(--realistec-primary, #8b5cf6);
    background: var(--realistec-surface-2, #14112e);
}

.realistec-stereo-frame-preview-item .realistec-stereo-frame-number {
    position: absolute;
    top: -8px;
    left: -8px;
    width: 24px;
    height: 24px;
    background: linear-gradient(135deg, var(--realistec-primary, #8b5cf6) 0%, var(--realistec-primary-hover, #6366f1) 100%);
    color: white;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: 600;
    box-shadow: 0 2px 6px rgba(79, 94, 200, 0.4);
}

.realistec-stereo-frame-preview-item .realistec-stereo-frame-image {
    width: 100%;
    height: 180px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--realistec-surface, #0d0b1f);
    border-radius: 6px;
    overflow: hidden;
    margin-bottom: 8px;
}

.realistec-stereo-frame-preview-item .realistec-stereo-frame-image img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}

.realistec-stereo-frame-preview-item .realistec-stereo-frame-filename {
    display: block;
    font-size: 11px;
    color: var(--realistec-text-secondary, #a8a3c9);
    text-align: center;
    width: 100%;
    word-break: break-all;
    overflow-wrap: break-word;
    margin-bottom: 8px;
}

.realistec-stereo-frame-preview-item .realistec-stereo-frame-remove {
    /* Visual language matches .realistec-mono-btn-secondary — solid
       surface-2 background, 1px brand-tinted border, light text/icon,
       violet on hover — adapted to a 24×24 circular corner-X. The full
       btn-secondary's padding/font-size/border-radius don't apply here
       because the button is icon-only at fixed pixel dimensions, but
       the color tokens and hover behavior are identical to the
       full-size .realistec-stereo-btn-secondary used by #realistec-remove-stereo
       further down this file. Was previously a red circle (--realistec-error
       background, white ×) which read as a destructive-action affordance;
       the new treatment matches the rest of the plugin's secondary-action
       buttons and lets the × glyph carry the destructive intent on its own.

       The hover ring uses the same violet treatment as the full-size
       button (border-color shifts to --realistec-primary). The shadow
       previously tinted red — now tinted violet at low alpha to keep
       the lift effect without re-introducing red. */
    position: absolute;
    top: -8px;
    right: -8px;
    width: 24px;
    height: 24px;
    background: var(--realistec-surface-2, #14112e);
    color: var(--realistec-text, #f5f3ff);
    border: 1px solid var(--realistec-border, #1f1b3a);
    border-radius: 50%;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    line-height: 1;
    transition: background 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
    box-shadow: 0 2px 6px rgba(139, 92, 246, 0.25);
}

.realistec-stereo-frame-preview-item .realistec-stereo-frame-remove:hover {
    background: #1f1b3a;
    border-color: var(--realistec-primary, #8b5cf6);
    transform: scale(1.1);
}

.realistec-stereo-frame-preview-item .realistec-stereo-drag-handle {
    display: none;
}

.realistec-stereo-frame-preview-item .realistec-stereo-drag-handle span {
    display: block;
    width: 4px;
    height: 4px;
    background: var(--realistec-border, #1f1b3a);
    border-radius: 50%;
}

/* =============================================
   STEREO PREVIEW
   ============================================= */
.realistec-stereo-stereo-preview {
    background: var(--realistec-surface, #0d0b1f);
    border-radius: 12px;
    padding: 16px;
    border: 2px solid var(--realistec-primary, #8b5cf6);
    margin-top: 20px;
}

.realistec-stereo-preview-container {
    margin-bottom: 12px;
    text-align: center;
}

.realistec-stereo-preview-container img {
    /* v3.7.16: max-height changed from 300px to 100% so wide JPS
       files (and any other wide stereo formats) can render at the
       full container width without the height cap forcing a uniform
       downscale that leaves empty space on the sides.

       Note: `max-height: 100%` resolves against the parent's height.
       Since no ancestor of this img has an explicit height set,
       100% effectively means "no height cap" — the practical result
       is equivalent to omitting the property. The browser will size
       the image to fit max-width: 100% and compute the height from
       the natural aspect ratio. For very tall stereo formats this
       could produce a tall preview, but typical stereo aspects
       (JPS, MPO) are wide (2:1 or wider), so this is rarely an
       issue. */
    max-width: 100%;
    max-height: 100%;
    border-radius: 8px;
    background: var(--realistec-surface-2, #14112e);
}

.realistec-stereo-file-info {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-top: 12px;
    border-top: 1px solid var(--realistec-border, #1f1b3a);
    flex-wrap: wrap;
    gap: 10px;
}

.realistec-stereo-file-details {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.realistec-stereo-file-name {
    font-weight: 600;
    color: var(--realistec-text, #f5f3ff);
    font-size: 14px;
    word-break: break-all;
}

.realistec-stereo-file-size {
    font-size: 12px;
    color: var(--realistec-text-secondary, #a8a3c9);
}

/* =============================================
   CROP OPTIONS
   ============================================= */
.realistec-stereo-custom-crop-option,
.realistec-stereo-stereo-crop-option {
    margin: 20px 0;
    padding: 16px;
    background: var(--realistec-surface, #0d0b1f);
    border: 2px solid var(--realistec-border, #1f1b3a);
    border-radius: 12px;
    transition: all 0.2s ease;
}

.realistec-stereo-custom-crop-option:hover,
.realistec-stereo-stereo-crop-option:hover {
    border-color: var(--realistec-primary, #8b5cf6);
}

.realistec-stereo-custom-crop-option.enabled,
.realistec-stereo-stereo-crop-option.enabled {
    border-color: var(--realistec-primary, #8b5cf6);
    background: rgba(139, 92, 246, 0.05);
}

.realistec-stereo-crop-checkbox-label {
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    font-weight: 600;
    color: var(--realistec-text, #f5f3ff);
    margin: 0;
}

.realistec-stereo-crop-checkbox-label input[type="checkbox"] {
    width: 18px;
    height: 18px;
    cursor: pointer;
    accent-color: var(--realistec-primary, #8b5cf6);
}

.realistec-stereo-crop-description {
    margin: 10px 0 0 28px;
    font-size: 13px;
    color: var(--realistec-text-secondary, #a8a3c9);
    line-height: 1.5;
}

.realistec-stereo-crop-indicator {
    /* Visual styling matches .realistec-stereo-match-color-selection-label (line 115)
       so the two indicator pills read as a coordinated pair when both
       appear in the same upload area. Properties and order are kept
       parallel so a change to one is easy to mirror to the other.

       Differences from the previous rule:
         - padding: 4px 10px -> 4px 12px (matches .realistec-stereo-match-color-selection-label)
         - background: a custom 90deg gradient between primary stops
           is replaced with the brand --realistec-gradient token (135deg
           violet→indigo). The 90deg orientation only matters on tall/wide
           elements like .realistec-stereo-progress-fill; on a small text pill
           the diagonal direction is visually identical, and using the
           token means a theme palette change propagates automatically. */
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: 12px;
    padding: 4px 12px;
    background: var(--realistec-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    color: white;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 500;
}

/* Icon inside the crop indicator pill — sized and aligned the same way
   .realistec-stereo-match-color-selection-label .realistec-stereo-msi is. Both rules reset the
   default .realistec-stereo-msi margin-right and vertical-align nudge because
   the parent's flex `gap: 4px` and `align-items: center` handle spacing
   and centering, and the nudge (designed for label-paired contexts)
   would push the icon off the pill's baseline. */
.realistec-stereo-crop-indicator .realistec-stereo-msi {
    font-size: 14px;
    margin-right: 0;
    vertical-align: baseline;
}

.realistec-stereo-edit-crop-btn,
.realistec-stereo-edit-stereo-crop-btn {
    /* Mirrors the Immersity plugin's .realistec-mono-edit-crop-btn — same
       small outlined action button as .realistec-stereo-match-color-compare-btn (above,
       in section 1). Properties and order follow that reference verbatim
       so all three buttons stay visually identical. The previous version
       had `border: none` and `color: white` which read inconsistently
       next to the compare button on the same row. */
    margin-left: 8px;
    padding: 4px 12px;
    background: var(--realistec-surface-2, #14112e);
    color: var(--realistec-text, #f5f3ff);
    border: 1px solid var(--realistec-border, #1f1b3a);
    border-radius: 4px;
    font-size: 12px;
    cursor: pointer;
    transition: background 0.2s, border-color 0.2s;
}

.realistec-stereo-edit-crop-btn:hover,
.realistec-stereo-edit-stereo-crop-btn:hover {
    background: #1f1b3a;
    border-color: var(--realistec-primary, #8b5cf6);
}

/* Stereo Split Preview */
.realistec-stereo-stereo-split-preview,
.realistec-stereo-standard-image-frames {
    /* v3.7.19: Mirrors Immersity's .realistec-mono-edited-preview
       (see immersity-upload-interface.css line 3413). Immersity's
       design system distinguishes between TWO classes of display
       block:
         (a) Interactive option panels (.realistec-stereo-custom-crop-option,
             .realistec-stereo-stereo-crop-option, .realistec-stereo-match-color-option) — user takes
             action on these, so they default to a muted 1px border
             that escalates to brand-violet on hover.
         (b) Read-only output blocks like this one — "your content,
             processed" — which sit at the heavier 2px brand-violet
             border + 12px radius treatment.

       v3.7.23: Padding and margin updated to match
       .realistec-stereo-frame-previews-container (line 2719) so the file-management
       block above and the preview block below render with the same
       inset and vertical rhythm. padding 16px → 20px; margin
       20px 0 → margin-top 20px only (dropping the explicit bottom
       margin matches realistec-stereo-frame-previews-container's pattern).

       v3.7.10 history note: .realistec-stereo-standard-image-frames is the standard-
       mode parallel of .realistec-stereo-stereo-split-preview (added after refactoring
       how standard previews are shown). Both share this rule because
       they have identical container semantics. */
    margin-top: 20px;
    padding: 20px;
    background: var(--realistec-surface, #0d0b1f);
    border: 2px solid var(--realistec-primary, #8b5cf6);
    border-radius: 12px;
}

.realistec-stereo-stereo-split-preview .realistec-stereo-loading-text {
    text-align: center;
    color: var(--realistec-text-secondary, #a8a3c9);
    font-style: italic;
}

.realistec-stereo-stereo-split-frames {
    display: flex;
    gap: 20px;
    justify-content: center;
    flex-wrap: wrap;
}

.realistec-stereo-stereo-split-frames .realistec-stereo-split-frame {
    text-align: center;
    background: var(--realistec-surface, #0d0b1f);
    padding: 12px;
    border-radius: 10px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.realistec-stereo-stereo-split-frames .realistec-stereo-frame-label {
    display: block;
    font-weight: 600;
    color: var(--realistec-primary, #8b5cf6);
    margin-bottom: 8px;
    font-size: 13px;
}

.realistec-stereo-stereo-split-frames img {
    /* v3.7.15: Bumped max-width from 200px to 300px to match the
       .realistec-stereo-frame-preview-item cards' max-width, so the Separate L/R
       display thumbnails span the same horizontal footprint as the
       file-management thumbnails above them. max-height bumped
       proportionally to keep the aspect ratio sensible for ~4:3
       and ~3:2 sources (300 × 0.75 = 225, 300 × 0.667 = 200 — 225
       comfortably covers both). */
    max-width: 300px;
    max-height: 225px;
    border-radius: 6px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
}

.realistec-stereo-stereo-split-frames .realistec-stereo-frame-dimensions {
    display: block;
    margin-top: 8px;
    font-size: 11px;
    color: var(--realistec-text-secondary, #a8a3c9);
}

/* =============================================
   DISPLAY-TYPE SELECTOR (v3.7.11, restyled v3.7.16)
   =============================================
   Sits at the top of .realistec-stereo-stereo-split-preview and .realistec-stereo-standard-image-frames
   above the thumbnails. Lets the user switch between separate L/R,
   stitched side-by-side, and anaglyph viewing modes. Same row appears
   in both blocks; same CSS applies via the shared .stereo-display-
   type-row class.

   v3.7.16: Visual treatment now matches the .realistec-stereo-frame-previews-header
   pair (.realistec-stereo-previews-title + .realistec-stereo-previews-hint above the file-management
   cards) so the page reads as a coherent system:
     - The label "Display:" mirrors .realistec-stereo-previews-title (near-white,
       weight 600, 15px)
     - The dropdown's selected-value text and option-list items
       mirror .realistec-stereo-previews-hint (muted lavender, 12px) so the active
       choice reads as a secondary descriptor rather than a competing
       title
   Row is now left-justified (was right) to read as a label-then-
   value pair flowing from the start of the panel, again matching
   the .realistec-stereo-previews-title + hint pair above. */
.realistec-stereo-stereo-display-type-row {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 0 0 12px 0;
    /* v3.7.16: was justify-content: flex-end (right-aligned). Now
       left-justified to match the .realistec-stereo-frame-previews-info pair above. */
    justify-content: flex-start;
}

.realistec-stereo-stereo-display-type-label {
    /* v3.7.16: Mirrors .realistec-stereo-previews-title exactly — same color, weight,
       size. Previously this was an uppercase muted small-caps label
       (12px, --realistec-text-secondary, letter-spacing 0.4). The new
       treatment makes "Display:" read as a section title sibling to
       "Frame Order" rather than a tiny form-field caption. */
    font-weight: 600;
    font-size: 15px;
    color: var(--realistec-text, #f5f3ff);
    /* Explicit resets in case the previous uppercase/spacing styling
       ever leaks back via specificity from somewhere else. */
    text-transform: none;
    letter-spacing: normal;
    margin: 0;
}

.realistec-stereo-stereo-display-type-select {
    /* v3.7.16: Text now matches .realistec-stereo-previews-hint (muted lavender, 12px)
       so the selected option reads as the same kind of secondary
       descriptor "Drag to reorder" reads as next to "Frame Order".
       Box chrome (background, border, focus ring) is kept dark-theme-
       branded since the element still needs to look clickable.

       Same compact dark-theme select base as the modal sidebar
       dropdowns (.realistec-stereo-hist-sidebar-control-group select / .crop-control-
       group select). */
    appearance: auto;
    -webkit-appearance: auto;
    background: var(--realistec-surface-2, #14112e);
    color: var(--realistec-text-secondary, #a8a3c9);
    border: 1px solid var(--realistec-border, #1f1b3a);
    border-radius: 4px;
    padding: 4px 8px;
    font-size: 12px;
    font-family: inherit;
    cursor: pointer;
    accent-color: var(--realistec-primary, #8b5cf6);
    color-scheme: dark;
    /* Cap width so a long option label like "Anaglyph (Magenta-Green)"
       doesn't push the row to overflow on narrow viewports. */
    max-width: 220px;
    min-width: 0;
    text-overflow: ellipsis;
}

.realistec-stereo-stereo-display-type-select:focus {
    outline: none;
    border-color: var(--realistec-primary, #8b5cf6);
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.18);
}

.realistec-stereo-stereo-display-type-select option {
    /* Dropdown list items match the .realistec-stereo-previews-hint color too so the
       open-list state stays consistent with the selected-value
       appearance. Background follows the dark surface palette;
       cross-browser support for styling option elements is uneven,
       so this is a best-effort rather than guaranteed. */
    background: var(--realistec-surface-2, #14112e);
    color: var(--realistec-text-secondary, #a8a3c9);
}

/* =============================================
   COMPOSITE PREVIEW FRAME (v3.7.11, expanded v3.7.12)
   =============================================
   When the user switches the display-type dropdown to a composite
   mode (anaglyph R-C/M-G/Y-B, or stitched side-by-side), the two
   separate cards are replaced by a single .realistec-stereo-stereo-anaglyph-frame
   holding one composite image. The class name is "anaglyph" for
   historical reasons (added in v3.7.11 for anaglyph only); it's
   now reused by the stitched-SBS path because the container needs
   are identical (single image, full panel width, same chrome).
   Container styling matches .realistec-stereo-stereo-split-frames .realistec-stereo-split-frame so
   the visual weight stays consistent across modes. */
.realistec-stereo-stereo-anaglyph-frame {
    /* Wraps the composite preview image (anaglyph or stitched SBS).
       Provides the rounded-corner card look and the dark surface
       backdrop.

       v3.7.22: Frame is a SQUARE pillarbox container — fixed 1:1
       aspect-ratio. The image inside fills the box via max-width:
       100% + max-height: 100% + object-fit: contain. Portrait
       sources render pillarboxed (empty space on sides); landscape
       sources render letterboxed (empty space top & bottom). Both
       anaglyph and SBS-stitched modes use this same frame, so they
       share the same square-box treatment for visual consistency.

       Matches Immersity's .rmcf-image-preview-wrap pattern (flex +
       center + max-100% on the image with object-fit: contain).
       Immersity gets its "roughly square" shape from the surrounding
       modal layout context; we don't have that context here, so we
       use aspect-ratio: 1/1 to declare the shape directly.

       v3.7.23: Removed the `max-width: min(420px, 100%)` cap and the
       auto margins. The cap was inset the frame from the panel
       borders (~46px of empty space on each side observed at panel
       content width ~512px), making the preview unnecessarily
       smaller than the panel could support. Without the cap, the
       frame fills the panel content width — square at whatever
       width the panel provides. Since the frame is square, the
       rendered height equals the rendered width and is by
       definition ≤ panel width; for typical desktop product-page
       column widths (~500-700px panel content) the square fits
       comfortably within the viewport height with no risk of
       requiring scroll.

       Padding kept (10px vertical) for breathing room from the
       frame's rounded corners; no horizontal padding so the image
       can fill the box edge-to-edge when its aspect matches the
       frame.

       aspect-ratio support: Chrome 88+, Firefox 89+, Safari 15+
       (all 2021). */
    display: flex;
    justify-content: center;
    align-items: center;
    aspect-ratio: 1 / 1;
    width: 100%;
    background: var(--realistec-surface, #0d0b1f);
    padding: 10px 0;
    border-radius: 10px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    box-sizing: border-box;
}

/* =============================================
   SIDE-BY-SIDE FREE-VIEWING ALIGNMENT AID (v3.7.13)
   =============================================
   When the user selects "Side-by-Side (Crossview)" display, the
   stitched image renders with a thin horizontal bar below it
   containing two filled dots — one centered under each half of the
   image. The dots act as a fixation target for free-viewing: when
   the viewer crosses their eyes and the two dots fuse into one,
   they're at the correct convergence for the stereo pair to "lock
   in" stereoscopically.

   Layout: the stack wrapper uses display: inline-block so its width
   shrinks to the image's rendered width rather than spanning the
   full panel. This keeps the bar (which gets width: 100% of its
   inline-block parent) aligned to the image's edges regardless of
   how the image's max-width: min(420px, 100%) cap resolves on the
   current viewport. The dots use flex `justify-content: space-around`
   which distributes equal space around each item — naturally
   centering them in each half of the bar's width. */
.realistec-stereo-stereo-sbs-stack {
    /* Wraps the SBS image + alignment bar so they share one width
       track (the bar's width: 100% pins to the image's rendered
       width via this parent). Within the square pillarbox frame
       (v3.7.22), the stack fills the available width.

       v3.7.22: Removed the per-stack max-width cap (was
       min(420px, 100%) per v3.7.21). The frame is now the size
       gatekeeper via aspect-ratio: 1/1 + max-width: min(420px, 100%);
       the stack just fills it. Max-height: 100% so the stack
       respects the square frame's vertical bound — stitched SBS
       (typically wide aspect like 2:1) will render the image at
       full stack width with empty space below for centering. */
    display: block;
    width: 100%;
    max-width: 100%;
    max-height: 100%;
    margin-left: auto;
    margin-right: auto;
}

.realistec-stereo-stereo-anaglyph-img {
    /* v3.7.22: Fills the square pillarbox frame. max-width: 100% +
       max-height: 100% + object-fit: contain matches Immersity's
       .rmcf-image-preview-wrap img pattern exactly — the image
       scales to fit the box, preserving natural aspect ratio, with
       empty space on the sides (portrait sources) or top/bottom
       (landscape sources) as needed.

       Previously (v3.7.15) this was width: 100% + height: auto,
       which made the image dictate the frame's height. v3.7.22
       inverts that: the FRAME has explicit dimensions (square via
       aspect-ratio), and the image fits inside. width/height: auto
       lets the browser's intrinsic sizing pick whichever dimension
       hits the 100% cap first while object-fit handles the rest. */
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
    object-fit: contain;
    border-radius: 6px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
}

/* v3.7.22: The per-child max-width caps that used to live here
   (v3.7.20 anaglyph + v3.7.21 SBS stack) are removed because the
   frame is now the size gatekeeper via aspect-ratio: 1/1 +
   max-width: min(420px, 100%). Children fill the box via
   max-width: 100% / max-height: 100% + object-fit: contain. */

.realistec-stereo-stereo-sbs-align-bar {
    /* Dark brand-tinted bar. Uses --realistec-surface-2 (= --rt-bg-3,
       a violet-tinged dark) at full alpha so the lighter dots inside
       read as the focal element, with the bar acting as a subtle
       backdrop rather than competing visually. Width: 100% of the
       parent stack = the image's rendered width.

       box-sizing: border-box so the 1px border is INCLUDED in the
       100% width allocation rather than added on top. Without
       border-box the rendered bar would be 100% + 2px wide and
       overflow the stack by 2px. */
    box-sizing: border-box;
    width: 100%;
    margin-top: 8px;
    /* Bar height of 18px gives the dots breathing room without
       making the strip itself feel heavy. */
    height: 18px;
    background: var(--realistec-surface-2, #14112e);
    /* Subtle violet edge to tie it to the brand palette without
       overpowering the dots. */
    border: 1px solid var(--realistec-border, #1f1b3a);
    border-radius: 9px; /* full-pill on an 18px-tall bar */
    /* space-around distributes equal flex-space ON EACH SIDE of items,
       so two items end up centered at 25% and 75% of the bar width —
       exactly the centers of the two image halves. */
    display: flex;
    align-items: center;
    justify-content: space-around;
}

.realistec-stereo-stereo-sbs-align-dot {
    /* Light filled circle — high contrast against the dark bar so it
       reads as a clear focal target during free-viewing. Color is the
       text token (near-white --rt-text) rather than pure white so it
       harmonizes with the rest of the dark theme's light surfaces. */
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--realistec-text, #f5f3ff);
    /* Subtle glow so the dot reads as a softly-emitting point rather
       than a flat sticker — helps the eye lock onto it during
       free-viewing where the surrounding image content is in soft
       focus. */
    box-shadow: 0 0 4px rgba(245, 243, 255, 0.4);
}

/* =============================================
   BUTTONS (FILM-style)
   ============================================= */
.realistec-stereo-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 10px 20px;
    font-size: 14px;
    font-weight: 500;
    border-radius: 8px;
    border: none;
    cursor: pointer;
    transition: all 0.2s ease;
}

.realistec-stereo-btn-secondary {
    /* Mirrors the Immersity plugin's .realistec-mono-btn-secondary —
       solid dark surface, 1px brand-tinted border, light text. The
       border + violet-on-hover pattern is what makes the secondary
       button read as a button (rather than a flat panel) against the
       surrounding dark UI. Without the border, the previous version
       blended into adjacent .realistec-stereo-form-section surfaces. */
    background: var(--realistec-surface-2, #14112e);
    color: var(--realistec-text, #f5f3ff);
    border: 1px solid var(--realistec-border, #1f1b3a);
}

.realistec-stereo-btn-secondary:hover {
    background: #1f1b3a;
    border-color: var(--realistec-primary, #8b5cf6);
}

.realistec-stereo-btn-secondary:disabled,
.realistec-stereo-btn-secondary[disabled] {
    opacity: 0.7;
    cursor: not-allowed;
}

.realistec-stereo-btn-small {
    padding: 6px 14px;
    font-size: 13px;
}

/* =============================================
   ADD-TO-CART SAVING-PREVIEW STATE
   =============================================
   While refreshOuterPreviews() is rendering thumbnails after an Apply
   Changes click, the add-to-cart button shows a centered spinner and
   becomes non-interactive. Mirrors Immersity's .realistec-mono-saving-crop
   pattern verbatim — same architecture, same anti-theme defenses, just
   renamed for the Replicate plugin.

   THEME WE'RE FIGHTING — the Realistec theme's style.css applies these
   rules to every WC button at specificity (0, 2, 1):

       .woocommerce button.button {
           background: var(--rt-gradient) !important;
           color: var(--rt-text-on-grad) !important;   // = #ffffff
           ...
       }
       .woocommerce button.button.alt {
           background-image: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%) !important;
       }

   Both are !important. To override, our selector must beat (0, 2, 1).
   The primary selector below scores (0, 4, 1) — same tag count, two
   more classes, decisive win. Looser fallback selectors are added for
   custom add-to-cart implementations that don't apply .button.alt.

   TEXT HIDING — the button HTML during loading is:
     <button class="single_add_to_cart_button button alt realistec-stereo-saving-preview">Add to cart<span class="realistec-stereo-btn-spinner"></span></button>
   "Add to cart" is a direct text node, not wrapped in a child element.
   font-size: 0 nukes text via layout (zero glyph width) rather than
   via color, sidestepping the theme's white text that wins the color
   cascade. The spinner span gets its own font-size reset below to
   keep its layout intact.

   PIXEL DIMENSIONS — font-size: 0 makes em units resolve to 0 too, so
   the entire button would collapse to zero size. We override the
   theme's em-based padding with concrete pixel values, plus min-height
   and min-width, so the button retains its visual footprint while the
   text is gone. */

button.single_add_to_cart_button.button.alt.realistec-stereo-saving-preview,
button.single_add_to_cart_button.button.alt.realistec-stereo-saving-preview:hover,
button.single_add_to_cart_button.button.alt.realistec-stereo-saving-preview:focus,
button.single_add_to_cart_button.button.alt.realistec-stereo-saving-preview:active,
button.single_add_to_cart_button.button.alt.realistec-stereo-saving-preview[disabled],
button.single_add_to_cart_button.button.alt.realistec-stereo-saving-preview:disabled,
.single_add_to_cart_button.realistec-stereo-saving-preview,
.single_add_to_cart_button.realistec-stereo-saving-preview[disabled],
.single_add_to_cart_button.realistec-stereo-saving-preview:disabled {
    cursor: wait !important;
    pointer-events: none;
    position: relative;
    /* Brand violet→indigo gradient — same as the resting CTA, so the
       spinner appears on the button's normal background rather than a
       darkened disabled-color variant. background-image AND background-
       color both set with !important to defeat the theme's
       .button.alt rule (which sets background-image !important too). */
    background-color: #8b5cf6 !important;
    background-image: linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%) !important;
    border: 0 !important;
    border-color: #8b5cf6 !important;
    /* Two-pronged text hiding (see comment above). */
    color: transparent !important;
    font-size: 0 !important;
    /* Concrete pixel dimensions — see PIXEL DIMENSIONS comment above. */
    padding: 12px 28px !important;
    min-height: 44px !important;
    min-width: 140px !important;
    line-height: normal !important;
    /* Theme's hover sets a glow shadow + scale; null those out for
       loading state since hover is no-op while pointer-events: none. */
    filter: none !important;
    /* Defensive: themes commonly apply opacity: 0.5 to disabled buttons.
       The button IS functionally disabled here, but we want it to LOOK
       like the resting CTA so the spinner reads against the full-
       saturation gradient. */
    opacity: 1 !important;
}

/* Spinner span needs a non-zero font-size so its inline-block dimensions
   render correctly inside the font-size: 0 parent. The width/height on
   .realistec-stereo-btn-spinner are explicit pixels but resetting font-size is
   defensive against any inherited zero. */
button.single_add_to_cart_button.realistec-stereo-saving-preview .realistec-stereo-btn-spinner,
.single_add_to_cart_button.realistec-stereo-saving-preview .realistec-stereo-btn-spinner {
    font-size: 14px !important;
}

/* Hide text held in child elements (defensive — current HTML doesn't
   wrap "Add to cart" in a child, but other themes might). */
.single_add_to_cart_button.realistec-stereo-saving-preview > *:not(.realistec-stereo-btn-spinner) {
    color: transparent !important;
    font-size: 0 !important;
}

/* Cancel out injected pseudo-element content — some themes use
   button::before { content: "Add to cart"; } or similar tricks. */
.single_add_to_cart_button.realistec-stereo-saving-preview::before,
.single_add_to_cart_button.realistec-stereo-saving-preview::after {
    content: none !important;
}

.realistec-stereo-btn-spinner {
    /* White 3/4-circle ring on a transparent track — three sides white,
       top transparent, producing a visible gap as the element rotates.
       Matches the WooCommerce Cart Block "Proceed to Checkout" spinner
       so loading states across the storefront read as one consistent
       design.

       !important on border colors is defensive against theme rules
       targeting button descendants that can muddy white into gray.
       The transparent top border also gets !important so the gap
       doesn't get filled in. */
    display: inline-block;
    width: 16px !important;
    height: 16px !important;
    border: 2px solid transparent !important;
    border-top-color: transparent !important;
    border-right-color: #ffffff !important;
    border-bottom-color: #ffffff !important;
    border-left-color: #ffffff !important;
    border-radius: 50%;
    animation: realistec-spin 0.7s linear infinite;
    vertical-align: middle;
    /* Explicit opacity: 1 — some themes set descendant opacity during
       the disabled/loading state, which would dim our white spinner. */
    opacity: 1 !important;
}

/* When inside a saving button, center the spinner over the (now-invisible)
   text rather than displaying inline alongside it. */
.single_add_to_cart_button.realistec-stereo-saving-preview .realistec-stereo-btn-spinner {
    position: absolute;
    top: 50%;
    left: 50%;
    /* Half of 16px width/height to center on the anchor point. */
    margin: -8px 0 0 -8px;
}

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

@media (prefers-reduced-motion: reduce) {
    .realistec-stereo-btn-spinner {
        animation: none;
    }
}

/* =============================================
   PROGRESS BAR (FILM-style)
   ============================================= */
.realistec-stereo-upload-progress {
    margin-top: 16px;
    padding: 16px;
    background: var(--realistec-surface, #0d0b1f);
    border-radius: 8px;
    border: 1px solid var(--realistec-border, #1f1b3a);
}

.realistec-stereo-progress-bar {
    height: 8px;
    background: var(--realistec-surface-2, #14112e);
    border-radius: 4px;
    overflow: hidden;
    margin-bottom: 8px;
}

.realistec-stereo-progress-fill {
    /* Mirrors Immersity's .realistec-mono-progress-fill, including the
       traveling shimmer (pulse) that signals active progress.

       Gradient angle: 90deg (horizontal) rather than 135deg. The brand
       --realistec-gradient token resolves to a 135deg diagonal, which is
       right for square/tall buttons but reads as a hot diagonal smear
       across an 8px-tall bar. Hardcoded values match the brand gradient
       stops (#8b5cf6 → #6366f1) but oriented to the bar's axis. */
    height: 100%;
    background: linear-gradient(90deg, #8b5cf6 0%, #6366f1 100%);
    border-radius: 4px;
    width: 0%;
    transition: width 0.3s ease;
    /* position + overflow contain the absolutely-positioned ::after
       shimmer so it travels along the FILLED portion only — without
       overflow:hidden the white sweep would extend beyond the current
       fill width and look like a separate floating element. */
    position: relative;
    overflow: hidden;
}

.realistec-stereo-progress-fill::after {
    /* Translucent white sweep that travels left-to-right across the
       fill bar on a 1.5s loop. Conveys "active / in-progress" the
       same way iOS/macOS shimmer skeletons do — the gradient stops
       are transparent → 40% white → transparent, so the highlight
       reads as a soft moving glint rather than a hard band.

       The translateX(-100%) → 100% animation moves the pseudo-element
       fully off-screen on both sides; combined with the parent's
       overflow: hidden, this produces a clean wipe with no edge
       artifacts. */
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
    animation: realistec-progress-shimmer 1.5s infinite;
}

@keyframes realistec-progress-shimmer {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(100%); }
}

.realistec-stereo-progress-text {
    font-size: 13px;
    color: var(--realistec-text-secondary, #a8a3c9);
}

/* =============================================
   STATUS MESSAGES (FILM-style)
   ============================================= */
.realistec-stereo-upload-status {
    margin-top: 16px;
    padding: 12px 16px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    gap: 10px;
}

.realistec-stereo-upload-status.success {
    /* Dark-mode success alert — translucent green wash on the deep
       surface, with the theme's success token for border + text. */
    background: rgba(16, 185, 129, 0.12);
    border: 1px solid var(--realistec-success, #10b981);
    color: var(--realistec-success, #10b981);
}

.realistec-stereo-upload-status.error {
    /* Dark-mode error alert — same pattern, error token. */
    background: rgba(239, 68, 68, 0.12);
    border: 1px solid var(--realistec-error, #ef4444);
    color: var(--realistec-error, #ef4444);
}

/* Status icon — wraps the Material Symbols 'check' or 'close' glyph
   emitted by showStatus() in the JS. Sized to read as a badge-ish
   prefix to the status text without dominating the alert. The parent
   .realistec-stereo-upload-status is already display: flex with gap: 10px so
   spacing is handled there; this rule just constrains the icon size
   and overrides the .realistec-stereo-msi default (18px) and vertical nudge
   (which were tuned for label contexts, not status alerts). */
.realistec-stereo-status-icon {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    color: inherit;
}

.realistec-stereo-status-icon .realistec-stereo-msi {
    font-size: 18px;
    margin-right: 0;
    vertical-align: baseline;
}

/* =============================================
   ERROR MESSAGES
   ============================================= */
.realistec-stereo-upload-errors {
    background: rgba(239, 68, 68, 0.12);
    color: var(--realistec-error, #ef4444);
    padding: 12px 16px;
    border-radius: 8px;
    margin-top: 16px;
    font-size: 14px;
}

/* =============================================
   COLOR CORRECTION
   ============================================= */
.realistec-stereo-match-color-option {
    margin: 20px 0;
    padding: 16px;
    background: var(--realistec-surface, #0d0b1f);
    border: 2px solid var(--realistec-border, #1f1b3a);
    border-radius: 12px;
    transition: all 0.2s ease;
}

.realistec-stereo-match-color-option:hover {
    border-color: var(--realistec-primary, #8b5cf6);
}

.realistec-stereo-match-color-option.enabled {
    border-color: var(--realistec-primary, #8b5cf6);
    background: rgba(139, 92, 246, 0.05);
}

.realistec-stereo-match-color-checkbox-label {
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    font-weight: 600;
    color: var(--realistec-text, #f5f3ff);
    margin: 0;
}

.realistec-stereo-match-color-checkbox-label input[type="checkbox"] {
    width: 18px;
    height: 18px;
    cursor: pointer;
    accent-color: var(--realistec-primary, #8b5cf6);
}

.realistec-stereo-match-color-description {
    margin: 10px 0 0 28px;
    font-size: 13px;
    color: var(--realistec-text-secondary, #a8a3c9);
    line-height: 1.5;
}

h4.realistec-stereo-match-color-reference-label {
    margin: 14px 0 10px 28px;
    font-size: 14px;
    color: var(--realistec-text, #f5f3ff);
}

.realistec-stereo-match-color-selector {
    display: flex;
    gap: 0;
    margin-left: 28px;
}

.realistec-stereo-match-color-selector .realistec-stereo-match-color-btn {
    flex: 1;
    padding: 8px 16px;
    font-size: 13px;
    font-weight: 500;
    border: 2px solid var(--realistec-border, #1f1b3a);
    background: var(--realistec-surface, #0d0b1f);
    color: var(--realistec-text, #f5f3ff);
    cursor: pointer;
    transition: all 0.2s ease;
    text-align: center;
}

.realistec-stereo-match-color-selector .realistec-stereo-match-color-btn:first-child {
    border-radius: 8px 0 0 8px;
}

.realistec-stereo-match-color-selector .realistec-stereo-match-color-btn:last-child {
    border-radius: 0 8px 8px 0;
}

.realistec-stereo-match-color-selector .realistec-stereo-match-color-btn:not(:first-child) {
    border-left: none;
}

.realistec-stereo-match-color-selector .realistec-stereo-match-color-btn:hover {
    background: var(--realistec-surface-2, #14112e);
}

.realistec-stereo-match-color-selector .realistec-stereo-match-color-btn.active {
    background: rgba(139, 92, 246, 0.05);
    border-color: var(--realistec-primary, #8b5cf6);
    color: var(--realistec-primary, #8b5cf6);
    font-weight: 600;
}

.realistec-stereo-match-color-selector .realistec-stereo-match-color-btn.active + .realistec-stereo-match-color-btn {
    border-left: none;
}

/* WCAG 2.1 contrast overrides for elements styled in external CSS */
.realistec-stereo-match-color-selection-label {
    color: white;
    background: linear-gradient(90deg, var(--realistec-primary, #8b5cf6) 0%, var(--realistec-primary-hover, #6366f1) 100%);
}

.realistec-stereo-hist-btn-reference {
    background: linear-gradient(135deg, var(--realistec-primary, #8b5cf6) 0%, var(--realistec-primary-hover, #6366f1) 100%);
    color: white;
}

.realistec-stereo-hist-btn-reference:hover {
    background: var(--realistec-gradient-hover, linear-gradient(135deg, #a78bfa 0%, #818cf8 100%));
    color: white;
}

/* =============================================
   ADD-TO-CART BUTTON
   =============================================
   THEME WE'RE FIGHTING — the Realistec theme's style.css applies these
   rules to .button.alt at specificity (0, 3, 0):

     .button.alt,
     .woocommerce a.button.alt,
     .woocommerce button.button.alt {
       background: var(--rt-indigo) !important;
       background-image: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%) !important;
     }

   Both are !important. The result is a darker, flatter indigo gradient
   that reads as solid against most surrounding UI. We want the brighter
   violet→indigo brand gradient (matching every other CTA in the plugin).

   To override !important we need both !important on our side AND a
   selector that beats specificity (0, 3, 0). We use:
     button.single_add_to_cart_button.button.alt
   which scores (0, 3, 1) — same class count, one extra tag, decisive win.
   Defensive looser selectors below cover variants without all the
   WooCommerce classes. */
button.single_add_to_cart_button.button.alt,
button.single_add_to_cart_button.button.alt:hover,
button.single_add_to_cart_button.button.alt:focus,
button.single_add_to_cart_button.button.alt:active {
    background: var(--rt-violet, #8b5cf6) !important;
    background-image: var(--rt-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%)) !important;
}

button.single_add_to_cart_button.button.alt:hover {
    background-image: var(--rt-gradient-hover, linear-gradient(135deg, #a78bfa 0%, #818cf8 100%)) !important;
    filter: brightness(1.05);
}

/* =============================================
   DISABLED STATE
   ============================================= */
.single_add_to_cart_button.realistec-stereo-disabled,
.single_add_to_cart_button[disabled],
.single_add_to_cart_button.disabled {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

/* Frame scrubber group — Left label | slider | Right label in one row */
.realistec-stereo-frame-scrubber-group {
    flex-direction: row !important;
    align-items: center !important;
    gap: 6px !important;
}

.realistec-stereo-frame-scrubber-group input[type="range"] {
    flex: 1;
    min-width: 0;
    width: auto;
    /* Brand-violet track + thumb — same treatment as #crop-opacity-slider
       (.realistec-stereo-crop-opacity-row input[type="range"] in section 1) so the two
       sidebar sliders look identical. Without these declarations the
       browser falls back to the default OS slider (light blue track,
       gray thumb) which clashes with the dark cosmic surface. */
    height: 6px;
    -webkit-appearance: none;
    appearance: none;
    background: linear-gradient(
        to right,
        var(--realistec-primary, #8b5cf6) 0%,
        var(--realistec-primary-hover, #6366f1) var(--range-pct, 50%),
        rgba(139, 92, 246, 0.2) var(--range-pct, 50%),
        rgba(139, 92, 246, 0.2) 100%
    );
    border-radius: 4px;
    outline: none;
    cursor: pointer;
    margin: 0;
}

.realistec-stereo-frame-scrubber-group input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--realistec-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    cursor: pointer;
    border: 2px solid white;
    box-shadow: 0 2px 6px rgba(139, 92, 246, 0.5), 0 1px 3px rgba(0, 0, 0, 0.2);
}

.realistec-stereo-frame-scrubber-group input[type="range"]::-moz-range-thumb {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--realistec-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    cursor: pointer;
    border: 2px solid white;
    box-shadow: 0 2px 6px rgba(139, 92, 246, 0.5), 0 1px 3px rgba(0, 0, 0, 0.2);
}

.realistec-stereo-frame-scrubber-group label,
.realistec-stereo-frame-scrubber-group .realistec-stereo-crop-frame-label-right {
    font-size: 11px;
    font-weight: 500;
    color: var(--realistec-text-secondary, #a8a3c9);
    white-space: nowrap;
    flex-shrink: 0;
}

.realistec-stereo-frame-scrubber-group #crop-frame-label {
    font-size: 11px;
    font-weight: 500;
    color: var(--realistec-text-secondary, #a8a3c9);
}

/* =============================================
   MAGNIFIER CANVAS (loupe overlay)
   ============================================= */
.realistec-stereo-magnifier-canvas {
    position: absolute;
    pointer-events: none;
    z-index: 10;
    display: none;
    border-radius: 50%;
    box-shadow: 0 2px 12px rgba(0,0,0,0.3);
}

/* =============================================
   AUTO-ALIGNMENT CHECKBOX
   ============================================= */
.realistec-stereo-auto-align-label {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    color: var(--realistec-text-dim, #6b6794);
    cursor: not-allowed;
    margin-left: auto;
    white-space: nowrap;
}

.realistec-stereo-auto-align-label input[type="checkbox"] {
    margin: 0;
    cursor: not-allowed;
    accent-color: var(--realistec-primary, #8b5cf6);
}

.realistec-stereo-auto-align-label span {
    user-select: none;
}

.realistec-stereo-auto-align-badge {
    font-size: 10px;
    font-weight: 600;
    color: var(--realistec-primary, #8b5cf6);
    background: rgba(139, 92, 246, 0.1);
    padding: 2px 6px;
    border-radius: 4px;
    text-transform: uppercase;
    letter-spacing: 0.3px;
}

/* =============================================
   ALIGNMENT STEP BUTTONS (+/-)  — FILM style
   ============================================= */
.realistec-stereo-align-step-btn {
    width: 26px;
    height: 26px;
    padding: 0;
    border: 2px solid rgba(255, 255, 255, 0.85);
    border-radius: 50%;
    background: transparent;
    color: var(--realistec-surface, #0d0b1f);
    font-size: 16px;
    font-weight: 700;
    line-height: 1;
    text-align: center;
    cursor: pointer;
    flex-shrink: 0;
    transition: background 0.15s, border-color 0.15s, transform 0.1s;
    display: flex;
    align-items: center;
    justify-content: center;
}

.realistec-stereo-align-step-btn:hover {
    background: var(--realistec-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    border-color: transparent;
}

.realistec-stereo-align-step-btn:active {
    transform: scale(0.9);
}

/* =============================================
   ALIGNMENT SLIDERS — flex layout, no JS positioning
   ============================================= */

/* Outer column: canvas+v-slider row on top, h-slider below */
/* Wrapper — fills the viewport, overflow visible for absolute-positioned sliders */
.realistec-stereo-crop-canvas-row {
    flex: 1;
    min-height: 0;
    width: 100%;
    display: flex;
    flex-direction: column;
    overflow: visible;
    position: relative;
}

/* Horizontal slider — absolutely positioned below canvas by JS */
.realistec-stereo-alignment-h-row {
    /* Floating control bar over the canvas. Was previously
       rgba(255, 255, 255, 0.88) — a near-white pill that read as a
       light theme leak against the dark cosmic surface. Now uses a
       dark translucent surface tinted with brand violet so it stays
       visible over both light and dark canvas content while reading
       as part of the dark theme.

       The 78% alpha keeps enough see-through that the canvas remains
       partially visible behind the controls; backdrop-filter blurs
       the canvas content for legibility. The 1px violet-tinted border
       ties the control bar to the brand. */
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    box-sizing: border-box;
    background: rgba(13, 11, 31, 0.78);
    border: 1px solid rgba(139, 92, 246, 0.25);
    border-radius: 20px;
    padding: 6px 10px;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35), 0 1px 4px rgba(0, 0, 0, 0.2);
}

.realistec-stereo-alignment-h-row .realistec-stereo-align-step-btn {
    border-color: rgba(139, 92, 246, 0.7);
    color: var(--rt-violet-bright, #a78bfa);
}

.realistec-stereo-alignment-h-row .realistec-stereo-align-step-btn:hover {
    background: var(--rt-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    border-color: transparent;
    color: white;
}

.realistec-stereo-alignment-h-row input[type="range"] {
    flex: 1;
    min-width: 0;
    height: 8px;
    -webkit-appearance: none;
    appearance: none;
    /* Bipolar fill — violet band spans from the center (50%) to the
       thumb position. The slider's range is min=-200 max=200 default=0,
       so JS sets --range-pct to 50% at the resting state, < 50% when
       offsetting left, > 50% when offsetting right. min()/max() resolve
       the band's start/end stops so the violet always fills outward
       from center toward the thumb regardless of direction:

         pct = 50  → band is 50% to 50%      (zero-width, track reads as empty)
         pct = 75  → band is 50% to 75%      (right half partially filled)
         pct = 25  → band is 25% to 50%      (left half partially filled)
         pct = 100 → band is 50% to 100%     (full right half)
         pct = 0   → band is 0% to 50%       (full left half)

       The two violet stops are --realistec-primary and --realistec-primary-hover
       so the band has the same dimensional gradient as the unipolar
       sliders. CSS min()/max() in gradient color stops: Chrome 79+,
       Firefox 75+, Safari 11.1+. */
    background: linear-gradient(
        to right,
        rgba(139, 92, 246, 0.2) 0%,
        rgba(139, 92, 246, 0.2) min(50%, var(--range-pct, 50%)),
        var(--realistec-primary, #8b5cf6)        min(50%, var(--range-pct, 50%)),
        var(--realistec-primary-hover, #6366f1)  max(50%, var(--range-pct, 50%)),
        rgba(139, 92, 246, 0.2) max(50%, var(--range-pct, 50%)),
        rgba(139, 92, 246, 0.2) 100%
    );
    border-radius: 4px;
    outline: none;
    margin: 0;
    cursor: pointer;
}

.realistec-stereo-alignment-h-row input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--realistec-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    cursor: pointer;
    border: 2px solid white;
    box-shadow: 0 2px 8px rgba(139, 92, 246, 0.5), 0 1px 3px rgba(0, 0, 0, 0.2);
}

.realistec-stereo-alignment-h-row input[type="range"]::-moz-range-thumb {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--realistec-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    cursor: pointer;
    border: 2px solid white;
    box-shadow: 0 2px 8px rgba(139, 92, 246, 0.5), 0 1px 3px rgba(0, 0, 0, 0.2);
}

/* Vertical slider — absolutely positioned to the right of canvas by JS */
.realistec-stereo-alignment-v-column {
    /* Same floating-control treatment as .realistec-stereo-alignment-h-row above —
       dark translucent surface tinted with brand violet, replacing the
       previous near-white pill that read as a light theme leak. */
    position: absolute;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    box-sizing: border-box;
    background: rgba(13, 11, 31, 0.78);
    border: 1px solid rgba(139, 92, 246, 0.25);
    border-radius: 20px;
    padding: 10px 6px;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35), 0 1px 4px rgba(0, 0, 0, 0.2);
}

.realistec-stereo-alignment-v-column .realistec-stereo-align-step-btn {
    border-color: rgba(139, 92, 246, 0.7);
    color: var(--rt-violet-bright, #a78bfa);
}

.realistec-stereo-alignment-v-column .realistec-stereo-align-step-btn:hover {
    background: var(--rt-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    border-color: transparent;
    color: white;
}

/* Vertical range input */
.realistec-stereo-alignment-v-column input[type="range"] {
    writing-mode: vertical-lr;
    direction: rtl;
    width: 8px;
    flex: 1;
    min-height: 0;
    /* Bipolar fill — see .realistec-stereo-alignment-h-row above for the full rationale.
       Same gradient construction; only the direction changes (`to top`
       so the visual y-axis matches the slider's perceived orientation,
       with the higher values at the top). At rest (--range-pct: 50%)
       the band has zero width and the track reads as empty. */
    background: linear-gradient(
        to top,
        rgba(139, 92, 246, 0.2) 0%,
        rgba(139, 92, 246, 0.2) min(50%, var(--range-pct, 50%)),
        var(--realistec-primary, #8b5cf6)        min(50%, var(--range-pct, 50%)),
        var(--realistec-primary-hover, #6366f1)  max(50%, var(--range-pct, 50%)),
        rgba(139, 92, 246, 0.2) max(50%, var(--range-pct, 50%)),
        rgba(139, 92, 246, 0.2) 100%
    );
    border-radius: 4px;
    outline: none;
    cursor: pointer;
    margin: 0;
    -webkit-appearance: none;
    appearance: none;
}

/* Firefox vertical track */
.realistec-stereo-alignment-v-column input[type="range"]::-moz-range-track {
    width: 8px;
    background: rgba(139, 92, 246, 0.2);
    border-radius: 4px;
}

.realistec-stereo-alignment-v-column input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--realistec-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    cursor: pointer;
    border: 2px solid white;
    box-shadow: 0 2px 8px rgba(139, 92, 246, 0.5), 0 1px 3px rgba(0, 0, 0, 0.2);
}

.realistec-stereo-alignment-v-column input[type="range"]::-moz-range-thumb {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--realistec-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    cursor: pointer;
    border: 2px solid white;
    box-shadow: 0 2px 8px rgba(139, 92, 246, 0.5), 0 1px 3px rgba(0, 0, 0, 0.2);
}

/* Overlap info shown in realistec-stereo-crop-info bar */
.realistec-stereo-crop-info .realistec-stereo-overlap-info {
    color: var(--realistec-primary, #8b5cf6);
    font-weight: 500;
}

.realistec-stereo-crop-btn-secondary {
    /* Mirrors the Immersity plugin's .realistec-mono-modal-btn-secondary
       — same Reset-button treatment as the modal-footer variant above
       (in this file's section 1). Uses the modal-scoped --modal-* vars
       declared on .realistec-stereo-crop-modal:
         background      -> --modal-surface  (= --rt-bg-3)
         color           -> --modal-text     (= --rt-text)
         border          -> --modal-border
         hover bg        -> --modal-border
         hover color     -> --modal-text-secondary

       Note: this block sits inside the editor-sidebar styling and shares
       the .realistec-stereo-crop-btn-secondary class with the modal footer's Cancel button.
       Both must reference the same variable set so the two visually match
       — the Reset button (sidebar) and the Cancel button (footer) appear
       on the same modal at the same time. */
    padding: 6px 14px;
    background: var(--modal-surface, #14112e);
    color: var(--modal-text, #f5f3ff);
    border: 1px solid var(--modal-border, #1f1b3a);
    border-radius: 6px;
    font-size: 13px;
    cursor: pointer;
    transition: background 0.2s, border-color 0.2s, color 0.2s;
}

.realistec-stereo-crop-btn-secondary:hover {
    background: var(--modal-border, #1f1b3a);
    /* Without an explicit color, the theme's generic button:hover rule
       (style.css line 636) sets color:#fff !important on hover. That's
       fine here since the bg is also dark, but we set it explicitly so
       the button resists external rule changes — same trick the Immersity
       reference uses (with the same comment). */
    color: var(--modal-text-secondary, #a8a3c9);
}

.realistec-stereo-crop-btn-primary {
    padding: 8px 20px;
    background: var(--realistec-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    color: white;
    border: none;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    transition: opacity 0.2s;
}

.realistec-stereo-crop-btn-primary:hover {
    background: var(--realistec-gradient-hover, linear-gradient(135deg, #a78bfa 0%, #818cf8 100%));
    opacity: 0.9;
}

/* =============================================
   RESPONSIVE
   ============================================= */
@media (max-width: 600px) {
    .realistec-stereo-upload-interface {
        padding: 16px;
    }
    
    .realistec-stereo-upload-area {
        padding: 32px 16px;
    }
    
    .realistec-stereo-type-options {
        flex-direction: column;
    }
    
    .realistec-stereo-type-option {
        min-width: 100%;
    }
    
    .realistec-stereo-frame-previews-header {
        flex-direction: column;
        align-items: flex-start;
    }
    
    .realistec-stereo-frame-previews-list {
        justify-content: center;
    }
    
    .realistec-stereo-frame-preview-item {
        min-width: 130px;
        max-width: 250px;
    }
    
    .realistec-stereo-frame-preview-item .realistec-stereo-frame-image {
        height: 80px;
    }
}

/* =============================================
   REDUCED MOTION
   =============================================
   Honor users who prefer reduced motion (set in their OS — macOS,
   iOS, Windows all expose this preference). The progress bar's
   shimmer animation reads as decorative motion that doesn't convey
   information beyond what the fill width already shows, so it's a
   safe candidate to disable. Mirrors Immersity's reduced-motion
   block — same animation: none + transition: none pattern. */
@media (prefers-reduced-motion: reduce) {
    .realistec-stereo-progress-fill::after {
        animation: none;
    }

    .realistec-stereo-upload-progress {
        transition: none;
    }
}
