/**
 * Realistec-Mono AI - Upload Interface CSS
 * Version: 2.1.0
 * Dark theme styled to match Realistec brand: violet gradient CTAs
 * (#8b5cf6 → #6366f1), Space Grotesk display type, subtle starfield.
 *
 * 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).
 */

/* =============================================
   GLOBAL RESETS — apply to every interactive element in the plugin's
   three render scopes (the inline upload interface, the photo editor
   modal, and the histogram/effects editor modal).
   ============================================= */

/* Suppress the mobile browser default tap-highlight: a semi-transparent
   blue overlay that flashes briefly on tap. Browsers default this to
   system blue (rgba(0, 0, 0, 0.18) on iOS Safari, rgba(0, 0, 0, 0.10)
   on Chrome) which reads as off-brand against the violet/indigo design
   language. Setting this to transparent doesn't remove tap feedback —
   it just makes the per-element :hover/:active/.active styles the
   sole source of truth, which is what we want. The selector covers
   the three scopes and all their descendants in one rule. */
.realistec-mono-upload-interface,
.realistec-mono-upload-interface *,
.realistec-mono-modal-overlay,
.realistec-mono-modal-overlay *,
#realistec-mono-color-filter-modal,
#realistec-mono-color-filter-modal * {
    -webkit-tap-highlight-color: transparent;
}

/* =============================================
   BASE STYLES
   ============================================= */
.realistec-mono-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-mono-primary: var(--rt-violet, #8b5cf6);          /* gradient start, also used solid */
    --realistec-mono-primary-hover: var(--rt-indigo, #6366f1);    /* gradient end, also used solid */
    --realistec-mono-gradient: var(--rt-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    --realistec-mono-gradient-hover: var(--rt-gradient-hover, linear-gradient(135deg, #a78bfa 0%, #818cf8 100%));
    --realistec-mono-link: var(--rt-violet-bright, #a78bfa);      /* lighter accent, used for links/icons */
    --realistec-mono-success: var(--rt-success, #10b981);
    --realistec-mono-error: var(--rt-error, #ef4444);
    --realistec-mono-bg: var(--rt-bg, #07060f);                   /* page background */
    --realistec-mono-surface: var(--rt-bg-2, #0d0b1f);            /* elevated panel surface */
    --realistec-mono-surface-2: var(--rt-bg-3, #14112e);          /* nested surface (depth thumbs, preview frames) */
    /* 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-mono-border: #1f1b3a;
    --realistec-mono-text: var(--rt-text, #f5f3ff);
    --realistec-mono-text-secondary: var(--rt-text-muted, #a8a3c9);

    /* Subtle starfield — three radial-gradient layers at different scales
       and offsets compose a non-repeating-feeling field of dim stars.
       Kept faint (alpha 0.10–0.22) so it reads as atmosphere, not noise.
       Pinned with `background-attachment: local` so the field doesn't
       reflow if a parent container scrolls. */
    background-color: var(--realistec-mono-bg);
    background-image:
        radial-gradient(1px 1px at 20px 30px,  rgba(245, 243, 255, 0.22), transparent 50%),
        radial-gradient(1px 1px at 80px 120px, rgba(167, 139, 250, 0.18), transparent 50%),
        radial-gradient(1px 1px at 150px 60px, rgba(245, 243, 255, 0.14), transparent 50%),
        radial-gradient(1px 1px at 240px 200px, rgba(167, 139, 250, 0.20), transparent 50%),
        radial-gradient(1px 1px at 60px 250px, rgba(245, 243, 255, 0.10), transparent 50%),
        radial-gradient(1px 1px at 320px 90px, rgba(245, 243, 255, 0.16), transparent 50%);
    background-size: 380px 320px, 380px 320px, 380px 320px, 380px 320px, 380px 320px, 380px 320px;
    background-repeat: repeat;
    border: 2px solid var(--realistec-mono-border);
    border-radius: 12px;
    padding: 25px;
    margin: 20px 0;
    font-family: var(--rt-font-body, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
}

.realistec-mono-upload-header h3 {
    margin-top: 0;
    margin-bottom: 8px;
    color: var(--realistec-mono-text);
    font-size: 20px;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 10px;
}

.realistec-mono-upload-header h3::before {
    content: "upload";
    font-family: 'Material Symbols Outlined';
    font-weight: normal;
    font-style: normal;
    font-size: 24px;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    display: inline-block;
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
    -webkit-font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased;
    font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
    color: var(--realistec-mono-primary);
}

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

/* 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 (descriptions, hints, file metadata) stays on
   the system stack via the body font on .realistec-mono-upload-interface
   for readability. */
.realistec-mono-upload-interface h3,
.realistec-mono-upload-interface h4,
.realistec-mono-upload-interface .realistec-mono-type-label {
    font-family: var(--rt-font-display, 'Space Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
    letter-spacing: -0.01em;
}

/* =============================================
   UPLOAD TYPE SELECTOR - Card Style Radio Buttons
   Matches replicate plugin design
   ============================================= */
.realistec-mono-upload-type-selector {
    margin-bottom: 24px;
}

.realistec-mono-upload-type-selector h4 {
    margin: 0 0 12px 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--realistec-mono-text);
}

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

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

/* Hide native radio button */
.realistec-mono-type-option input[type="radio"] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

/* Card label */
.realistec-mono-type-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 20px;
    background: var(--realistec-mono-surface);
    border: 2px solid var(--realistec-mono-border);
    border-radius: 12px;
    /* Explicit transition list so border-color, background, and the
       box-shadow that powers focus/checked rings all animate together.
       `all` would technically work here too but listing properties is
       safer because some properties (notably `outline`) don't animate
       reliably and silently no-op when included in `all`. */
    transition: border-color 0.2s ease, background 0.2s ease, box-shadow 0.2s ease;
    text-align: center;
    cursor: pointer;
}

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

/* Focus state for accessibility — implemented as box-shadow rather than
   outline so it participates in the card's transition (outline doesn't
   animate reliably and snaps in instantly, which produced a brief white
   flash on click before the :checked transition caught up). The shadow
   is layered: the inner 0/0/0/3 ring matches the :checked state's
   shadow size for visual continuity, and the outer 0/0/0/5 adds a
   gentle violet halo so focus remains distinct from checked. */
.realistec-mono-type-option input[type="radio"]:focus-visible + .realistec-mono-type-card {
    box-shadow:
        0 0 0 3px rgba(139, 92, 246, 0.25),
        0 0 0 5px rgba(139, 92, 246, 0.10);
}

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

/* Hover state */
.realistec-mono-type-card:hover {
    border-color: var(--realistec-mono-primary);
}

.realistec-mono-type-icon {
    color: var(--realistec-mono-primary);
    margin-bottom: 12px;
}

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

.realistec-mono-type-desc {
    font-size: 12px;
    color: #595959;
}

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

.realistec-mono-upload-area {
    background: var(--realistec-mono-surface);
    border: 2px dashed var(--realistec-mono-border);
    border-radius: 12px;
    padding: 48px 24px;
    text-align: center;
    cursor: pointer;
    transition: all 0.2s ease;
    position: relative;
}

.realistec-mono-upload-area:hover,
.realistec-mono-upload-area.realistec-mono-drag-over {
    border-color: var(--realistec-mono-primary);
    background: rgba(139, 92, 246, 0.04);
}

.realistec-mono-upload-area.realistec-mono-drag-over {
    transform: scale(1.01);
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.15);
}

/* Smaller upload area for depth map */
.realistec-mono-upload-area-small {
    padding: 28px 20px;
}

.realistec-mono-upload-icon {
    color: var(--realistec-mono-primary);
    margin-bottom: 16px;
}

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

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

/* Allowed-format badges shown in the upload-area prompt. The container
   holds them in a centered horizontal row; each badge is a small pill
   with the plugins indigo accent so the supported formats are visible
   at a glance without a wall of comma-separated text. */
.realistec-mono-format-badges {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0 0 10px 0;
}

.realistec-mono-format-badge {
    display: inline-block;
    padding: 3px 10px;
    background: rgba(139, 92, 246, 0.1);
    color: var(--realistec-mono-primary);
    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 the cap-height of mixed-case names like "WebP"
       sitting cleanly with the all-uppercase labels above */
    font-feature-settings: "tnum";
}

.realistec-mono-file-input {
    position: absolute;
    left: -9999px;
    opacity: 0;
}

/* =============================================
   IMAGE PREVIEW
   ============================================= */
.realistec-mono-image-preview {
    background: var(--realistec-mono-surface);
    border-radius: 12px;
    padding: 16px;
    border: 2px solid var(--realistec-mono-primary);
}

.realistec-mono-preview-container {
    background: var(--realistec-mono-surface-2);
    border-radius: 8px;
    overflow: hidden;
    margin-bottom: 16px;
    display: flex;
    justify-content: center;
    align-items: center;
}

.realistec-mono-preview-container img {
    width: 100%;
    height: auto;
    aspect-ratio: 1 / 1;
    object-fit: contain;
    transition: transform 0.3s ease;
}

.realistec-mono-preview-container:hover img {
    transform: scale(1.02);
}

.realistec-mono-file-info {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
}

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

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

.realistec-mono-file-size,
.realistec-mono-file-dimensions {
    font-size: 12px;
    color: var(--realistec-mono-text-secondary);
}

/* =============================================
   DEPTH MAP SECTION
   ============================================= */
.realistec-mono-depth-map-section {
    margin-top: 20px;
}

/* Extraction status */
.realistec-mono-depth-status {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 18px;
    background: var(--realistec-mono-surface);
    border: 2px solid var(--realistec-mono-border);
    border-radius: 12px;
    margin-bottom: 16px;
}

.realistec-mono-depth-status-text {
    font-size: 14px;
    color: var(--realistec-mono-text-secondary);
    font-weight: 500;
}

/* Extracted depth map */
.realistec-mono-depth-extracted {
    background: var(--realistec-mono-surface);
    border: 2px solid var(--realistec-mono-primary);
    border-radius: 12px;
    padding: 16px;
    margin-bottom: 16px;
}

.realistec-mono-depth-extracted-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
    flex-wrap: wrap;
    gap: 8px;
}

.realistec-mono-depth-extracted-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    /* Success badge — emerald wash matching the success status pill,
       just at smaller scale (no border to keep the badge compact). */
    background: rgba(16, 185, 129, 0.15);
    color: #34d399;                          /* emerald-400 */
    border-radius: 6px;
    font-size: 13px;
    font-weight: 600;
}

.realistec-mono-depth-extracted-badge.realistec-mono-badge-manual {
    /* Manual variant — amber wash matching the manual notice it
       appears alongside. Was previously an off-brand indigo wash
       (rgba(139, 92, 246, …)) which neither matched the brand
       palette nor signaled "manual" as a distinct state. */
    background: rgba(245, 158, 11, 0.15);
    color: #fbbf24;                          /* amber-400 */
}

.realistec-mono-depth-preview-row {
    display: flex;
    gap: 16px;
    justify-content: center;
}

.realistec-mono-depth-thumb {
    text-align: center;
    background: var(--realistec-mono-surface-2);
    border-radius: 8px;
    padding: 12px;
    width: 100%;
}

.realistec-mono-depth-thumb img {
    max-width: 100%;
    width: auto;
    height: auto;
    border-radius: 6px;
    object-fit: contain;
}

.realistec-mono-depth-thumb-label {
    display: block;
    margin-top: 8px;
    font-size: 12px;
    font-weight: 600;
    color: var(--realistec-mono-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

/* Manual depth upload notice */
.realistec-mono-depth-manual-header {
    margin-bottom: 16px;
}

.realistec-mono-depth-manual-notice {
    margin-top: 16px;
    padding: 12px 16px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    gap: 10px;
    /* Warning state — same formula as success/error status pills:
       saturated amber-500 wash + denser amber-500 border + amber-400
       foreground. Reads confidently against #07060f without the
       pastel-alert glow of the previous #fef3c7 / #92400e values. */
    background: rgba(245, 158, 11, 0.12);
    border: 1px solid rgba(245, 158, 11, 0.35);
    color: #fbbf24;                          /* amber-400 */
}

.realistec-mono-depth-manual-desc {
    margin: 8px 0 0 0;
    font-size: 13px;
    color: var(--realistec-mono-text-secondary);
    line-height: 1.5;
}

/* Depth-only hint in requirements */
.realistec-mono-depth-only {
    color: var(--realistec-mono-primary);
    font-weight: 500;
}

/* =============================================
   BUTTONS
   ============================================= */
.realistec-mono-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-mono-btn-secondary {
    background: #f1f3f4;
    color: var(--realistec-mono-text);
}

.realistec-mono-btn-secondary:hover {
    background: #e2e6ea;
}

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

/* =============================================
   PROGRESS BAR
   ============================================= */
.realistec-mono-upload-progress {
    margin-top: 16px;
    padding: 16px;
    background: var(--realistec-mono-surface);
    border-radius: 8px;
    border: 1px solid var(--realistec-mono-border);
}

.realistec-mono-progress-bar {
    height: 8px;
    /* Dark track inside the dark panel — surface-2 gives just enough
       contrast that the empty portion of the bar is visible. */
    background: var(--realistec-mono-surface-2);
    border-radius: 4px;
    overflow: hidden;
    margin-bottom: 8px;
}

.realistec-mono-progress-fill {
    height: 100%;
    /* Signature gradient — matches primary CTAs. The previous gradient
       went from --realistec-mono-primary (#8b5cf6) to #8b5cf6, which
       rendered as a flat color once the primary var was retargeted. */
    background: linear-gradient(90deg, #8b5cf6 0%, #6366f1 100%);
    border-radius: 4px;
    width: 0%;
    transition: width 0.3s ease;
    position: relative;
    overflow: hidden;
}

.realistec-mono-progress-fill::after {
    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-mono-shimmer 1.5s infinite;
}

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

.realistec-mono-progress-text {
    font-size: 13px;
    color: var(--realistec-mono-text-secondary);
}

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

/* Status pills follow the same formula as the modal close button —
   saturated foreground color for icon/text, low-alpha wash for the
   background, slightly denser same-hue border. This reads confidently
   on the very dark page surface (#07060f) without the pastel-alert
   glow that the previous Bootstrap-3-style values produced. */
.realistec-mono-upload-status.success {
    background: rgba(16, 185, 129, 0.12);   /* #10b981 wash — emerald-500 */
    border: 1px solid rgba(16, 185, 129, 0.35);
    color: #34d399;                          /* emerald-400 — slightly brighter
                                                so the text reads against the
                                                already-tinted background */
}

.realistec-mono-upload-status.error {
    background: rgba(239, 68, 68, 0.12);    /* #ef4444 wash — matches close button */
    border: 1px solid rgba(239, 68, 68, 0.35);
    color: #f87171;                          /* red-400 */
}

/* =============================================
   ERROR MESSAGES
   ============================================= */
.realistec-mono-upload-errors {
    background: rgba(239, 68, 68, 0.12);
    border: 1px solid rgba(239, 68, 68, 0.35);
    color: #f87171;
    padding: 12px 16px;
    border-radius: 8px;
    margin-top: 16px;
    font-size: 14px;
    animation: realistec-mono-shake 0.3s ease-in-out;
}

@keyframes realistec-mono-shake {
    0%, 100% { transform: translateX(0); }
    25% { transform: translateX(-5px); }
    75% { transform: translateX(5px); }
}

/* =============================================
   REQUIREMENTS / INFO BOXES
   ============================================= */
.realistec-mono-upload-requirements,
.realistec-mono-animation-info {
    margin-top: 24px;
    padding: 18px;
    background: var(--realistec-mono-surface);
    border-radius: 10px;
    border-left: 4px solid var(--realistec-mono-primary);
}

.realistec-mono-upload-requirements h4,
.realistec-mono-animation-info h4 {
    margin: 0 0 10px 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--realistec-mono-text);
}

.realistec-mono-upload-requirements ul,
.realistec-mono-animation-info ul {
    margin: 0;
    padding-left: 20px;
}

.realistec-mono-upload-requirements li,
.realistec-mono-animation-info li {
    font-size: 13px;
    color: var(--realistec-mono-text-secondary);
    margin: 6px 0;
    line-height: 1.5;
}

.realistec-mono-animation-info {
    border-left-color: var(--realistec-mono-success);
}

/* =============================================
   SPINNER
   ============================================= */
.realistec-mono-spinner {
    display: inline-block;
    width: 18px;
    height: 18px;
    border: 2px solid rgba(139, 92, 246, 0.3);
    border-top-color: var(--realistec-mono-primary);
    border-radius: 50%;
    animation: realistec-mono-spin 0.8s linear infinite;
}

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

/* =============================================
   DISABLED STATE
   ============================================= */
.single-add-to-cart-button.realistec-mono-disabled,
.single_add_to_cart_button.realistec-mono-disabled {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

/* While a save is in flight, dim/disable interaction and show a tinted
   background so the loading state reads clearly. position:relative anchors
   the absolutely-positioned spinner that gets appended inside.

   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 them, our selector must beat
   specificity (0, 2, 1). We use `button.single_add_to_cart_button.button.alt.realistec-mono-saving-crop`
   which scores (0, 4, 1) — same tag count, two more classes, decisive win.

   Critically, the theme also sets `background-image` on `.button.alt`,
   which is a separate property from `background-color`. A `!important`
   `background: #343582` on our side resets background-image to none, but
   we set background-image explicitly too as defense in depth.

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

button.single_add_to_cart_button.button.alt.realistec-mono-saving-crop,
button.single_add_to_cart_button.button.alt.realistec-mono-saving-crop:hover,
button.single_add_to_cart_button.button.alt.realistec-mono-saving-crop:focus,
button.single_add_to_cart_button.button.alt.realistec-mono-saving-crop:active,
button.single_add_to_cart_button.button.alt.realistec-mono-saving-crop[disabled],
button.single_add_to_cart_button.button.alt.realistec-mono-saving-crop:disabled,
/* Looser selectors for buttons without all the WC classes (defensive — covers
   custom add-to-cart implementations that don't apply .button.alt). */
.single_add_to_cart_button.realistec-mono-saving-crop,
.single_add_to_cart_button.realistec-mono-saving-crop[disabled],
.single_add_to_cart_button.realistec-mono-saving-crop:disabled,
/* Backward-compat for the older hyphenated class name */
.single-add-to-cart-button.realistec-mono-saving-crop,
.single-add-to-cart-button.realistec-mono-saving-crop[disabled],
.single-add-to-cart-button.realistec-mono-saving-crop:disabled {
    cursor: wait !important;
    pointer-events: none;
    position: relative;
    /* Loading state uses the brand violet gradient (#8b5cf6 → #6366f1) —
       same gradient as the resting CTA, so the spinner appears on the
       button's normal background rather than a darkened disabled-color
       variant. The theme's `.button.alt` rule sets background-image
       !important, so we set background-image (gradient) and background-
       color (fallback solid) explicitly with !important to win. */
    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: color:transparent for the visible-glyph
       case, font-size:0 as a layout-based fallback the theme can't
       override via the color cascade. */
    color: transparent !important;
    font-size: 0 !important;
    /* Dimensions in PIXELS, not em — because font-size:0 makes em units
       resolve to 0 too. Without explicit pixel values here the entire
       button collapses to zero size (only the absolutely-positioned
       spinner remains visible). The theme uses padding: 0.85em 1.75em
       !important and we have to override that with concrete pixels for
       the same reason. Values picked to preserve the button's natural
       resting size (~14px text * 0.85em vertical, * 1.75em horizontal). */
    padding: 12px 28px !important;
    min-height: 44px !important;
    min-width: 140px !important;
    line-height: normal !important;
    /* Theme also sets a glow shadow on hover; null it out for the
       loading state since hover is no-op while pointer-events:none. */
    filter: none !important;
    /* Defensive: many themes apply opacity: 0.5 (or similar) to disabled
       buttons, which would mute the gradient. The button IS functionally
       disabled (pointer-events:none + cursor:wait), but we want it to
       still LOOK like the resting CTA so the spinner reads against the
       full-saturation gradient rather than a dimmed one. */
    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-mono-btn-spinner are explicit pixels but resetting font-size
   is defensive against any inherited 0. */
button.single_add_to_cart_button.realistec-mono-saving-crop .realistec-mono-btn-spinner,
.single_add_to_cart_button.realistec-mono-saving-crop .realistec-mono-btn-spinner,
.single-add-to-cart-button.realistec-mono-saving-crop .realistec-mono-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-mono-saving-crop > *:not(.realistec-mono-btn-spinner),
.single-add-to-cart-button.realistec-mono-saving-crop > *:not(.realistec-mono-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-mono-saving-crop::before,
.single_add_to_cart_button.realistec-mono-saving-crop::after,
.single-add-to-cart-button.realistec-mono-saving-crop::before,
.single-add-to-cart-button.realistec-mono-saving-crop::after {
    content: none !important;
}

.realistec-mono-btn-spinner {
    display: inline-block;
    width: 16px !important;
    height: 16px !important;
    /* Matches the WooCommerce Cart Block "Proceed to Checkout" spinner
       (.wc-block-components-button) — a thicker white 3/4-circle ring on
       a transparent track, so loading states across the storefront read
       as one consistent design. The ring is mostly transparent with
       three sides white; the fourth (top) side stays transparent,
       producing the visible gap as the element rotates.

       !important on border colors is defensive — themes (especially
       WooCommerce-aware ones) often have rules targeting button
       descendants that can muddy the white into a gray. The transparent
       top border also gets !important so the gap doesn't get filled in.

       Stroke is 2px (was 1.5px) and size is 16px (was 14px) to match
       the visual weight of the cart block's spinner — at smaller sizes
       the ring reads as too delicate against the gradient. */
    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-mono-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-mono-saving-crop .realistec-mono-btn-spinner,
.single_add_to_cart_button.realistec-mono-saving-crop .realistec-mono-btn-spinner {
    position: absolute;
    top: 50%;
    left: 50%;
    margin: -8px 0 0 -8px; /* half of 16px width/height to center on the anchor point */
}

/* =============================================
   ANIMATIONS
   ============================================= */
.realistec-mono-upload-area,
.realistec-mono-image-preview,
.realistec-mono-upload-progress,
.realistec-mono-upload-status,
.realistec-mono-upload-errors {
    transition: all 0.3s ease;
}

/* Success checkmark */
@keyframes realistec-mono-checkmark {
    0% { transform: scale(0); }
    50% { transform: scale(1.2); }
    100% { transform: scale(1); }
}

.realistec-mono-upload-status.success .realistec-mono-status-icon {
    animation: realistec-mono-checkmark 0.3s ease-out;
}

/* =============================================
   ACCESSIBILITY
   ============================================= */
.realistec-mono-upload-area:focus-within {
    outline: 2px solid var(--realistec-mono-primary);
    outline-offset: 2px;
}

.realistec-mono-btn:focus {
    outline: 2px solid var(--realistec-mono-primary);
    outline-offset: 2px;
}

/* =============================================
   RESPONSIVE
   ============================================= */
@media (max-width: 600px) {
    .realistec-mono-upload-interface {
        padding: 16px;
    }
    
    .realistec-mono-upload-area {
        padding: 32px 16px;
    }
    
    .realistec-mono-type-options {
        flex-direction: column;
    }
    
    .realistec-mono-type-option {
        min-width: 100%;
    }
    
    .realistec-mono-file-info {
        flex-direction: column;
        align-items: flex-start;
    }
    
    .realistec-mono-depth-preview-row {
        flex-direction: column;
        align-items: center;
    }
}

/* =============================================
   DARK THEME (default — Realistec brand palette)
   ============================================= */
.realistec-mono-upload-interface .realistec-mono-upload-area {
    background: var(--realistec-mono-surface);
    border-color: var(--realistec-mono-border);
}

.realistec-mono-upload-interface .realistec-mono-upload-area:hover {
    /* Violet wash on hover — uses primary (#8b5cf6) at low alpha to pop
       against the very dark page background. */
    background: rgba(139, 92, 246, 0.08);
    /* border-color must be set HERE too, not just on the lower-specificity
       .realistec-mono-upload-area:hover rule (line ~260). That rule and the
       resting-state .realistec-mono-upload-interface .realistec-mono-upload-
       area rule (line ~947) have equal specificity (0,2,0), and the
       resting-state rule comes later in source — so it was overriding the
       hover border-color, leaving the dashed border grey on hover. Setting
       it on this (0,3,0) rule makes the dashed border turn brand violet on
       hover, matching the Realistec plugin's .realistec-upload-area:hover
       behaviour. The 2px dashed border-style/width from the base rule
       (line ~249) is untouched, so only the colour animates. */
    border-color: var(--realistec-mono-primary);
}

/* Drag-over needs the same treatment as :hover above — the lower-
   specificity .realistec-mono-upload-area.realistec-mono-drag-over rule
   (line ~261) is overridden by the equal-specificity, later resting-state
   .realistec-mono-upload-interface .realistec-mono-upload-area rule
   (line ~947). This (0,3,0) rule restores the violet dashed border while
   a file is being dragged over the dropzone. */
.realistec-mono-upload-interface .realistec-mono-upload-area.realistec-mono-drag-over {
    border-color: var(--realistec-mono-primary);
    background: rgba(139, 92, 246, 0.08);
}

.realistec-mono-upload-interface .realistec-mono-type-card {
    background: var(--realistec-mono-surface);
    border-color: var(--realistec-mono-border);
}

.realistec-mono-upload-interface .realistec-mono-type-option input[type="radio"]:checked + .realistec-mono-type-card {
    background: rgba(139, 92, 246, 0.10);
}

.realistec-mono-upload-interface .realistec-mono-image-preview,
.realistec-mono-upload-interface .realistec-mono-depth-extracted,
.realistec-mono-upload-interface .realistec-mono-depth-status {
    background: var(--realistec-mono-surface);
}

.realistec-mono-upload-interface .realistec-mono-preview-container,
.realistec-mono-upload-interface .realistec-mono-depth-thumb {
    /* Slightly lighter nested surface so the image inside has a faint
       frame against the panel it sits in. */
    background: var(--realistec-mono-surface-2);
}

.realistec-mono-upload-interface .realistec-mono-upload-requirements,
.realistec-mono-upload-interface .realistec-mono-animation-info {
    background: var(--realistec-mono-surface);
}

/* Secondary buttons stay solid (per the gradient policy: CTAs only).
   Surface-2 is light enough to read as a button against panel surfaces. */
.realistec-mono-upload-interface .realistec-mono-btn-secondary {
    background: var(--realistec-mono-surface-2);
    color: var(--realistec-mono-text);
    border: 1px solid var(--realistec-mono-border);
}

.realistec-mono-upload-interface .realistec-mono-btn-secondary:hover {
    background: #1f1b3a;
    border-color: var(--realistec-mono-primary);
}

/* Suppress the browser-default focus outline that flashes white on mouse
   click. Same bug class as the type-options cards above. */
.realistec-mono-upload-interface .realistec-mono-btn-secondary:focus {
    outline: none;
}

/* Replace with a violet focus ring shown only on keyboard navigation.
   :focus-visible does not trigger on mouse clicks, so there is no flash,
   but tab-key users still get a clear, accessible focus indicator. */
.realistec-mono-upload-interface .realistec-mono-btn-secondary:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.25);
}

.realistec-mono-upload-interface .realistec-mono-crop-option {
    background: var(--realistec-mono-surface);
    border-color: var(--realistec-mono-border);
}

.realistec-mono-upload-interface .realistec-mono-crop-option:hover {
    border-color: var(--realistec-mono-primary);
}

.realistec-mono-upload-interface .realistec-mono-crop-option.enabled {
    background: rgba(139, 92, 246, 0.10);
    border-color: var(--realistec-mono-primary);
}

.realistec-mono-upload-interface .realistec-mono-crop-checkbox-label {
    color: var(--realistec-mono-text);
}

.realistec-mono-upload-interface .realistec-mono-crop-description {
    color: var(--realistec-mono-text-secondary);
}

.realistec-mono-upload-interface .realistec-mono-edit-crop-btn {
    background: var(--realistec-mono-surface-2);
    color: var(--realistec-mono-text);
}

.realistec-mono-upload-interface .realistec-mono-edit-crop-btn:hover {
    background: #1f1b3a;
}

.realistec-mono-upload-interface .realistec-mono-type-label,
.realistec-mono-upload-interface .realistec-mono-upload-text,
.realistec-mono-upload-interface h3,
.realistec-mono-upload-interface h4 {
    color: var(--realistec-mono-text);
}

.realistec-mono-upload-interface .realistec-mono-type-desc {
    color: var(--realistec-mono-text-secondary);
}

/* =============================================
   HIGH CONTRAST
   ============================================= */
@media (prefers-contrast: high) {
    .realistec-mono-upload-interface {
        border-width: 3px;
    }
    
    .realistec-mono-upload-area {
        border-width: 3px;
    }
    
    .realistec-mono-btn {
        border: 2px solid currentColor;
    }
    
    .realistec-mono-type-card {
        border-width: 3px;
    }
}

/* =============================================
   REDUCED MOTION
   ============================================= */
@media (prefers-reduced-motion: reduce) {
    .realistec-mono-progress-fill::after,
    .realistec-mono-spinner,
    .realistec-mono-upload-status.success .realistec-mono-status-icon,
    .realistec-mono-upload-errors {
        animation: none;
    }
    
    .realistec-mono-upload-area,
    .realistec-mono-image-preview,
    .realistec-mono-upload-progress,
    .realistec-mono-upload-status,
    .realistec-mono-upload-errors,
    .realistec-mono-preview-container img {
        transition: none;
    }
}

/* =============================================
   MOBILE TOUCH
   ============================================= */
@media (hover: none) and (pointer: coarse) {
    .realistec-mono-upload-area {
        padding: 40px 20px;
    }
    
    .realistec-mono-btn {
        min-height: 44px;
        min-width: 44px;
    }
    
    .realistec-mono-btn-small {
        min-height: 40px;
    }
    
    .realistec-mono-type-card {
        padding: 16px;
    }
}

/* =============================================
   PRINT
   ============================================= */
@media print {
    .realistec-mono-upload-interface {
        display: none;
    }
}

/* =============================================================
   DEPTH MAP EDITOR & CROP MODAL
   Version: 1.1.0 — Cross-plugin harmonized with Replicate
   
   These styles power the depth-editor-modal.js overlay.
   Dark-themed by design (depth map editing demands a dark canvas).
   Namespaced under .realistec-mono-modal-* to avoid collisions above.
   ============================================================= */

/* =============================================
   MODAL OVERLAY & CONTAINER
   ============================================= */
.realistec-mono-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 999999;
    background: rgba(0, 0, 0, 0.8);
    backdrop-filter: blur(4px);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow-y: auto;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s ease, visibility 0.3s ease;
}

.realistec-mono-modal-overlay.realistec-mono-modal-open {
    opacity: 1;
    visibility: visible;
}

.realistec-mono-modal {
    /* Realistec brand palette — modal is its own variable scope but
       coupled to the site theme's design tokens (see style.css :root)
       so palette changes propagate here too. Same fallback pattern as
       the plugin scope above: hardcoded values after the comma keep the
       modal functional if --rt-* tokens are ever missing. The few vars
       that stay hardcoded (border, accent-hover, warning, radius) have
       no theme equivalent and are called out with comments. */
    --modal-bg: var(--rt-bg-2, #0d0b1f);                          /* matches footer / surface */
    --modal-surface: var(--rt-bg-3, #14112e);                     /* nested surface inside the modal */
    /* Border stays hardcoded — same reasoning as plugin's
       --realistec-mono-border. Theme's --rt-border is rgba. */
    --modal-border: #1f1b3a;
    --modal-text: var(--rt-text, #f5f3ff);
    --modal-text-secondary: var(--rt-text-muted, #a8a3c9);
    --modal-accent: var(--rt-violet, #8b5cf6);                    /* solid violet for sliders/indicators */
    /* Accent-hover stays hardcoded — no theme equivalent for a solid
       darkened-violet hover state used by the modal's slider/indicator
       components. */
    --modal-accent-hover: #7c4def;
    --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%));
    /* Status palette — matched at the same saturation tier so the
       three states read with equal weight on the dark surface.
       success: emerald-500, warning: amber-500, danger: red-500.
       Foreground states (text/icon) typically use the -400 step of
       each (e.g. #34d399, #fbbf24, #f87171) for legibility against
       the low-alpha tinted washes used as backgrounds. */
    --modal-success: var(--rt-success, #10b981);
    /* Warning stays hardcoded — theme has no warning token (the modal
       is the only place in the plugin that needs amber). */
    --modal-warning: #f59e0b;
    --modal-danger:  var(--rt-error, #ef4444);
    /* Radius stays hardcoded — 12px sits between theme's --rt-radius-sm
       (8px) and --rt-radius (16px); modal needs this specific midpoint
       for its visual weight. */
    --modal-radius: 12px;

    background-color: var(--modal-bg);
    /* Starfield on the modal too — same recipe as the upload interface
       but anchored to its own coordinate space so it doesn't shift when
       the modal opens. */
    background-image:
        radial-gradient(1px 1px at 40px 50px,   rgba(245, 243, 255, 0.20), transparent 50%),
        radial-gradient(1px 1px at 130px 180px, rgba(167, 139, 250, 0.16), transparent 50%),
        radial-gradient(1px 1px at 220px 90px,  rgba(245, 243, 255, 0.12), transparent 50%),
        radial-gradient(1px 1px at 300px 240px, rgba(167, 139, 250, 0.18), transparent 50%),
        radial-gradient(1px 1px at 90px 290px,  rgba(245, 243, 255, 0.10), transparent 50%);
    background-size: 380px 320px;
    background-repeat: repeat;
    border: 1px solid var(--modal-border);
    border-radius: var(--modal-radius);
    width: 95vw;
    max-width: 1200px;
    height: 90vh;
    max-height: 800px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    /* Slightly stronger shadow + a faint violet glow to lift the modal
       off the page and tie it to the brand palette. */
    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;
}

.realistec-mono-modal-open .realistec-mono-modal {
    transform: scale(1) translateY(0);
}

/* =============================================
   MODAL HEADER
   ============================================= */
.realistec-mono-modal-header {
    display: flex;
    align-items: center;
    padding: 14px 20px;
    background: var(--modal-surface);
    border-bottom: 1px solid var(--modal-border);
    flex-shrink: 0;
    gap: 12px;
}

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

.realistec-mono-modal-title {
    font-size: 16px;
    font-weight: 600;
    color: var(--modal-text);
    margin: 0;
    font-family: var(--rt-font-display, 'Space Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
    letter-spacing: -0.01em;
    white-space: nowrap;
}

.realistec-mono-modal-title::before {
    content: none;
}

.realistec-mono-modal-tabs {
    display: flex;
    gap: 4px;
    background: var(--modal-border);
    border-radius: 8px;
    padding: 3px;
    /* Fixed width: sized to fit both tabs so it never reflows when Edit Depth is hidden */
    width: max-content;
    flex-shrink: 0;
}

.realistec-mono-modal-tab {
    /* Fixed equal width — both tabs stay the same size regardless of visibility */
    flex: 0 0 auto;
    min-width: 90px;
    padding: 6px 16px;
    font-size: 13px;
    font-weight: 500;
    color: var(--modal-text-secondary);
    background: transparent;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    transition: all 0.2s ease;
    font-family: inherit;
    white-space: nowrap;
    text-align: center;
}

/* Inactive tab hover/focus/active states.
   We don't want either the plugin's old indigo wash or the theme's
   #9b7ebd background+border bleeding through. Explicitly clear both,
   and bump specificity (two classes) to beat the theme's button:hover. */
.realistec-mono-modal-tabs .realistec-mono-modal-tab:hover:not(:disabled),
.realistec-mono-modal-tabs .realistec-mono-modal-tab:focus:not(:disabled),
.realistec-mono-modal-tabs .realistec-mono-modal-tab:active:not(:disabled) {
    color: var(--modal-text);
    background: transparent;
    border-color: transparent;
    outline: none;
}

.realistec-mono-modal-tab.active {
    color: white;
    background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
    border: none;
}

/* Keep the gradient on the active tab regardless of hover/focus/click.
   The plugin's own .realistec-mono-modal-tab:hover rule above and the theme's
   generic button:hover (which sets background-color: #9b7ebd and
   border-color: #9b7ebd) both stomp on the gradient otherwise. Higher
   specificity (three classes vs one) beats both without needing !important.
   `border: none` here neutralizes any theme border ring on click/focus. */
.realistec-mono-modal-tabs .realistec-mono-modal-tab.active:hover:not(:disabled),
.realistec-mono-modal-tabs .realistec-mono-modal-tab.active:focus,
.realistec-mono-modal-tabs .realistec-mono-modal-tab.active:active {
    color: white;
    background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
    border: none;
    outline: none;
}

.realistec-mono-modal-tab:disabled {
    opacity: 0.35;
    cursor: not-allowed;
}

/* Undo button — standalone in header-actions on desktop.
   On mobile it is repositioned into the tab row via order + flex rules below. */
.realistec-mono-modal-undo-btn {
    /* inherits .realistec-mono-history-btn styles; no overrides needed at base */
}

.realistec-mono-modal-header-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

/* =============================================
   MODAL BUTTONS
   ============================================= */
.realistec-mono-modal-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 7px 16px;
    font-size: 13px;
    font-weight: 500;
    border-radius: 6px;
    border: none;
    cursor: pointer;
    transition: all 0.2s ease;
    font-family: inherit;
}

.realistec-mono-modal-btn-primary {
    /* Signature gradient — used on primary CTAs across the plugin to
       echo the storefront's button treatment. */
    background: var(--modal-gradient);
    color: white;
    /* Subtle violet glow ties the button to the brand and lifts it off
       the dark surface. Strengthened on hover. */
    box-shadow: 0 2px 8px rgba(139, 92, 246, 0.25);
}

.realistec-mono-modal-btn-primary:hover {
    background: var(--modal-gradient-hover);
    box-shadow: 0 4px 14px rgba(139, 92, 246, 0.4);
}

.realistec-mono-modal-btn-secondary {
    background: var(--modal-surface);
    color: var(--modal-text);
    border: 1px solid var(--modal-border);
}

.realistec-mono-modal-btn-secondary:hover {
    background: var(--modal-border);
    /* Without an explicit color, the theme's generic button:hover rule
       sets color:#ffffff, which is unreadable on the gray background.
       Match --modal-text-secondary so the hover stays consistent with
       other secondary text (inactive tabs, etc.) in both color modes. */
    color: var(--modal-text-secondary);
}

.realistec-mono-modal-btn-danger {
    background: rgba(239, 68, 68, 0.15);
    color: #f87171;
    border: 1px solid rgba(239, 68, 68, 0.3);
}

.realistec-mono-modal-btn-danger:hover {
    background: rgba(239, 68, 68, 0.25);
}

.realistec-mono-modal-btn-icon {
    width: 32px;
    height: 32px;
    padding: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--modal-text-secondary);
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s ease;
}

.realistec-mono-modal-btn-icon:hover {
    background: var(--modal-surface);
    color: var(--modal-text);
}

/* Suppress the browser-default focus outline (white in dark mode) that
   flashes on click before the :hover state catches up — same bug class
   as the type-options cards and brush tool buttons. Keyboard users
   still get a brand-aligned violet focus ring via :focus-visible.
   Mobile blue tap highlight is handled by the global reset at the top
   of this file. */
.realistec-mono-modal-btn-icon:focus {
    outline: none;
}

.realistec-mono-modal-btn-icon:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px rgba(139, 92, 246, 0.5);
}

.realistec-mono-modal-close:hover {
    color: var(--modal-danger);
    /* 0.15 alpha matches the histogram modal close button hover so
       both modals' close affordances read identically. */
    background: rgba(239, 68, 68, 0.15);
}

/* When the close button (the variant that uses red on hover) receives
   keyboard focus, use a red focus ring to match the hover treatment
   instead of the generic violet ring. Keeps the visual language
   consistent: red = "this will close/dismiss". */
.realistec-mono-modal-close:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.5);
}

/* =============================================
   MODAL BODY — SPLIT LAYOUT
   ============================================= */
.realistec-mono-modal-body {
    display: flex;
    flex: 1;
    min-height: 0;
    overflow: hidden;
}

/* =============================================
   CANVAS VIEWPORT
   ============================================= */
.realistec-mono-editor-viewport {
    flex: 1;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    position: relative;
}

.realistec-mono-canvas-container {
    flex: 1;
    min-height: 0;
    position: relative;
    overflow: scroll;
    cursor: crosshair;
}

/* Prevent browser gestures when drawing with brush/eraser */
.realistec-mono-tool-brush .realistec-mono-canvas-container,
.realistec-mono-tool-eraser .realistec-mono-canvas-container,
.realistec-mono-tool-eyedropper .realistec-mono-canvas-container {
    touch-action: none;
}

/* Scrollbar gutter: always reserve 16px on both axes so clientWidth/clientHeight
   are identical between Crop and Edit Depth — viewport never resizes on tab toggle.
   overflow:scroll keeps the gutter present; scrollbar-gutter:stable ensures consistent
   layout even when the scrollbar thumb is invisible. */
.realistec-mono-canvas-container::-webkit-scrollbar { width: 16px; height: 16px; }
.realistec-mono-canvas-container::-webkit-scrollbar-track { background: transparent; }
.realistec-mono-canvas-container::-webkit-scrollbar-thumb { background: transparent; border-radius: 8px; }
.realistec-mono-canvas-container::-webkit-scrollbar-corner { background: transparent; }

/* Edit Depth mode — reveal pill-within-track scrollbars for easy touch-and-drag */
.realistec-mono-canvas-container.realistec-mono-tool-brush::-webkit-scrollbar-track,
.realistec-mono-canvas-container.realistec-mono-tool-eraser::-webkit-scrollbar-track,
.realistec-mono-canvas-container.realistec-mono-tool-eyedropper::-webkit-scrollbar-track { background: var(--modal-surface); border-radius: 8px; }
.realistec-mono-canvas-container.realistec-mono-tool-brush::-webkit-scrollbar-thumb,
.realistec-mono-canvas-container.realistec-mono-tool-eraser::-webkit-scrollbar-thumb,
.realistec-mono-canvas-container.realistec-mono-tool-eyedropper::-webkit-scrollbar-thumb { background: var(--modal-border); border-radius: 8px; border: 3px solid var(--modal-surface); }
.realistec-mono-canvas-container.realistec-mono-tool-brush::-webkit-scrollbar-thumb:hover,
.realistec-mono-canvas-container.realistec-mono-tool-eraser::-webkit-scrollbar-thumb:hover,
.realistec-mono-canvas-container.realistec-mono-tool-eyedropper::-webkit-scrollbar-thumb:hover { background: var(--modal-text-secondary); }
.realistec-mono-canvas-container.realistec-mono-tool-brush::-webkit-scrollbar-corner,
.realistec-mono-canvas-container.realistec-mono-tool-eraser::-webkit-scrollbar-corner,
.realistec-mono-canvas-container.realistec-mono-tool-eyedropper::-webkit-scrollbar-corner { background: var(--modal-surface); }

/* Wrapper: centers content when canvas is smaller than viewport,
   grows to natural size when zoomed so scrolling covers the full image.

   v2.4.5 FIX: Previously used justify-content:center + align-items:center
   on this flex container. That causes a well-known CSS bug with overflow:
   when the canvas is LARGER than the container (i.e. zoomed in), flex
   centering pushes the left/top portion of the canvas into NEGATIVE
   overflow space — but overflow:scroll can only scroll into POSITIVE
   space (0 .. scrollWidth). The user could therefore scroll right but
   NOT left, clipping the zoomed image. The fix: remove
   justify-content/align-items centering from the CONTAINER and add
   margin:auto to the child (.realistec-mono-editor-canvas and siblings).
   Auto margins on a flex child produce the same visual centering when
   the child is smaller, but don't push it into negative space when it's
   larger — it starts at 0 and overflows rightward, making the full
   scrollWidth reachable in both directions. */
.realistec-mono-canvas-wrapper {
    position: relative;
    display: flex;
    min-width: 100%;
    min-height: 100%;
    /* Checkerboard — shared by Crop and Edit Depth */
    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;
}

.realistec-mono-editor-canvas {
    position: relative;
    z-index: 1;
    image-rendering: auto;
    border-radius: 4px;
    /* v2.4.5: margin:auto replaces the wrapper's justify-content/align-items
       centering — see the fix note on .realistec-mono-canvas-wrapper above.
       Centers the canvas when smaller than the viewport, stays at 0,0 when
       larger, so overflow scrolls correctly in both directions. */
    margin: auto;
    /* Width and height are set explicitly by JS via canvas.style.width/height.
       Do NOT use max-width/max-height here — they break aspect ratio
       when the canvas is zoomed larger than the container, because
       overflow:hidden clips the overflow while max-width squishes only
       the width dimension. */
}

/* Crop region — positioned absolutely inside the canvas wrapper
   (matches Replicate pattern: crop-box is sibling of canvas) */
.realistec-mono-crop-region {
    position: absolute;
    border: 2px solid #8b5cf6;
    pointer-events: auto;
    cursor: move;
    z-index: 10;
    touch-action: none;       /* prevent browser gestures on crop region */
}

/* Prevent browser scroll/pan when interacting with the canvas area
   in crop mode.  Without this, mobile browsers may scroll the modal
   overlay instead of moving crop handles. */
.realistec-mono-tool-crop .realistec-mono-canvas-wrapper {
    touch-action: none;
}

/* =============================================
   CROP HANDLES — Replicate-aligned (12px, white/red)
   ============================================= */
.realistec-mono-crop-handle {
    position: absolute;
    width: 12px;
    height: 12px;
    background: white;
    border: 2px solid #8b5cf6;
    border-radius: 2px;
    pointer-events: auto;
    z-index: 11;
    touch-action: none;       /* prevent browser gestures on handles */
}

/* =============================================
   RULE-OF-THIRDS GUIDES — Replicate-aligned (white 40%)
   ============================================= */
.realistec-mono-crop-thirds-v1,
.realistec-mono-crop-thirds-v2,
.realistec-mono-crop-thirds-h1,
.realistec-mono-crop-thirds-h2 {
    position: absolute;
    background: rgba(255, 255, 255, 0.4);
    pointer-events: none;
    z-index: 10;
}

.realistec-mono-crop-thirds-v1 {
    left: 33.33%;
    top: 0;
    width: 1px;
    height: 100%;
}

.realistec-mono-crop-thirds-v2 {
    left: 66.66%;
    top: 0;
    width: 1px;
    height: 100%;
}

.realistec-mono-crop-thirds-h1 {
    top: 33.33%;
    left: 0;
    width: 100%;
    height: 1px;
}

.realistec-mono-crop-thirds-h2 {
    top: 66.66%;
    left: 0;
    width: 100%;
    height: 1px;
}

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

.realistec-mono-crop-dimensions {
    position: absolute;
    bottom: -24px;
    left: 50%;
    transform: translateX(-50%);
    background: rgba(0, 0, 0, 0.75);
    color: white;
    font-size: 11px;
    padding: 2px 8px;
    border-radius: 4px;
    white-space: nowrap;
    pointer-events: none;
    z-index: 13;
}

/* =============================================
   VIEWPORT TOOLBAR
   ============================================= */
.realistec-mono-viewport-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 16px;
    background: var(--modal-bg);
    border-top: 1px solid var(--modal-border);
    flex-shrink: 0;
    gap: 12px;
    /* Wrap to a second row if the coord readout grows wide enough that the
       icon group on the left would otherwise be clipped by editor-viewports
       overflow:hidden. Fixes the Invert button vanishing on desktop with
       wide images (long coord strings push it past the right edge). */
    flex-wrap: wrap;
}

.realistec-mono-viewport-toolbar-group {
    display: flex;
    align-items: center;
    gap: 8px;
    /* Keep individual button groups intact when wrapping — only the gap
       between groups should give way, never a single button being cut. */
    flex-shrink: 0;
}

.realistec-mono-toolbar-separator {
    width: 1px;
    height: 18px;
    background: var(--modal-border);
    margin: 0 2px;
    flex-shrink: 0;
}

.realistec-mono-zoom-controls {
    display: flex;
    align-items: center;
    gap: 4px;
}

.realistec-mono-zoom-label {
    font-size: 12px;
    color: var(--modal-text-secondary);
    min-width: 40px;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.realistec-mono-coords-display {
    font-size: 11px;
    color: var(--modal-text-secondary);
    font-variant-numeric: tabular-nums;
    font-family: var(--rt-font-mono, 'SF Mono', 'Fira Code', monospace);
}

/* =============================================
   RIGHT SIDEBAR
   ============================================= */
.realistec-mono-editor-sidebar {
    width: 280px;
    flex-shrink: 0;
    min-height: 0;
    background: var(--modal-bg);
    border-left: 1px solid var(--modal-border);
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    overflow-x: hidden;
}

.realistec-mono-sidebar-section {
    padding: 16px;
    border-bottom: 1px solid var(--modal-border);
}

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

.realistec-mono-sidebar-section-title {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--modal-text-secondary);
    margin: 0 0 12px 0;
    font-family: inherit;
}

/* =============================================
   SLIDERS — 16px thumb (Replicate-aligned)
   ============================================= */
.realistec-mono-slider-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
}

.realistec-mono-slider-row:last-child {
    margin-bottom: 0;
}

.realistec-mono-slider-label {
    font-size: 12px;
    color: var(--modal-text);
    /* Wide enough to hold "Hardness" plus an inline 14px icon + 4px margin
       without forcing icon-less labels (Size, Hardness) to render at a
       different effective width than icon-bearing ones (Opacity, Strength).
       Keeps every slider row aligned to the same start column. */
    min-width: 73px;
    font-weight: 500;
}

.realistec-mono-slider-input {
    flex: 1;
    -webkit-appearance: none;
    appearance: none;
    height: 4px;
    background: var(--modal-surface);
    border-radius: 2px;
    outline: none;
    cursor: pointer;
}

.realistec-mono-slider-input::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    background: var(--modal-accent);
    border-radius: 50%;
    cursor: pointer;
    border: 2px solid white;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
    transition: transform 0.1s ease;
}

.realistec-mono-slider-input::-webkit-slider-thumb:hover {
    transform: scale(1.15);
}

.realistec-mono-slider-input::-moz-range-thumb {
    width: 16px;
    height: 16px;
    background: var(--modal-accent);
    border-radius: 50%;
    cursor: pointer;
    border: 2px solid white;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
}

.realistec-mono-slider-input:disabled {
    cursor: not-allowed;
    opacity: 0.45;
}

.realistec-mono-slider-input:disabled::-webkit-slider-thumb {
    cursor: not-allowed;
}

.realistec-mono-slider-input:disabled::-moz-range-thumb {
    cursor: not-allowed;
}

.realistec-mono-slider-value {
    font-size: 12px;
    color: var(--modal-text-secondary);
    /* Two layout properties working together:
       1. min-width: 40px reserves enough horizontal space that the
          slider track doesn't visibly contract as the user drags from
          single-digit values up to 100%/200px (stability).
       2. flex-shrink: 0 prevents the flex container from compressing
          this element below its content width — without it, the
          slider input's `flex: 1` greedily takes space and squeezes
          the value box down to exactly 40px, which truncates "200px"
          to "200p" and "100%" to "100" because the content overflows
          the 40px box (confirmed via DevTools box model inspection).
       white-space: nowrap is also necessary; min-width alone is not
       a guarantee against wrapping when the parent is text-wrappable. */
    min-width: 40px;
    flex-shrink: 0;
    white-space: nowrap;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* =============================================
   BRUSH ENGINE CONTROLS
   ============================================= */
.realistec-mono-brush-tools {
    display: flex;
    gap: 4px;
    margin-bottom: 12px;
    flex-wrap: wrap;
}

.realistec-mono-brush-tool-btn {
    flex: 1;
    min-width: 0;
    padding: 8px 4px;
    background: var(--modal-surface);
    border: 1px solid var(--modal-border);
    border-radius: 8px;
    color: var(--modal-text-secondary);
    cursor: pointer;
    transition: all 0.2s ease;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    font-size: 10px;
    font-weight: 500;
    font-family: inherit;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    /* outline:none on :focus removes the default focus outline (white
       in dark mode, blue in light mode), which was producing a brief
       white flash on click before the :active/.active state caught
       up — same bug class as the type-options cards we fixed earlier.
       The mobile blue tap-highlight is handled by a global reset at
       the top of this file. */
}

.realistec-mono-brush-tool-btn:hover {
    border-color: var(--modal-accent);
    color: var(--modal-text);
}

/* Focus indicator — implemented as box-shadow rather than outline so it
   animates with the button's transition and matches the .active state's
   visual language (also a violet ring). Without this rule, the browser
   draws its default focus outline on click which flashes white before
   the .active class is applied via JS. */
.realistec-mono-brush-tool-btn:focus {
    outline: none;
}

.realistec-mono-brush-tool-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.25);
}

.realistec-mono-brush-tool-btn.active {
    background: rgba(139, 92, 246, 0.15);
    border-color: var(--modal-accent);
    color: var(--modal-accent);
}

/* When a button 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 active selection. */
.realistec-mono-brush-tool-btn.active:focus-visible {
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.35);
}

.realistec-mono-brush-tool-btn svg {
    width: 18px;
    height: 18px;
}

/* Material Symbols icon span — base sizing for inline use in the toolbar.
   The .material-symbols-outlined class (set on the same element) brings
   the font-family from Googles served CSS; this rule sets size, alignment,
   and color so the icon matches the surrounding 14x14 SVGs it replaced.
   .realistec-mono-msi is plugin-scoped so we can target it without
   affecting other Material Symbols elsewhere on the page. */
.realistec-mono-msi {
    font-size: 18px;
    line-height: 1;
    color: inherit;
    vertical-align: middle;
    /* Center the glyph inside the buttons icon slot — Material Symbols
       glyphs vary in optical size, so vertical-align:middle alone can leave
       a tiny baseline offset relative to the adjacent text labels. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Material Symbols ligatures are CASE-SENSITIVE: the font maps the
       lowercase string "brush" to the brush glyph, but "BRUSH" doesnt
       match any substitution rule and renders as plain text. The parent
       .realistec-mono-brush-tool-btn applies text-transform:uppercase to
       its label, which would otherwise reach the ligature span and break
       icon rendering. Reset both transform and letter-spacing here, and
       force the liga feature on for older browsers that ignore it by
       default. */
    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 ("brush", "undo")
       would otherwise show as fallback text. word-wrap:normal and the
       `display=block` query parameter on the font URL together blank
       the text until the font arrives. */
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
}

/* Toolbar icons (Undo, Rotate, Invert, etc.) used to be 14x14 SVGs —
   match that footprint so the buttons height doesnt shift. */
.realistec-mono-modal-btn-icon .realistec-mono-msi,
.realistec-mono-modal-undo-btn .realistec-mono-msi {
    font-size: 16px;
}

/* Icon buttons that also contain a text label (Rotate 180°, Invert) need
   to grow beyond the default 32px square — the icon plus label otherwise
   gets clipped. Override the fixed width on just these two. */
#ide-rotate-180,
#ide-invert-depth {
    width: auto;
    padding: 0 10px;
    gap: 4px;
}

/* Upload-section icons (2D Image, 2D Image with Depth, Upload depth map)
   used to be 48x48 SVGs (32x32 for the type-selector cards) — set the
   default upload-icon size to 48px to match the original visual weight,
   and override down to 32px for the smaller type-selector context. */
.realistec-mono-upload-icon .realistec-mono-msi {
    font-size: 48px;
}

.realistec-mono-type-icon .realistec-mono-msi {
    font-size: 32px;
}

/* Inline icons paired with a label/text in the sidebar (Opacity, Strength,
   Aspect Ratio). The default 18px MSI is too dominant next to 12-13px text;
   match the icon to the surrounding font size and add a small right-gap so
   the glyph doesnt collide with the label text. */
.realistec-mono-slider-label .realistec-mono-msi,
.realistec-mono-crop-control-group label .realistec-mono-msi {
    font-size: 14px;
    margin-right: 4px;
    vertical-align: -2px; /* nudge down a hair so the optical center matches the texts x-height */
}

.realistec-mono-brush-preview {
    width: 120px;
    height: 120px;
    border-radius: 50%;
    background: var(--modal-surface);
    margin: 8px auto;
    position: relative;
    overflow: hidden;
    border: 1px solid var(--modal-border);
}

.realistec-mono-brush-preview-dot {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: white;
}

/* =============================================
   DEPTH VALUE PICKER
   ============================================= */
.realistec-mono-depth-value-picker {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
}

.realistec-mono-depth-swatch {
    width: 36px;
    height: 36px;
    border-radius: 8px;
    border: 2px solid var(--modal-border);
    cursor: pointer;
    position: relative;
    overflow: hidden;
    flex-shrink: 0;
}

.realistec-mono-depth-swatch-inner {
    width: 100%;
    height: 100%;
    background: rgb(128, 128, 128);
}

.realistec-mono-depth-value-info { flex: 1; }

.realistec-mono-depth-value-label {
    font-size: 11px;
    color: var(--modal-text-secondary);
    margin-bottom: 2px;
}

.realistec-mono-depth-value-number {
    font-size: 14px;
    font-weight: 600;
    color: var(--modal-text);
    font-variant-numeric: tabular-nums;
    font-family: var(--rt-font-mono, 'SF Mono', 'Fira Code', monospace);
}

.realistec-mono-depth-gradient-bar {
    width: 100%;
    height: 20px;
    border-radius: 6px;
    background: linear-gradient(to right, #000 0%, #fff 100%);
    cursor: pointer;
    position: relative;
    border: 1px solid var(--modal-border);
    margin-bottom: 8px;
}

.realistec-mono-depth-gradient-indicator {
    position: absolute;
    top: -3px;
    width: 4px;
    height: 26px;
    background: var(--modal-accent);
    border-radius: 2px;
    transform: translateX(-50%);
    pointer-events: none;
    box-shadow: 0 0 4px rgba(139, 92, 246, 0.5);
}

/* =============================================
   CROP SIDEBAR CONTROLS
   ============================================= */
.realistec-mono-crop-inputs {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    margin-bottom: 12px;
}

.realistec-mono-crop-input-group {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.realistec-mono-crop-input-label {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--modal-text-secondary);
}

.realistec-mono-crop-input {
    background: var(--modal-surface);
    border: 1px solid var(--modal-border);
    border-radius: 6px;
    padding: 6px 8px;
    font-size: 12px;
    color: var(--modal-text);
    font-family: var(--rt-font-mono, 'SF Mono', 'Fira Code', monospace);
    width: 100%;
    box-sizing: border-box;
    transition: border-color 0.2s ease;
}

.realistec-mono-crop-input:focus {
    outline: none;
    border-color: var(--modal-accent);
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.15);
}

/* =============================================
   CROP ASPECT RATIO DROPDOWN (Replicate-aligned)
   ============================================= */
.realistec-mono-crop-control-group {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
}

.realistec-mono-crop-control-group label {
    font-size: 12px;
    font-weight: 500;
    color: var(--modal-text);
    white-space: nowrap;
}

.realistec-mono-crop-control-group select {
    flex: 1;
    min-width: 0;
    max-width: 100%;
    background: var(--modal-surface);
    border: 1px solid var(--modal-border);
    border-radius: 6px;
    padding: 6px 8px;
    font-size: 12px;
    color: var(--modal-text);
    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;
}

.realistec-mono-crop-control-group select:focus {
    outline: none;
    border-color: var(--modal-accent);
    /* Brand violet ring — matches the focus treatment used elsewhere in
       the plugin. Prior value (rgba(99,102,241,…)) was the old indigo. */
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.20);
}

/* 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. */
.realistec-mono-crop-control-group select option {
    background-color: #14112b;
    color: #f5f3ff;
}

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

/* =============================================
   UNDO/REDO
   ============================================= */
.realistec-mono-history-bar {
    display: flex;
    align-items: center;
    gap: 4px;
}

.realistec-mono-history-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 7px 16px;
    font-size: 13px;
    font-weight: 500;
    border-radius: 6px;
    background: var(--modal-surface);
    border: 1px solid var(--modal-border);
    color: var(--modal-text-secondary);
    cursor: pointer;
    transition: all 0.2s ease;
    font-family: inherit;
}

.realistec-mono-history-btn:hover:not(:disabled) {
    border-color: var(--modal-accent);
    color: var(--modal-text);
    background: var(--modal-border);
}

.realistec-mono-history-btn:disabled {
    opacity: 0.3;
    cursor: not-allowed;
}

.realistec-mono-history-count {
    font-size: 11px;
    color: var(--modal-text-secondary);
    margin-left: 4px;
}

/* =============================================
   LAYER VISIBILITY
   ============================================= */
.realistec-mono-layer-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 12px;
    background: var(--modal-surface);
    border-radius: 8px;
    margin-bottom: 6px;
    cursor: pointer;
    transition: background 0.2s ease;
}

.realistec-mono-layer-toggle:hover { background: var(--modal-border); }
.realistec-mono-layer-toggle:last-child { margin-bottom: 0; }

.realistec-mono-layer-toggle-info {
    display: flex;
    align-items: center;
    gap: 8px;
}

.realistec-mono-layer-color-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
}

.realistec-mono-layer-name {
    font-size: 12px;
    color: var(--modal-text);
    font-weight: 500;
}

.realistec-mono-layer-eye {
    color: var(--modal-text-secondary);
    transition: color 0.2s ease;
}

.realistec-mono-layer-eye.hidden {
    color: var(--modal-border);
}

/* =============================================
   BRUSH CURSOR
   ============================================= */
.realistec-mono-brush-cursor {
    position: absolute;
    border: 1.5px solid rgba(255, 255, 255, 0.8);
    border-radius: 50%;
    pointer-events: none;
    z-index: 20;
    mix-blend-mode: difference;
    transform: translate(-50%, -50%);
    display: none;
}

.realistec-mono-editor-viewport.realistec-mono-tool-brush .realistec-mono-brush-cursor,
.realistec-mono-editor-viewport.realistec-mono-tool-eraser .realistec-mono-brush-cursor {
    display: block;
}

.realistec-mono-canvas-container.realistec-mono-tool-brush,
.realistec-mono-canvas-container.realistec-mono-tool-eraser { cursor: none; }

.realistec-mono-canvas-container.realistec-mono-tool-eyedropper,
.realistec-mono-canvas-container.realistec-mono-tool-crop { cursor: crosshair; }

/* =============================================
   MODAL FOOTER
   ============================================= */
.realistec-mono-modal-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 20px;
    border-top: 1px solid var(--modal-border);
    flex-shrink: 0;
    background: var(--modal-bg);
}

.realistec-mono-modal-footer-info {
    font-size: 12px;
    color: var(--modal-text-secondary);
}

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

/* =============================================
   KEYBOARD SHORTCUT HINTS
   ============================================= */
.realistec-mono-shortcut-hint {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 4px;
    background: var(--modal-border);
    border-radius: 3px;
    font-size: 10px;
    font-weight: 600;
    color: var(--modal-text-secondary);
    margin-left: 6px;
    font-family: var(--rt-font-mono, 'SF Mono', 'Fira Code', monospace);
}

/* =============================================
   CROP OPTION CHECKBOX
   Matches Replicate: .custom-crop-option / .stereo-crop-option
   ============================================= */
.realistec-mono-crop-option {
    margin: 20px 0;
    padding: 16px;
    background: var(--realistec-mono-surface);
    border: 2px solid var(--realistec-mono-border);
    border-radius: 12px;
    transition: all 0.2s ease;
}

.realistec-mono-crop-option:hover {
    border-color: var(--realistec-mono-primary);
}

.realistec-mono-crop-option.enabled {
    border-color: var(--realistec-mono-primary);
    background: rgba(139, 92, 246, 0.05);
}

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

.realistec-mono-crop-checkbox-label input[type="checkbox"] {
    width: 18px;
    height: 18px;
    cursor: pointer;
    /* Reference --rt-violet (defined on :root in style.css) directly
       rather than --realistec-mono-primary, because this selector also
       matches the "Auto Increase" checkbox inside the photo editor
       modal, which is appended to <body> outside the
       .realistec-mono-upload-interface scope where --realistec-mono-*
       variables are defined. Theme tokens on :root are in scope
       everywhere on the page, so using --rt-violet directly is the
       most reliable way to hit both the upload-interface checkbox
       (which is inside the plugin scope) and the modal checkbox
       (which is not). Without this, the modal checkbox falls back to
       the OS-default blue accent. */
    accent-color: var(--rt-violet, #8b5cf6);
}

.realistec-mono-crop-checkbox-label.is-disabled {
    cursor: not-allowed;
    opacity: 0.45;
}

.realistec-mono-crop-checkbox-label input[type="checkbox"]:disabled {
    cursor: not-allowed;
}

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

/* Indicator badge (injected by JS after crop apply) */
.realistec-mono-crop-indicator {
    display: inline-block;
    margin: 10px 0 0 28px;
    padding: 4px 10px;
    /* Signature gradient — was an off-brand #4f46e5→#7c3aed purple. */
    background: linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%);
    color: white;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 500;
}

/* Edit button (injected by JS after crop apply).
   The dark-theme block above also targets this selector; the override
   wins in the cascade, but we keep this rule on-brand as the canonical
   default in case the override is ever removed. */
.realistec-mono-edit-crop-btn {
    margin-left: 8px;
    padding: 4px 12px;
    background: var(--realistec-mono-surface-2);
    color: var(--realistec-mono-text);
    border: 1px solid var(--realistec-mono-border);
    border-radius: 4px;
    font-size: 12px;
    cursor: pointer;
    transition: background 0.2s, border-color 0.2s;
}

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

/* =============================================
   EDITOR ACTION BUTTONS (in upload interface)
   ============================================= */
.realistec-mono-editor-actions {
    margin-top: 12px;
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.realistec-mono-editor-actions .realistec-mono-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.realistec-mono-editor-actions .realistec-mono-btn svg {
    flex-shrink: 0;
}

/* =============================================
   DEPTH EDITOR — RESPONSIVE OVERRIDES
   (Appended to existing @media blocks)
   ============================================= */
@media (max-width: 900px) {
    /* Overlay scrolls — exactly like Replicate */
    .realistec-mono-modal-overlay {
        align-items: flex-start;
        padding: 10px;
    }

    .realistec-mono-modal {
        width: 100%;
        height: auto;
        max-width: none;
        max-height: none;
        border-radius: 8px;
        margin: 10px auto;
        overflow: visible;
    }

    .realistec-mono-modal-body {
        flex-direction: column;
        overflow: visible;
    }

    /* Viewport gets a fixed height */
    .realistec-mono-editor-viewport {
        flex: none;
        height: 50vh;
        overflow: hidden;
    }

    /* Sidebar flows below viewport at its natural height */
    .realistec-mono-editor-sidebar {
        width: 100%;
        height: auto;
        flex: none;
        min-height: 0;
        border-left: none;
        border-top: 1px solid var(--modal-border);
        flex-direction: column;
        flex-wrap: nowrap;
        overflow-y: visible;
    }

    .realistec-mono-sidebar-section {
        flex: none;
        min-width: 100%;
        border-bottom: 1px solid var(--modal-border);
        border-right: none;
    }
}

@media (max-width: 600px) {
    /* Header layout on mobile — two rows:
       Row 1: title  (full-width forces its own line)
       Row 2: [tab strip, flex:1]  [undo]  — close is position:absolute top-right

       header-left uses display:contents so its children (title, tabs) join the
       header's flex context directly alongside header-actions.                 */

    .realistec-mono-modal-header {
        flex-wrap: wrap;
        align-items: center;
        gap: 8px;
        padding: 12px 16px;
        position: relative;   /* anchor for the absolutely-positioned close button */
    }

    /* Dissolve header-left into the header's flex context */
    .realistec-mono-modal-header-left {
        display: contents;
    }

    /* Title: full-width forces its own row */
    .realistec-mono-modal-title {
        width: 100%;
        padding-right: 36px;  /* prevent text running under the close button */
        white-space: normal;
        box-sizing: border-box;
    }

    /* Tab strip: fixed natural width, never stretches or shrinks —
       the undo button appearing/disappearing beside it has no effect */
    .realistec-mono-modal-tabs {
        flex-shrink: 0;
        width: max-content;
    }

    /* Tabs: fixed equal pixel width so both tabs are always identical
       regardless of what else is visible in the header row */
    .realistec-mono-modal-tab {
        flex: 0 0 auto;
        width: 86px;
        min-width: 0;
        text-align: center;
        padding: 6px 8px;
    }

    /* header-actions: static flow on row 2 beside the tab strip,
       but the close button inside it is pulled to the corner (see below).
       margin-left:auto right-justifies the undo button to the far end of the row. */
    .realistec-mono-modal-header-actions {
        position: static;
        flex-shrink: 0;
        gap: 6px;
        margin-left: auto;
    }

    /* Close button: absolutely positioned in the top-right corner */
    .realistec-mono-modal-close {
        position: absolute;
        top: 12px;
        right: 16px;
    }

    /* Undo button: stays in normal flow on row 2, hidden via JS when Crop active */
    .realistec-mono-modal-undo-btn {
        padding: 6px 12px;
        font-size: 13px;
        align-self: stretch;
    }

    /* Crop option: description loses left indent on mobile */
    .realistec-mono-crop-description {\n        margin-left: 0;\n        margin-top: 10px;\n    }\n\n    .realistec-mono-crop-indicator {\n        margin-left: 0;\n        display: block;\n        margin-top: 10px;\n    }\n\n    .realistec-mono-edit-crop-btn {\n        margin-left: 0;\n        margin-top: 6px;\n    }\n\n    .realistec-mono-cf-indicator {\n        margin-left: 0;\n        display: block;\n        margin-top: 10px;\n    }\n\n    .realistec-mono-cf-edit-btn {\n        margin-left: 0;\n        margin-top: 6px;\n    }\n}

@media (max-width: 480px) {
    .realistec-mono-crop-handle {
        width: 16px;
        height: 16px;
    }

    .realistec-mono-crop-handle-nw { top: -8px; left: -8px; }
    .realistec-mono-crop-handle-ne { top: -8px; right: -8px; }
    .realistec-mono-crop-handle-sw { bottom: -8px; left: -8px; }
    .realistec-mono-crop-handle-se { bottom: -8px; right: -8px; }
    .realistec-mono-crop-handle-n  { top: -8px; }
    .realistec-mono-crop-handle-s  { bottom: -8px; }
    .realistec-mono-crop-handle-w  { left: -8px; }
    .realistec-mono-crop-handle-e  { right: -8px; }
}

/* Extend existing reduced-motion to cover modal */
@media (prefers-reduced-motion: reduce) {
    .realistec-mono-modal-overlay,
    .realistec-mono-modal {
        transition: none;
    }
}

/* Extend existing touch targets to cover modal */
@media (hover: none) and (pointer: coarse) {
    .realistec-mono-modal-btn {
        min-height: 44px;
        min-width: 44px;
    }

    .realistec-mono-modal-btn-icon {
        width: 44px;
        height: 44px;
    }

    .realistec-mono-modal-tab {
        padding: 10px 8px;
    }

    .realistec-mono-modal-undo-btn {
        min-height: 44px;
        padding: 10px 12px;
    }

    .realistec-mono-brush-tool-btn {
        padding: 12px 4px;
    }
}

/* =============================================
   SIDEBAR SCROLLBAR
   ============================================= */
.realistec-mono-editor-sidebar::-webkit-scrollbar { width: 6px; }
.realistec-mono-editor-sidebar::-webkit-scrollbar-track { background: transparent; }
.realistec-mono-editor-sidebar::-webkit-scrollbar-thumb { background: var(--modal-border); border-radius: 3px; }
.realistec-mono-editor-sidebar::-webkit-scrollbar-thumb:hover { background: var(--modal-text-secondary); }

/* =============================================
   APPLY COLOR FILTER OPTION
   ============================================= */

.realistec-mono-color-filter-option {
    margin: 20px 0;
    padding: 16px;
    background: var(--realistec-mono-surface);
    border: 2px solid var(--realistec-mono-border);
    border-radius: 12px;
    transition: all 0.2s ease;
}

.realistec-mono-color-filter-option:hover {
    border-color: var(--realistec-mono-primary);
}

.realistec-mono-color-filter-option.enabled {
    border-color: var(--realistec-mono-primary);
    /* Match the violet wash used on other enabled card states
       (.realistec-mono-crop-option.enabled, selected type-card). */
    background: rgba(139, 92, 246, 0.10);
}

/* Indicator badge injected by JS after filter is applied */
.realistec-mono-cf-indicator {
    display: inline-block;
    margin: 10px 0 0 28px;
    padding: 4px 10px;
    /* Signature gradient — was an off-brand #4f46e5→#7c3aed purple. */
    background: linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%);
    color: white;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 500;
}

.realistec-mono-cf-edit-btn {
    display: inline-flex;
    align-items: center;
    margin: 0 0 0 8px;
    padding: 4px 12px;
    /* Small inline action — stays solid (not a major CTA), but uses
       a brand-aligned surface instead of the previous neutral gray. */
    background: var(--realistec-mono-surface-2);
    color: var(--realistec-mono-text);
    border: 1px solid var(--realistec-mono-border);
    border-radius: 4px;
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.2s ease, border-color 0.2s ease;
}

.realistec-mono-cf-edit-btn:hover {
    background: #1f1b3a;
    border-color: var(--realistec-mono-primary);
}

/* =============================================
   COLOR FILTER MODAL
   All hist-* rules are scoped under
   #realistec-mono-color-filter-modal so they
   work without Replicate's stylesheet.
   ============================================= */

#realistec-mono-color-filter-modal {
    /* Brand vars defined locally on the modal itself.
       The histogram modal lives in <body>, OUTSIDE the
       .realistec-mono-upload-interface element where these vars are
       declared — so without this block, every var(--realistec-mono-*)
       reference inside the modal falls through to its initial value
       (transparent / unset). That's why the shell, header, sidebar,
       and selects all read incorrectly when the modal is portaled.

       Coupled to the theme's --rt-* tokens (defined on :root in
       style.css) with hardcoded fallbacks so the modal stays in sync
       with site palette changes. Same pattern as the upload-interface
       and modal-* variable scopes elsewhere in this file. */
    --realistec-mono-primary: var(--rt-violet, #8b5cf6);
    --realistec-mono-primary-hover: var(--rt-indigo, #6366f1);
    --realistec-mono-link: var(--rt-violet-bright, #a78bfa);
    --realistec-mono-bg: var(--rt-bg, #07060f);
    --realistec-mono-surface: var(--rt-bg-2, #0d0b1f);
    --realistec-mono-surface-2: var(--rt-bg-3, #14112e);
    /* Border stays hardcoded — theme's --rt-border is rgba; modal
       needs the solid violet-tinted color used for 1px panel borders. */
    --realistec-mono-border: #1f1b3a;
    --realistec-mono-text: var(--rt-text, #f5f3ff);
    --realistec-mono-text-secondary: var(--rt-text-muted, #a8a3c9);

    display: none;
    position: fixed;
    top: 0; left: 0;
    width: 100%; height: 100%;
    /* Slightly stronger backdrop than 0.8 so when this modal is opened
       on top of the Crop modal, the underlying modal's content is fully
       obscured rather than ghosting through. */
    background: rgba(0, 0, 0, 0.88);
    z-index: 999999;
    overflow-y: auto;
    padding: 20px;
    box-sizing: border-box;
    opacity: 0;
    transition: opacity 0.3s ease;
}

#realistec-mono-color-filter-modal.active {
    display: flex;
    justify-content: center;
    align-items: center;
    opacity: 1;
}

/* Modal content shell */
#realistec-mono-color-filter-modal .hist-modal-content {
    background: var(--realistec-mono-bg);
    border: 1px solid var(--realistec-mono-border);
    border-radius: 12px;
    width: 95vw;
    max-width: 900px;
    height: 90vh;
    max-height: 720px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    /* Stronger shadow + faint violet glow — matches the editor modal. */
    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-mono-color-filter-modal.active .hist-modal-content {
    transform: scale(1) translateY(0);
}

/* Header — sized and styled to match the crop modal header so both
   modals share one header rhythm. The histogram modal has <h3> + close
   button as direct children (no header-left wrapper), so we keep
   space-between to push the button to the right edge instead of
   relying on flex:1 like the crop header does. */
#realistec-mono-color-filter-modal .hist-modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 14px 20px;
    gap: 12px;
    background: var(--realistec-mono-surface);
    border-bottom: 1px solid var(--realistec-mono-border);
    flex-shrink: 0;
}

#realistec-mono-color-filter-modal .hist-modal-header h3 {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
    color: var(--realistec-mono-text);
    /* Display font on the modal heading to match the editor modal title.
       Coupled to --rt-font-display via theme token. */
    font-family: var(--rt-font-display, 'Space Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
    letter-spacing: -0.01em;
    white-space: nowrap;
}

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

#realistec-mono-color-filter-modal .hist-close-btn:hover {
    color: var(--rt-error, #ef4444);
    background: rgba(239, 68, 68, 0.15);
}

/* Same focus treatment as .realistec-mono-modal-close — red ring on
   keyboard focus to match the hover language. Suppresses the browser-
   default white focus outline that otherwise flashes on click. */
#realistec-mono-color-filter-modal .hist-close-btn:focus {
    outline: none;
}

#realistec-mono-color-filter-modal .hist-close-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.5);
}

/* Body: sidebar left, main right — horizontal flex row */
#realistec-mono-color-filter-modal .hist-modal-body {
    display: flex;
    flex-direction: row;
    flex: 1;
    min-height: 0;
    overflow: hidden;
}

/* Sidebar on the RIGHT — matches Replicate's hist-sidebar exactly */
#realistec-mono-color-filter-modal .hist-sidebar {
    width: 200px;
    flex-shrink: 0;
    background: var(--realistec-mono-surface);
    border-left: 1px solid var(--realistec-mono-border);
    border-right: none;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    overflow-x: hidden;
    order: 1;
}

#realistec-mono-color-filter-modal .hist-sidebar::-webkit-scrollbar { width: 6px; }
#realistec-mono-color-filter-modal .hist-sidebar::-webkit-scrollbar-track { background: transparent; }
#realistec-mono-color-filter-modal .hist-sidebar::-webkit-scrollbar-thumb { background: var(--realistec-mono-border); border-radius: 3px; }
#realistec-mono-color-filter-modal .hist-sidebar::-webkit-scrollbar-thumb:hover { background: var(--realistec-mono-text-secondary); }

#realistec-mono-color-filter-modal .hist-sidebar-section {
    padding: 16px;
    border-bottom: 1px solid var(--realistec-mono-border);
}

#realistec-mono-color-filter-modal .hist-sidebar-section:last-child {
    border-bottom: none;
}

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

#realistec-mono-color-filter-modal .hist-sidebar-control-label {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--realistec-mono-text-secondary);
    margin: 0 0 12px 0;
    display: block;
}

#realistec-mono-color-filter-modal .hist-sidebar-control-group {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
}

/* Histogram channel + color filter selects — styled to mirror the
   Aspect Ratio dropdown in the crop modal so both modals feel like
   one consistent design system. */
#realistec-mono-color-filter-modal .hist-sidebar-control-group select {
    flex: 1;
    min-width: 0;
    max-width: 100%;
    width: 100%;
    background: var(--realistec-mono-surface-2);
    border: 1px solid var(--realistec-mono-border);
    border-radius: 6px;
    padding: 6px 8px;
    font-size: 12px;
    color: var(--realistec-mono-text);
    font-family: inherit;
    cursor: pointer;
    transition: border-color 0.2s ease;
    appearance: auto;
    text-overflow: ellipsis;
    /* See note on .realistec-mono-crop-control-group select for what
       these two do — same treatment so both modals' option popups
       render dark with brand-violet highlights. */
    accent-color: var(--rt-violet, #8b5cf6);
    color-scheme: dark;
}

#realistec-mono-color-filter-modal .hist-sidebar-control-group select:focus {
    outline: none;
    border-color: var(--realistec-mono-primary);
    /* Brand-violet focus ring (matches Aspect Ratio dropdown). */
    box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.20);
}

/* Option list theming — see equivalent rule on the crop modal selects. */
#realistec-mono-color-filter-modal .hist-sidebar-control-group select option {
    background-color: var(--realistec-mono-surface-2);
    color: var(--realistec-mono-text);
}

#realistec-mono-color-filter-modal .hist-sidebar-control-group select option:checked,
#realistec-mono-color-filter-modal .hist-sidebar-control-group select option:hover {
    /* Highlight stays hardcoded — #2a1f5a is a deeper violet wash with
       no theme equivalent, used specifically for OS-rendered option
       list selection and hover states inside dark-mode <select> popups. */
    background-color: #2a1f5a;
    color: var(--realistec-mono-text);
}

#realistec-mono-color-filter-modal .hist-filter-strength-group {
    width: 100%;
}

#realistec-mono-color-filter-modal .hist-filter-strength-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 8px;
    width: 100%;
}

#realistec-mono-color-filter-modal .hist-filter-strength-row input[type="range"] {
    flex: 1;
    min-width: 0;
    height: 6px;
    -webkit-appearance: none;
    appearance: none;
    /* Brand gradient on the filled portion; dark surface-2-derived
       track for the unfilled portion. The two-stop pattern at
       --range-pct lets JS show progress without a separate fill div. */
    background: linear-gradient(
        to right,
        var(--realistec-mono-primary) 0%,
        var(--realistec-mono-primary-hover) var(--range-pct, 100%),
        rgba(139, 92, 246, 0.15) var(--range-pct, 100%),
        rgba(139, 92, 246, 0.15) 100%
    );
    border-radius: 4px;
    outline: none;
    cursor: pointer;
    margin: 0;
}

#realistec-mono-color-filter-modal .hist-filter-strength-row input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--rt-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    cursor: pointer;
    /* Dark border so the thumb reads against either the filled or
       unfilled portion of the track. */
    border: 2px solid var(--realistec-mono-bg);
    box-shadow: 0 2px 6px rgba(139, 92, 246, 0.5), 0 1px 3px rgba(0, 0, 0, 0.4);
}

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

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

/* Main content: histogram on top, image preview below */
#realistec-mono-color-filter-modal .hist-main {
    flex: 1;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: 24px;
    overflow-y: auto;
}

/* Histogram container — no compare slider, cursor default */
#realistec-mono-color-filter-modal .rmcf-histogram-container {
    position: relative;
    /* Neutral near-black (#1a1a1a) stays hardcoded — no theme equivalent.
       The histogram canvas needs a flat neutral gray to maximize contrast
       against the violet/orange tone curves; the theme's --rt-bg
       (#07060f) is too dark and the surface tokens have a violet tint
       that would bleed into the data visualization. */
    background: #1a1a1a;
    border-radius: 8px;
    overflow: hidden;
    cursor: default;
    user-select: none;
    -webkit-user-select: none;
    flex: 0 0 140px;
    min-height: 140px;
    margin-bottom: 20px;
}

#realistec-mono-color-filter-modal .rmcf-histogram-container canvas {
    display: block;
    width: 100%;
    height: 100%;
}

/* Tone labels inside histogram */
#realistec-mono-color-filter-modal .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-mono-color-filter-modal .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-mono-color-filter-modal .hist-tone-label:first-child { text-align: left;  padding-left:  10px; }
#realistec-mono-color-filter-modal .hist-tone-label:last-child  { text-align: right; padding-right: 10px; }

/* Loading overlay */
#realistec-mono-color-filter-modal .hist-loading-overlay {
    display: none;
    position: absolute;
    inset: 0;
    /* Darker overlay so the spinner reads against it on the dark modal. */
    background: rgba(7, 6, 15, 0.65);
    z-index: 9999;
    align-items: center;
    justify-content: center;
    border-radius: 12px;
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
}

#realistec-mono-color-filter-modal .hist-spinner {
    width: 44px;
    height: 44px;
    /* Brand violet (was off-brand #667eea). */
    border: 4px solid rgba(139, 92, 246, 0.25);
    border-top-color: var(--realistec-mono-primary);
    border-radius: 50%;
    animation: hist-spin 0.75s linear infinite;
    box-shadow: 0 2px 12px rgba(139, 92, 246, 0.4);
}

/* Single image preview */
.rmcf-image-preview-wrap {
    flex: 1;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--realistec-mono-surface-2);
    border: 2px solid var(--realistec-mono-border);
    border-radius: 8px;
    overflow: hidden;
    padding: 8px;
}

.rmcf-image-preview-wrap img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: 4px;
    display: block;
}

/* Footer */
#realistec-mono-color-filter-modal .hist-modal-footer {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding: 12px 20px;
    background: var(--realistec-mono-surface);
    border-top: 1px solid var(--realistec-mono-border);
    flex-shrink: 0;
}

#realistec-mono-color-filter-modal .hist-modal-footer-actions {
    display: flex;
    gap: 10px;
}

#realistec-mono-color-filter-modal .hist-btn-primary {
    padding: 8px 20px;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s;
    border: none;
    font-family: inherit;
    /* Signature gradient — references --rt-gradient (theme :root token)
       directly because the Effects Editor modal is portaled to <body>
       and is NOT inside the .realistec-mono-modal scope where the
       --modal-gradient variable is defined. Using --rt-* directly
       (rather than --modal-*) ensures the variable resolves correctly
       no matter where the modal is mounted. Hardcoded fallback after
       the comma keeps the button functional without the theme. */
    background: var(--rt-gradient, linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%));
    color: white;
    box-shadow: 0 2px 8px rgba(139, 92, 246, 0.25);
}

#realistec-mono-color-filter-modal .hist-btn-primary:hover {
    /* --rt-gradient-hover lightens on hover (#a78bfa → #818cf8). Was
       previously hardcoded to the older darker-on-hover values
       (#7c4def → #4f46e5) which made the button feel pressed/disabled
       rather than active. Now matches the Photo Editor's primary CTA
       hover treatment. */
    background: var(--rt-gradient-hover, linear-gradient(135deg, #a78bfa 0%, #818cf8 100%));
    box-shadow: 0 4px 14px rgba(139, 92, 246, 0.4);
}

#realistec-mono-color-filter-modal .hist-btn-secondary {
    padding: 8px 20px;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s;
    border: 1px solid var(--realistec-mono-border);
    font-family: inherit;
    background: var(--realistec-mono-surface-2);
    color: var(--realistec-mono-text);
}

#realistec-mono-color-filter-modal .hist-btn-secondary:hover {
    background: var(--realistec-mono-border);
    border-color: var(--realistec-mono-primary);
    /* Preserve the resting text color — without this, theme button:hover
       sets color:#ffffff which is fine here, but explicit is safer. */
    color: var(--realistec-mono-text);
}

/* ---- Mobile: stack sidebar above main, inline label+control rows ---- */
@media (max-width: 768px) {
    #realistec-mono-color-filter-modal {
        padding: 10px;
    }

    #realistec-mono-color-filter-modal.active {
        align-items: flex-start;
    }

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

    #realistec-mono-color-filter-modal .hist-modal-header,
    #realistec-mono-color-filter-modal .hist-modal-footer {
        padding: 12px 16px;
    }

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

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

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

    #realistec-mono-color-filter-modal .hist-sidebar-section:last-child {
        border-bottom: none;
    }

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

    /* Control group takes remaining space on the right */
    #realistec-mono-color-filter-modal .hist-sidebar-control-group {
        flex: 1;
        min-width: 0;
        margin: 0;
    }

    /* Dropdowns fill the control group width */
    #realistec-mono-color-filter-modal .hist-sidebar-control-group select {
        width: 100%;
    }

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

    #realistec-mono-color-filter-modal .hist-filter-strength-group .hist-sidebar-control-label {
        margin: 0;
        flex-shrink: 0;
    }

    #realistec-mono-color-filter-modal .hist-filter-strength-row {
        flex: 1;
        min-width: 0;
    }

    #realistec-mono-color-filter-modal .rmcf-histogram-container {
        flex: none;
        height: 160px;
        min-height: 160px;
    }

    /* Preview wrap: on mobile the body is overflow:auto (scrolling column
       layout), so `flex:1` gives the wrap no reliable height — portrait
       images then render letterboxed inside a roughly-square box that
       looks cropped. Switch to content-driven height with a viewport cap
       so portraits show at full aspect without pushing far below the fold. */
    #realistec-mono-color-filter-modal .rmcf-image-preview-wrap {
        flex: none;
        height: auto;
        min-height: 0;
    }

    #realistec-mono-color-filter-modal .rmcf-image-preview-wrap img {
        width: auto;
        height: auto;
        max-width: 100%;
        max-height: 60vh;
    }

    #realistec-mono-color-filter-modal .hist-main {
        padding: 16px;
        overflow-y: visible;
    }

    #realistec-mono-color-filter-modal .hist-modal-footer {
        flex-wrap: wrap;
    }

    #realistec-mono-color-filter-modal .hist-modal-footer-actions {
        width: 100%;
        justify-content: flex-end;
    }

    #realistec-mono-color-filter-modal .hist-btn-primary,
    #realistec-mono-color-filter-modal .hist-btn-secondary {
        flex: 1;
        min-width: 100px;
        text-align: center;
    }
}

/* =============================================================================
   EDITED PREVIEW (v2.3.0)
   =============================================================================
   The Edited Preview block sits in the shortcode between the Extracted Depth
   Map Preview (#realistec-mono-depth-extracted) and the Edit & Crop Option
   panel (#realistec-mono-crop-option). It surfaces the post-modal-save result
   of the Photo Editor and Color Filter modals in dedicated cards, so the
   originals in the upload-area .realistec-mono-preview-container thumbnails
   above can remain untouched.

   Visual language is borrowed from the Realistec plugin's
   .stereo-split-preview / .standard-image-frames + .stereo-split-frames
   pattern (search realistec-upload-interface.css line ~3110 and ~3144). The
   class names are local to this plugin (realistec-mono-edited-*) so they
   compose cleanly with the existing styles without colliding with any
   Realistec selectors should both plugins ever co-exist on the same page.
   The palette is mapped from Realistec's --realistec-* tokens to this
   plugin's --realistec-mono-* tokens (which resolve to the same shared
   --rt-* theme variables, so the rendered colors are identical).
   ============================================================================= */

/* Outer panel — restyled in v2.3.1 to match the established Immersity
   panel pattern used by .realistec-mono-image-preview (line ~332),
   .realistec-mono-crop-option (line ~2333), and
   .realistec-mono-color-filter-option (line ~2638):
       padding: 16px
       border: 2px solid <color>
       border-radius: 12px
       background: --realistec-mono-surface
   The border color stays --realistec-mono-primary (brand violet) like
   .realistec-mono-image-preview does for successful-content surfaces —
   the edited preview is similarly "your content, processed" rather than
   an interactive option panel (the .crop-option / .color-filter-option
   default to a muted border that escalates to primary on hover, since
   those panels are user-actionable; this block is read-only output, so
   it stays primary-violet at rest, matching .image-preview).
   Prior versions used Realistec's stereo-split styling (1px border,
   8px radius, 15px padding) which didn't match the rest of the plugin. */
.realistec-mono-edited-preview {
    margin: 20px 0;
    padding: 16px;
    background: var(--realistec-mono-surface);
    border: 2px solid var(--realistec-mono-primary);
    border-radius: 12px;
}

/* Display-type selector row — mirrors .stereo-display-type-row.
   Left-justified label-then-value pair, gap matches Realistec. */
.realistec-mono-edited-display-row {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 0 0 12px 0;
    justify-content: flex-start;
}

/* "Display:" label — mirrors .stereo-display-type-label / .previews-title
   (near-white, weight 600, 15px). Reads as a section title. */
.realistec-mono-edited-display-label {
    font-weight: 600;
    font-size: 15px;
    color: var(--realistec-mono-text);
    text-transform: none;
    letter-spacing: normal;
    margin: 0;
}

/* Dropdown — mirrors .stereo-display-type-select. Muted lavender text on
   the dark-surface-2 background, brand violet focus ring. */
.realistec-mono-edited-display-select {
    appearance: auto;
    -webkit-appearance: auto;
    background: var(--realistec-mono-surface-2);
    color: var(--realistec-mono-text-secondary);
    border: 1px solid var(--realistec-mono-border);
    border-radius: 4px;
    padding: 4px 8px;
    font-size: 12px;
    font-family: inherit;
    cursor: pointer;
    accent-color: var(--realistec-mono-primary);
    color-scheme: dark;
    max-width: 240px;
    min-width: 0;
    text-overflow: ellipsis;
}

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

.realistec-mono-edited-display-select option {
    background: var(--realistec-mono-surface-2);
    color: var(--realistec-mono-text-secondary);
}

/* Disabled options ("3D Point Cloud — coming soon") get the standard
   greyed-out treatment so users can see the future capability is planned
   without being able to select it today. */
.realistec-mono-edited-display-select option:disabled {
    color: rgba(168, 163, 201, 0.45);   /* derived from --realistec-mono-text-secondary @ 45% */
    background: var(--realistec-mono-surface-2);
    font-style: italic;
}

/* Two-up card row — mirrors .stereo-split-frames. */
.realistec-mono-edited-frames {
    display: flex;
    gap: 20px;
    justify-content: center;
    flex-wrap: wrap;
}

/* Each card — fills available width like Realistec's .split-frame.
   v2.3.2: Switched to the proven Realistec "FILL WIDTH" pattern
   (realistec-upload-interface.css line 58):
       flex: 1 1 0    — both cards split available row width 50/50
       min-width: 0   — lets the flex item shrink below its content size,
                        which is essential when the inner img would
                        otherwise push the card past its allocation
       max-width: 100% — never overflow the panel content area
       box-sizing: border-box — padding stays inside the flex allocation

   Why the prior v2.3.1 (shrink-to-fit + max-width:300px on img) failed:
   With no `width:100%` on the img, the img rendered at min(intrinsic,
   300px) = 300px for any reasonably-sized source. Each card became
   ~324px (300 + 12·2 padding). Two cards plus 20px gap = 668px, which
   exceeds the typical WooCommerce product-summary content width
   (~544px after panel padding/border). flex-wrap kicked in and the
   cards stacked.

   The fill-width pattern is robust because card width is derived from
   the available row width, not from the image's intrinsic size. So
   high-resolution dataURLs from modal saves can't blow the layout up.

   Background uses --realistec-mono-surface-2 to match the nested-
   surface convention established by .realistec-mono-preview-container
   (line ~339) — slightly lighter than the outer panel's
   --realistec-mono-surface so the image has a faint frame against
   the panel it sits in. */
.realistec-mono-edited-frame {
    flex: 1 1 0;
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
    text-align: center;
    background: var(--realistec-mono-surface-2);
    padding: 12px;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

/* Frame label — mirrors .stereo-split-frames .frame-label.
   Brand violet, 600 weight, small uppercase-style caption. */
.realistec-mono-edited-frame-label {
    display: block;
    font-weight: 600;
    color: var(--realistec-mono-primary);
    margin-bottom: 8px;
    font-size: 13px;
}

/* Image inside the card — fills the card width, height auto-derived
   from aspect ratio. No fixed max-width: the card itself is now the
   width gatekeeper (via flex:1 sharing of the panel content area), so
   the image can simply track its container.

   v2.3.2 — Mobile fix: Earlier versions used max-width: 300px with no
   width declaration. On narrow viewports where the card content area
   was less than 300px (e.g. mobile at 320–360px), the image would
   render at its 300px cap and overflow the card and panel border.
   With width: 100% + max-width: 100%, the image always shrinks with
   its card, no matter how narrow the viewport. */
.realistec-mono-edited-frame img {
    display: block;
    width: 100%;
    max-width: 100%;
    height: auto;
    object-fit: contain;
    border-radius: 6px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
    margin: 0 auto;
}

/* Frame dimensions text — mirrors .stereo-split-frames .frame-dimensions. */
.realistec-mono-edited-frame-dimensions {
    display: block;
    margin-top: 8px;
    font-size: 11px;
    color: var(--realistec-mono-text-secondary);
}

/* =============================================================================
   Standard mode: hide the depth card entirely (v2.3.1)
   =============================================================================
   Earlier versions rendered a "No depth map" placeholder tile in the second
   card when running in standard 2D mode. That placeholder turned out to be
   misleading — it suggested a depth map was expected and missing, when in
   fact standard mode has no concept of one. v2.3.1 simply hides the entire
   depth-role card in standard mode, leaving a single centered "Edited
   Image" card. The .realistec-mono-edited-frames row uses justify-content:
   center on the parent so the lone card stays centered.

   JS toggles .has-depth on .realistec-mono-edited-preview based on the
   current upload type:
       .has-depth     => depth mode: show both cards
       :not(.has-depth) => standard mode: show only the RGB card
   ============================================================================= */
.realistec-mono-edited-preview:not(.has-depth) .realistec-mono-edited-frame[data-frame-role="depth"] {
    display: none;
}

/* v2.3.2: In standard mode with only one card visible, the card defaults
   would let flex:1 stretch it to fill the entire panel width — which feels
   off (a single huge image card). Instead, give the lone card a sensible
   cap so it sizes to a comfortable single-card width and centers in the
   panel via the parent's justify-content: center. */
.realistec-mono-edited-preview:not(.has-depth) .realistec-mono-edited-frame[data-frame-role="rgb"] {
    flex: 0 1 auto;
    max-width: min(420px, 100%);
}

/* =============================================================================
   Responsive — narrow viewports (v2.3.2)
   =============================================================================
   Below 480px, force the two-card layout into a single column. Without
   this, flex-wrap:wrap on the parent would wrap the second card onto its
   own line, but flex:1 1 0 would still try to size each wrapped card to
   the entire row width — which can look correct OR can produce uneven
   widths depending on how the browser resolves the wrapped flex item.
   Switching to flex-direction:column makes the stack explicit and
   predictable, and lets each card stretch to the available column width
   (constrained by max-width:100%) so images never extend past the panel
   border on mobile.
   ============================================================================= */
@media (max-width: 480px) {
    .realistec-mono-edited-frames {
        flex-direction: column;
        gap: 12px;
    }
    .realistec-mono-edited-frame {
        max-width: 100%;
    }
    /* Standard-mode lone card: drop the desktop cap on phones — the card
       can take the full column width since there's only one. */
    .realistec-mono-edited-preview:not(.has-depth) .realistec-mono-edited-frame[data-frame-role="rgb"] {
        max-width: 100%;
    }
}

/* =============================================================================
   EDITED PREVIEW — 3D POINT CLOUD (v2.4.x)
   =============================================================================
   The "3D Point Cloud" display mode in the Edited Preview block swaps the
   side-by-side .realistec-mono-edited-frames cards for a WebGL canvas that
   renders the edited RGB + depth-map pair as an interactive point cloud
   (see the POINT CLOUD RENDERER block in upload-interface.js).

   These rules style the HOST element the JS injects after the frames row,
   plus the small status line shown while the cloud builds. The canvas
   itself is sized in JS (it tracks the host's width and picks its own
   height), so CSS here only needs to give the host a sensible box and
   style the status text — without these rules the cloud still renders,
   it just sits on a bare background with an unstyled "Building..." line.

   Palette follows the same --realistec-mono-* tokens the rest of the
   Edited Preview block uses, so the point-cloud panel reads as part of
   the same surface.
   ============================================================================= */

/* Host — the container the WebGL canvas lives in. JS toggles its
   display (none <-> block) as the user switches the Display dropdown
   between "Standard View" and "3D Point Cloud". Background uses
   --realistec-mono-surface-2 to match the nested-surface convention of
   the .realistec-mono-edited-frame cards it replaces, so swapping
   between the two views doesn't change the panel's visual depth. */
.realistec-mono-edited-pointcloud-host {
    position: relative;        /* anchor for the absolutely-centred status line */
    width: 100%;
    min-height: 220px;         /* matches the JS minimum canvas height */
    box-sizing: border-box;
    background: var(--realistec-mono-surface-2);
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    overflow: hidden;          /* keep the canvas corners inside the radius */
}

/* The canvas element itself. JS sets its pixel dimensions and inline
   width/height; this just makes sure it behaves as a block and can't
   pick up stray inline-element spacing. The cursor hints that the
   cloud is draggable (JS also sets cursor:grab inline, this is a
   stylesheet-level fallback). */
.realistec-mono-edited-pointcloud-canvas {
    display: block;
    margin: 0 auto;
    cursor: grab;
}
.realistec-mono-edited-pointcloud-canvas:active {
    cursor: grabbing;
}

/* Status line — shown centred over the host while the cloud is
   building ("Building 3D point cloud...") and removed once it's up, or
   left in place with an error message if the build fails. Muted text
   on the nested surface, same treatment as .realistec-mono-edited-
   frame-dimensions so it reads as quiet supporting text rather than a
   prominent message. */
.realistec-mono-edited-pointcloud-status {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    margin: 0;
    padding: 0 12px;
    font-size: 13px;
    text-align: center;
    color: var(--realistec-mono-text-secondary);
    pointer-events: none;      /* never intercept drags meant for the canvas */
}

/* Responsive — on narrow viewports the host can shrink with the panel;
   keep the minimum height a touch smaller so it doesn't dominate a
   phone screen. The canvas tracks the host width in JS regardless. */
@media (max-width: 480px) {
    .realistec-mono-edited-pointcloud-host {
        min-height: 180px;
    }
}

/* =============================================================================
   POINT CLOUD — ZOOM CONTROLS (v2.4.5)
   =============================================================================
   Zoom +/- buttons in the bottom-right corner of the point-cloud host panel.
   Primary zoom mechanism on touch devices (no mouse wheel); supplements wheel
   zoom on desktop. Uses Material Symbols "zoom_in" / "zoom_out" icons, matching
   the rest of the plugin's icon usage (.realistec-mono-msi material-symbols-
   outlined).
   ============================================================================= */

/* Container — absolutely positioned in the bottom-right corner of the
   host panel, with a small margin so the buttons don't touch the edges. */
.realistec-mono-edited-pointcloud-zoom {
    position: absolute;
    bottom: 12px;
    right: 12px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    z-index: 2; /* sit above the canvas */
}

/* Each button — small, square, translucent dark background so it reads
   over both light and dark cloud content. The icon inherits the button's
   color. */
.realistec-mono-edited-pointcloud-zoom-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    margin: 0;
    border: 1px solid var(--realistec-mono-border, rgba(255,255,255,0.15));
    border-radius: 8px;
    background: rgba(0, 0, 0, 0.55);
    color: var(--realistec-mono-text, #fff);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, border-color 0.15s;
}
.realistec-mono-edited-pointcloud-zoom-btn:hover,
.realistec-mono-edited-pointcloud-zoom-btn:focus-visible {
    background: rgba(0, 0, 0, 0.75);
    border-color: var(--realistec-mono-primary, #8b5cf6);
    outline: none;
}
.realistec-mono-edited-pointcloud-zoom-btn:active {
    background: var(--realistec-mono-primary, #8b5cf6);
}
/* Material Symbols icon inside the button — size it to fit the 36px
   square without extra padding. */
.realistec-mono-edited-pointcloud-zoom-btn .realistec-mono-msi {
    font-size: 22px;
    line-height: 1;
}

/* =============================================================================
   POINT CLOUD — SWIPE HINT OVERLAY (v2.4.7)
   =============================================================================
   A centered "swipe" icon overlay that appears when the 3D Depth Projection
   is first shown, indicating to the user that the projection is interactive.
   Dismissed on the first click/touch anywhere on the host panel — the JS
   removes the .visible class, which fades the overlay out via opacity
   transition.
   ============================================================================= */

.realistec-mono-edited-pointcloud-swipe-hint {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 3;              /* above the canvas (z:1) and zoom buttons (z:2) */
    pointer-events: none;    /* never block drags or clicks on the canvas */
    opacity: 0;
    transition: opacity 0.4s ease;
}
.realistec-mono-edited-pointcloud-swipe-hint.visible {
    opacity: 1;
}

/* The icon itself — large, softly glowing, with a subtle pulse animation
   to draw attention without being obnoxious. */
.realistec-mono-edited-pointcloud-swipe-hint .realistec-mono-msi {
    font-size: 56px;
    color: rgba(255, 255, 255, 0.7);
    text-shadow: 0 0 20px rgba(139, 92, 246, 0.5);
    animation: realistec-mono-swipe-pulse 2s ease-in-out infinite;
}

@keyframes realistec-mono-swipe-pulse {
    0%, 100% { opacity: 0.7; transform: scale(1); }
    50%      { opacity: 1;   transform: scale(1.08); }
}
