/* ═══════════════════════════════════════════════════════════
   LIGHTDROPPER — Canvas + tool-managed UI styles
   The Webflow page owns all the chrome (nav, modals, controls,
   info panel, preloader, buttons). This file only styles the
   3D canvas and the floating UI the script creates dynamically.
═══════════════════════════════════════════════════════════ */

/* ─── Tokens ─────────────────────────────────────────────── */
/* The two font stacks were previously written out verbatim in six
   places, which is how they drift. Declared once here instead.
   Roboto itself is loaded by the Webflow page's Google Fonts embed —
   this file requests no fonts and no other assets (no @import, no
   url()), so nothing is fetched twice. */
:root {
    --ld-font: 'Roboto', -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
    --ld-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    /* Diameter of one ellipsis dot in the saved-setups rows. Single knob:
       the dots are real elements, not a text glyph, so this is exact. */
    --ld-dot-size: 3px;
}

/* ─── Canvas ─────────────────────────────────────────────── */
/* Sits inside the .code-embed div which is already
   position: absolute; inset: 0; z-index: -1 in Webflow CSS,
   so the canvas naturally fills the viewport behind all chrome. */
#lightdropper-canvas {
    display: block;
    pointer-events: auto;
}

/* ─── Color picker (iro.js + hex input, unified panel) ──── */
.ld-color-picker-wrapper {
    position: fixed;
    display: none;
    background: #121212;
    color: #ffffff;
    padding: 20px;
    border-radius: 16px;
    z-index: 2000;
    pointer-events: auto;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4);
    font-family: var(--ld-font);
}
/* ─── Shared text-input style ────────────────────────────── */
/* The hex field is the reference implementation; the saved-setups name
   field reuses it. Written as one rule rather than two copies so the
   border weight, radius, height and focus treatment cannot drift.
   Per-field extras (width, monospace, lowercasing) stay separate. */
.ld-color-picker-hex,
.ld-setups-input {
    display: block;
    box-sizing: border-box;
    padding: 10px 14px;
    /* currentColor, not a literal: the picker sits on a permanently dark
       panel while the setups modal flips with the canvas. Following the
       text colour means one rule serves both and neither can drift. */
    border: 2px solid currentColor;
    border-radius: 12px;
    background: transparent;
    color: inherit;
    font-size: 14px;
    outline: none;
}
.ld-color-picker-hex:focus,
.ld-setups-input:focus {
    /* Muted version of whatever the border already is. The rgba line is the
       fallback for browsers without color-mix(); it matches the picker's
       original white-on-dark focus state. */
    border-color: rgba(255, 255, 255, 0.55);
    border-color: color-mix(in srgb, currentColor 55%, transparent);
}
.ld-color-picker-hex {
    width: 140px; /* matches the iro picker `width: 140` option */
    margin-top: 14px;
    font-family: var(--ld-mono);
    letter-spacing: 0.5px;
    text-transform: lowercase;
}

/* ─── Right-click context menu ───────────────────────────── */
/* Default colors are set below in the contrast section (light menu
   on default dark canvas; dark menu when canvas is light). */
.ld-context-menu {
    position: fixed;
    display: none;
    border-radius: 12px;
    overflow: hidden;
    padding: 0;
    min-width: 220px;
    z-index: 2000;
    font-size: 13px;
    font-family: var(--ld-font);
}
.ld-context-menu-item {
    padding: 10px 16px;
    display: flex;
    justify-content: space-between;
    cursor: pointer;
    user-select: none;
    transition: background 0.1s;
}
.ld-context-menu-shortcut {
    font-size: 11px;
    margin-left: 20px;
}

/* ─── Intensity flash (shows %% on light click) ──────────── */
/* Background/color set below in the contrast section. */
.ld-intensity-flash {
    position: fixed;
    display: none;
    padding: 4px 10px;
    border-radius: 20px;
    font-weight: 700;
    font-size: 13px;
    pointer-events: none;
    transform: translate(-50%, -50%);
    z-index: 2000;
    opacity: 0;
    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
    white-space: nowrap;
    transition: opacity 0.2s ease-out, background 0.1s ease, color 0.1s ease, left 0.15s ease-out, top 0.15s ease-out;
    font-family: var(--ld-font);
}

/* ─── Persistent light labels (shown on L key) ───────────── */
.ld-persistent-labels {
    position: fixed;
    inset: 0;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.3s ease;
    z-index: 1500;
}
.ld-persistent-label {
    position: absolute;
    background: rgba(0,0,0,0.7);
    color: #fff;
    padding: 4px 10px;
    border-radius: 20px;
    font-size: 11px;
    font-weight: 600;
    pointer-events: none;
    transform: translate(-50%, -50%);
    white-space: nowrap;
    z-index: 50;
    backdrop-filter: blur(4px);
    transition: left 0.15s ease-out, top 0.15s ease-out, opacity 0.2s ease;
    font-family: var(--ld-font);
}

/* ═══════════════════════════════════════════════════════════
   STACKING CONTEXT FIX
   The Webflow .code-embed uses z-index: -1 to sit behind chrome.
   For that to be hit-testable (so OrbitControls/DragControls
   on the canvas inside actually receive clicks), <body> must
   create its own stacking context. This single rule does that.
═══════════════════════════════════════════════════════════ */
body {
    position: relative;
    z-index: 0;
}

/* ═══════════════════════════════════════════════════════════
   LUMINANCE / DARK MODE
   When the canvas background is LIGHT, white Webflow chrome
   becomes invisible. The script adds `.light-bg` to <body>,
   which inverts any `.luminance` element. Raster images
   inside `.luminance` that should keep their original colors
   get a `.no-invert` class which double-inverts them back.
═══════════════════════════════════════════════════════════ */
body.light-bg .luminance {
    filter: invert(1);
}
body.light-bg .luminance .no-invert {
    filter: invert(1); /* double-invert = original colors */
}

/* ═══════════════════════════════════════════════════════════
   CONTEXT MENU — always contrasts the canvas background.
   Default canvas is dark (#333), so menu is LIGHT by default.
   When the user picks a light bg, .light-bg activates and the
   menu flips DARK so it remains readable.
═══════════════════════════════════════════════════════════ */
.ld-context-menu {
    background: #f9f9f9;
    color: #121212;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2);
}
.ld-context-menu-item { border-bottom: 1px solid #e0e0e0; }
.ld-context-menu-item:last-child { border-bottom: none; }
.ld-context-menu-item:hover { background: #e0e0e0; }
.ld-context-menu-shortcut { color: #666; }
.ld-intensity-flash {
    background: rgba(255, 255, 255, 0.9);
    color: #121212;
}

body.light-bg .ld-context-menu {
    background: #121212;
    color: #eee;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4);
}
body.light-bg .ld-context-menu-item { border-bottom: 1px solid #2a2a2a; }
body.light-bg .ld-context-menu-item:last-child { border-bottom: none; }
body.light-bg .ld-context-menu-item:hover { background: #2a2a2a; }
body.light-bg .ld-context-menu-shortcut { color: #888; }
body.light-bg .ld-intensity-flash {
    background: rgba(0, 0, 0, 0.8);
    color: #ffffff;
}

/* ═══════════════════════════════════════════════════════════
   POINTER-EVENTS FIXES — let clicks reach the canvas through
   the upload page's intro overlay and other 100%-wide chrome
═══════════════════════════════════════════════════════════ */

/* Upload page intro: container shouldn't block events, only the button does */
.custom-model-holder {
    pointer-events: none;
}
.custom-model-holder a,
.custom-model-holder button,
.custom-model-holder #upload {
    pointer-events: auto;
}

/* The 1px-line and toggle-info indicator shouldn't block events either */
._1px-line { pointer-events: none; }
.toggle-info { pointer-events: none; }

/* ═══════════════════════════════════════════════════════════
   MATERIAL APPEARANCE EDITOR — matches the color-picker panel and
   its slider. Panel padding is applied to inner rows (not the
   wrapper) so divider lines can span the full panel width.
═══════════════════════════════════════════════════════════ */
.ld-mat-editor {
    padding: 20px;              /* match the color-picker panel padding */
    width: 148px;               /* 232 - 84; matches picker content width feel */
    box-sizing: content-box;
}
.ld-mat-editor-drag {
    height: 22px;
    cursor: grab;
    user-select: none;
    touch-action: none;
    background: rgba(127, 127, 127, 0.18);
    border-radius: 4px;
    /* Pull to the padded wrapper's edges but stay inset by the corner radius —
       same treatment as the color-picker drag bar. */
    margin: -8px -8px 14px -8px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.ld-mat-editor-grip {
    width: 24px;
    height: 4px;
    background-image: radial-gradient(circle, #ffffff 1px, transparent 1px);
    background-size: 6px 4px;
    opacity: 0.6;
    pointer-events: none;
}
/* All rows have identical horizontal content boxes (no side padding), so the
   slider track is the SAME width in every row regardless of dividers. The
   divider is a separate full-bleed element drawn between rows, not a border on
   the row — that previously made divider-rows narrower than the last row. */
.ld-mat-slider-row {
    padding: 14px 0;
    box-sizing: border-box;
    width: 100%;
}
.ld-mat-slider-row:first-child { padding-top: 0; }
.ld-mat-slider-row:last-child  { padding-bottom: 0; }
/* Disabled row: greyed + non-interactive. Used for the transparency group
   (Transparency/Distortion/Dispersion) when Metalness > 0, since a metal can't
   be transmissive. The greying signals the metalness↔transparency dependency. */
.ld-mat-slider-row.ld-mat-disabled {
    opacity: 0.4;
    pointer-events: none;
}
/* Full-width divider line between rows. Negative side margins span the panel's
   20px padding so the line reaches edge to edge. */
.ld-mat-divider-line {
    height: 1px;
    background: rgba(255, 255, 255, 0.18);
    margin: 0 -20px;
}
.ld-mat-slider-label {
    font-family: var(--ld-mono);
    font-size: 13px;
    color: #ffffff;
    margin-bottom: 12px;
    letter-spacing: 0.3px;
    white-space: nowrap;
}
/* ── Slider geometry ──
   Track height: 28.5px including outline. 2px white outline, track fill = panel
   background (#121212). Handle: 14px circle, white 2px outline / black center.
   The track has 5.5px horizontal padding so the thumb keeps an end-gap at the
   left/right extremes (native range inputs don't provide horizontal end-gaps on
   their own). These exact values were pixel-tuned by the user; see the 2x note
   below before changing them. */
/* NOTE ON SIZES: the user measures in Photoshop on a 2x (Retina) display, so
   their pixel readings are DOUBLE these CSS values. Values below are in CSS px;
   e.g. a 28.5px track reads as ~57px in a 2x screenshot. Keep this in mind when
   translating measured targets → CSS (divide by 2). */
.ld-mat-slider-track {
    position: relative;
    height: 28.5px;             /* 57px @2x */
    border-radius: 14.25px;     /* half the height — full pill */
    background: #121212;
    border: 2px solid #ffffff;
    box-sizing: border-box;
    padding: 0 5.5px;           /* 11px @2x horizontal end-gaps */
    margin-bottom: 6px;         /* 12px @2x gap between rows */
    display: flex;
    align-items: center;
}
.ld-mat-slider {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    height: 14px;
    margin: 0;
    background: transparent;
    cursor: pointer;
}
.ld-mat-slider::-webkit-slider-runnable-track {
    height: 14px;
    background: transparent;
    border: none;
}
.ld-mat-slider::-moz-range-track {
    height: 14px;
    background: transparent;
    border: none;
}
.ld-mat-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: #000000;
    border: 2px solid #ffffff;
    box-sizing: border-box;
    margin-top: 0;
    cursor: grab;
}
.ld-mat-slider::-moz-range-thumb {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: #000000;
    border: 2px solid #ffffff;
    box-sizing: border-box;
    cursor: grab;
}
.ld-mat-slider:active::-webkit-slider-thumb { cursor: grabbing; }
.ld-mat-slider:active::-moz-range-thumb { cursor: grabbing; }

/* ═══════════════════════════════════════════════════════════
   SAVED SETUPS — panel, row menu, and modals
   Created dynamically by the script (like the context menu and color
   picker), so all of their styling lives here rather than in Webflow.
   The only Webflow-authored piece is the trigger button (id="save",
   containing span.saved-setups-count), which ships with display:none
   so the in-progress feature stays hidden if the script fails to load.
═══════════════════════════════════════════════════════════ */

/* ─── Panel ──────────────────────────────────────────────── */
.ld-setups-panel {
    position: fixed;
    display: none;
    /* Measured 76px too high and 10px too far right on a 2x display —
       halved to CSS px: down 38 (64→102), left 5 (24→29, since `right`
       grows leftward). */
    top: 102px;
    right: 29px;
    width: 300px;
    /* Palette, radius and type size all come from .ld-context-menu: these
       panels CONTRAST the canvas rather than matching it, so they stay
       readable when the user picks a light background. Light here because
       the default canvas is dark; body.light-bg flips both. */
    background: #f9f9f9;
    color: #121212;
    border-radius: 12px;
    font-size: 13px;
    overflow: hidden;
    z-index: 2000;
    pointer-events: auto;   /* the nav overlay above is pointer-events:none */
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2);
    font-family: var(--ld-font);
}

/* Ten rows, then scroll. A row is 10px + 10px padding + a ~15px line box
   + a 1px divider ≈ 36px, matching .ld-context-menu-item exactly. */
.ld-setups-list {
    max-height: 360px;
    overflow-y: auto;
    overscroll-behavior: contain;
}
/* Geometry lifted from .ld-context-menu-item — same padding, same divider,
   same hover timing. Not written as a shared selector because the palette
   differs (see the row-menu note below). */
.ld-setups-row {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 16px;
    box-sizing: border-box;
    border-bottom: 1px solid #e0e0e0;
    cursor: pointer;
    user-select: none;
    transition: background 0.1s;
}
.ld-setups-row:last-child { border-bottom: none; }
.ld-setups-row:hover { background: #e0e0e0; }
.ld-setups-row-name {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* The ellipsis only appears on hover, so a resting list stays quiet.
   Three real elements rather than a "···" text glyph: dot size is then an
   exact number (--ld-dot-size) instead of a side effect of font metrics.
   The button keeps its padding as a generous hit area but paints no
   background — only the dots themselves respond, brightening to full
   white. */
.ld-setups-row-dots {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 3px;
    opacity: 0;
    background: none;
    border: none;
    color: inherit;
    padding: 6px 8px;
    cursor: pointer;
    transition: opacity 0.2s ease;
}
.ld-setups-dot {
    width: var(--ld-dot-size);
    height: var(--ld-dot-size);
    border-radius: 50%;
    background: currentColor;
}
.ld-setups-row:hover .ld-setups-row-dots { opacity: 0.85; }
.ld-setups-row-dots:hover { opacity: 1; }

/* ─── Empty state ────────────────────────────────────────── */
.ld-setups-empty { padding: 28px 24px; text-align: center; }
.ld-setups-empty-title { font-size: 16px; font-weight: 600; margin-bottom: 10px; }
.ld-setups-empty-body { font-size: 13px; line-height: 1.5; color: #4D4D4D; }

/* ─── Storage-warning footer ─────────────────────────────── */
/* Only rendered when at least one setup exists. Same muted treatment as the
   empty-state copy; the last row drops its own divider, so the border here
   supplies the single separating line. */
.ld-setups-foot {
    padding: 12px 16px;
    border-top: 1px solid #e0e0e0;
    color: #4D4D4D;
    line-height: 1.45;
}

/* ─── Row ellipsis menu ──────────────────────────────────── */
/* Now a plain narrowing of .ld-context-menu again. It previously needed a
   full colour override because the panel matched the canvas while the menu
   contrasted it — the two were exact inverses, so a light menu opened out
   of a dark panel. With the panel on the same contrast-the-canvas rule,
   inheritance is correct on its own. */
.ld-setups-rowmenu { min-width: 160px; }

/* ─── Modals (Save / Rename / Delete) ────────────────────── */
.ld-setups-modal {
    position: fixed;
    inset: 0;
    display: none;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.45);
    z-index: 2100;
    pointer-events: auto;
    font-family: var(--ld-font);
}
.ld-setups-modal-card {
    position: relative;
    width: 340px;
    background: #f9f9f9;
    color: #121212;
    border-radius: 16px;
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.25);
}
.ld-setups-modal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 18px 20px;
    border-bottom: 1px solid #e0e0e0;
}
.ld-setups-modal-title { font-size: 18px; font-weight: 600; }
/* An X in the corner instead of a Cancel button — one less control to read.
   The glyph is now the Material close icon as inline SVG (stroke follows
   currentColor, so the light-bg flip needs no separate icon asset). */
.ld-setups-modal-x {
    position: absolute;
    top: 14px;
    right: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding: 0;
    background: none;
    border: none;
    color: inherit;
    cursor: pointer;
    opacity: 0.85;
    transition: opacity 0.2s ease;
}
.ld-setups-modal-x:hover { opacity: 1; }
.ld-setups-modal-x svg { display: block; width: 24px; height: 24px; }
.ld-setups-modal-head .ld-setups-modal-x { position: static; }
.ld-setups-modal-body { padding: 20px; }

/* Base style shared with .ld-color-picker-hex — see the input rule above.
   Only the field-specific bits live here. */
.ld-setups-input {
    width: 100%;
    font-family: inherit;
}

/* Duplicate-name warning. */
.ld-setups-warn {
    margin-top: 12px;
    color: #DF2915;
    font-size: 13px;
    line-height: 1.45;
}

.ld-setups-modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: 20px;
    margin-top: 18px;
}
.ld-setups-action {
    background: none;
    border: none;
    color: inherit;
    font-size: 14px;
    font-family: inherit;
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
    padding: 4px 2px;
    transition: opacity 0.2s ease;
}
.ld-setups-action:hover { opacity: 0.5; }

/* ─── Delete confirmation ────────────────────────────────── */
.ld-setups-modal-confirm { width: 400px; padding: 32px; box-sizing: border-box; }
/* Material warning icon, inline SVG filled with currentColor. */
.ld-setups-warn-icon { width: 48px; height: 48px; margin-bottom: 20px; }
.ld-setups-warn-icon svg { display: block; width: 100%; height: 100%; }
.ld-setups-modal-confirm .ld-setups-modal-title { font-size: 26px; margin-bottom: 16px; }
.ld-setups-modal-copy { font-size: 15px; line-height: 1.5; color: #3a3a3a; margin-bottom: 28px; }
.ld-setups-confirm-actions { display: flex; gap: 16px; }
.ld-setups-btn {
    flex: 1;
    padding: 14px 18px;
    border-radius: 999px;
    border: 2px solid #c8c8c8;
    background: transparent;
    color: inherit;
    font-size: 15px;
    font-family: inherit;
    cursor: pointer;
    transition: background 0.12s ease, border-color 0.12s ease;
}
.ld-setups-btn:hover { background: #e6e6e6; }
.ld-setups-btn-danger { border-color: #DF2915; }
.ld-setups-btn-danger:hover { background: rgba(223, 41, 21, 0.15); }

/* ─── Light-background contrast ──────────────────────────── */
/* Mirrors .ld-context-menu exactly: when the canvas goes light these panels
   go dark, so they always contrast whatever is behind them. Anything that
   uses `inherit` or `currentColor` above (dots, close icon, link actions,
   input border) needs no entry here — it follows the surface on its own. */
body.light-bg .ld-setups-panel,
body.light-bg .ld-setups-modal-card {
    background: #121212;
    color: #eee;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4);
}
body.light-bg .ld-setups-row { border-bottom-color: #2a2a2a; }
body.light-bg .ld-setups-row:hover { background: #2a2a2a; }
body.light-bg .ld-setups-modal-head { border-bottom-color: #2a2a2a; }
body.light-bg .ld-setups-modal-copy { color: #d8d8d8; }
body.light-bg .ld-setups-btn { border-color: #3a3a3a; }
body.light-bg .ld-setups-btn:hover { background: #1c1c1c; }
/* Both of the rules above outrank the plain .ld-setups-btn-danger pair
   (0,2,0 and 0,3,0 against 0,1,0 and 0,2,0), so the neutral grey was
   overwriting the red outline whenever the card went dark. Restated at
   matching specificity rather than reordered, since source order alone
   wouldn't settle it. */
body.light-bg .ld-setups-btn-danger { border-color: #DF2915; }
body.light-bg .ld-setups-btn-danger:hover { background: rgba(223, 41, 21, 0.15); }
/* The mirror of #4D4D4D under the same invert(1) the .luminance chrome
   uses (255-77 = 178), so the muted copy reads the same weight in both. */
body.light-bg .ld-setups-empty-body { color: #B2B2B2; }
body.light-bg .ld-setups-foot { border-top-color: #2a2a2a; color: #B2B2B2; }
/* Primary action (Save / Replace) reads slightly stronger than Cancel. */
.ld-setups-action-primary { font-weight: 500; }
