<style>
.clr-color-block{position:relative}
.clr-color-row{display:flex;align-items:center;gap:8px}
.clr-color-swatch{width:34px;height:34px;border-radius:8px;border:2px solid #e5e7eb;cursor:pointer;flex-shrink:0;padding:0;position:relative;overflow:hidden;background:repeating-conic-gradient(#d1d5db 0% 25%,#fff 0% 50%) 0 0/14px 14px}
.clr-color-swatch .clr-swatch-fill{position:absolute;inset:0;border-radius:6px;pointer-events:none}
.clr-color-swatch:hover{border-color:#818cf8}
.clr-hex-input{width:88px;padding:6px 8px;border:1px solid #d1d5db;border-radius:7px;font-size:12px;font-family:monospace;outline:none;transition:border-color .12s}
.clr-hex-input:focus{border-color:#4f46e5;box-shadow:0 0 0 3px rgba(79,70,229,.08)}
.clr-opacity-badge{padding:2px 6px;font-size:10px;font-weight:600;color:#6b7280;background:#f3f4f6;border-radius:10px;white-space:nowrap}
.clr-reset-btn{padding:3px 6px;font-size:10px;color:#9ca3af;background:none;border:1px solid #e5e7eb;border-radius:6px;cursor:pointer;transition:all .12s;white-space:nowrap;line-height:1}
.clr-reset-btn:hover{color:#dc2626;border-color:#fecaca;background:#fef2f2}
.clr-picker{display:none;position:absolute;top:100%;left:0;z-index:100;width:260px;background:#fff;border:1px solid #e5e7eb;border-radius:12px;box-shadow:0 12px 40px rgba(0,0,0,.15);padding:14px;margin-top:6px}
.clr-picker.open{display:block}
.clr-picker__sv-wrap{position:relative;width:100%;height:150px;border-radius:8px;overflow:hidden;cursor:crosshair;margin-bottom:12px}
.clr-picker__sv-wrap canvas{width:100%;height:100%;display:block}
.clr-picker__sv-cursor{position:absolute;width:14px;height:14px;border:2px solid #fff;border-radius:50%;box-shadow:0 0 0 1px rgba(0,0,0,.3),inset 0 0 0 1px rgba(0,0,0,.15);pointer-events:none;transform:translate(-50%,-50%)}
.clr-picker__row{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.clr-picker__label{font-size:10px;font-weight:600;color:#9ca3af;text-transform:uppercase;width:14px;flex-shrink:0}
.clr-picker__hue{-webkit-appearance:none;appearance:none;flex:1;height:12px;border-radius:6px;outline:none;background:linear-gradient(to right,#f00 0%,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,#f00 100%);cursor:pointer}
.clr-picker__hue::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;border-radius:50%;background:#fff;border:2px solid rgba(0,0,0,.2);box-shadow:0 1px 3px rgba(0,0,0,.2);cursor:pointer}
.clr-picker__alpha-track{flex:1;height:12px;border-radius:6px;position:relative;overflow:hidden;background:repeating-conic-gradient(#d1d5db 0% 25%,#fff 0% 50%) 0 0/10px 10px}
.clr-picker__alpha-fill{position:absolute;inset:0;border-radius:6px}
.clr-picker__alpha{-webkit-appearance:none;appearance:none;position:absolute;inset:0;width:100%;height:100%;background:transparent;cursor:pointer;margin:0}
.clr-picker__alpha::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;border-radius:50%;background:#fff;border:2px solid rgba(0,0,0,.2);box-shadow:0 1px 3px rgba(0,0,0,.2);cursor:pointer}
.clr-picker__alpha-val{font-size:11px;font-weight:600;color:#374151;min-width:30px;text-align:right}
.clr-picker__hex-row{display:flex;align-items:center;gap:8px;margin-top:4px}
.clr-picker__hex-input{flex:1;padding:6px 8px;border:1px solid #d1d5db;border-radius:6px;font-size:12px;font-family:monospace;outline:none}
.clr-picker__hex-input:focus{border-color:#4f46e5;box-shadow:0 0 0 3px rgba(79,70,229,.08)}
.clr-picker__default{font-size:10px;color:#9ca3af;cursor:pointer;white-space:nowrap;padding:5px 8px;border:1px solid #e5e7eb;border-radius:5px;background:#f9fafb;transition:all .1s}
.clr-picker__default:hover{color:#4f46e5;border-color:#c7d2fe}
.clr-preview{display:flex;gap:3px;height:28px;border-radius:6px;overflow:hidden;border:1px solid #e5e7eb}
.clr-preview__slab{flex:1}
.clr-tip{position:relative;display:inline-flex;align-items:center;color:#9ca3af;font-size:9px;cursor:help;margin-left:3px;vertical-align:middle}
.clr-tip::after{content:attr(data-tip);position:absolute;bottom:calc(100% + 6px);left:50%;transform:translateX(-50%);background:#1e293b;color:#f1f5f9;font-size:10px;font-weight:400;line-height:1.3;padding:5px 9px;border-radius:6px;white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .15s;z-index:50}
.clr-tip:hover::after{opacity:1}
.clr-tip:hover{color:#6366f1}
.clr-tip--dark{color:#64748b}
.clr-tip--dark::after{background:#f1f5f9;color:#1e293b}
.clr-tip--dark:hover{color:#818cf8}
.clr-shared-badge{display:inline-flex;align-items:center;gap:3px;padding:1px 6px;font-size:9px;font-weight:600;color:#6366f1;background:#eef2ff;border-radius:8px;margin-left:4px;letter-spacing:.02em}
@media(max-width:479px){.clr-picker{width:calc(100vw - 48px);left:50%;transform:translateX(-50%)}}
.clr-card--disabled{position:relative;opacity:.45;pointer-events:none}
.clr-disabled-banner{pointer-events:auto;padding:8px 16px;font-size:11px;font-weight:500;color:#6b7280;background:#f9fafb;border-bottom:1px solid #e5e7eb;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.clr-disabled-banner--dark{background:#1e293b;color:#94a3b8;border-color:#334155}
.clr-activate-link{color:#4f46e5;font-weight:600;text-decoration:none;margin-left:2px}
.clr-activate-link:hover{text-decoration:underline}
@media(max-width:639px){.clr-color-row{gap:6px}}
</style>

<?php
 
$dmEnabled = (Setting::get('hentai_dark_mode_enabled', '1') === '1');
$dmDefault = Setting::get('hentai_dark_mode_default', 'dark');
$lightNeeded = $dmEnabled || $dmDefault === 'light';
$darkNeeded  = $dmEnabled || $dmDefault === 'dark';
$lightPrimary = $settings['color_primary'] ?? '';

 
$lightColors = [
    'color_primary'      => ['label' => 'Primary',     'default' => '#2563eb', 'badge' => $dmEnabled ? 'both themes (default)' : ''],
    'color_bg'           => ['label' => 'Background',  'default' => '#ffffff'],
    'color_bg_surface'   => ['label' => 'Surface',     'default' => '#f8fafc', 'tip' => 'Sidebar, section backgrounds, inputs'],
    'color_bg_card'      => ['label' => 'Card',        'default' => '#ffffff', 'tip' => 'Video cards, comments, content blocks'],
    'color_bg_dark'      => ['label' => 'Dark BG',     'default' => '#0f172a', 'tip' => 'Footer, overlays, placeholders'],
    'color_text'         => ['label' => 'Text',        'default' => '#1e293b'],
    'color_text_muted'   => ['label' => 'Muted Text',  'default' => '#64748b', 'tip' => 'Links, buttons, meta, "See more", placeholders'],
    'color_border'       => ['label' => 'Border',      'default' => '#e2e8f0'],
];

 
$darkColors = [
    'dk_color_primary'    => ['label' => 'Primary',     'default' => $lightPrimary ?: '#2563eb', 'tip' => 'Inherits from Light if empty'],
    'dk_color_bg'         => ['label' => 'Background',  'default' => '#0f172a'],
    'dk_color_bg_surface' => ['label' => 'Surface',     'default' => '#020617', 'tip' => 'Sidebar, section backgrounds, inputs'],
    'dk_color_bg_card'    => ['label' => 'Card',        'default' => '#1e293b', 'tip' => 'Video cards, comments, content blocks'],
    'dk_color_bg_dark'    => ['label' => 'Dark BG',     'default' => '#020617', 'tip' => 'Footer, overlays, placeholders'],
    'dk_color_text'       => ['label' => 'Text',        'default' => '#f1f5f9'],
    'dk_color_text_muted' => ['label' => 'Muted Text',  'default' => '#b8c5d4', 'tip' => 'Links, buttons, meta, "See more", placeholders'],
    'dk_color_border'     => ['label' => 'Border',      'default' => '#334155'],
];

$allColors = array_merge($lightColors, $darkColors);

 
function renderColorField(string $key, array $info, array $settings): void {
    $val = $settings[$key] ?? '';
    $opVal = (int) ($settings[$key . '_opacity'] ?? '100');
    $tip = $info['tip'] ?? '';
    $badge = $info['badge'] ?? '';
    ?>
    <div class="clr-color-block" id="clr_<?= $key ?>_block">
        <label class="block text-xs font-medium text-gray-600 mb-1"><?= $info['label'] ?><?php if ($tip): ?><span class="clr-tip" data-tip="<?= htmlspecialchars($tip) ?>"><i class="fa-solid fa-circle-info"></i></span><?php endif; ?><?php if ($badge): ?><span class="clr-shared-badge"><i class="fa-solid fa-link" style="font-size:7px"></i> <?= $badge ?></span><?php endif; ?></label>
        <div class="clr-color-row">
            <button type="button" class="clr-color-swatch" id="clr_<?= $key ?>_swatch"
                    onclick="clrOpen('<?= $key ?>')" data-default="<?= $info['default'] ?>">
                <span class="clr-swatch-fill" id="clr_<?= $key ?>_fill"></span>
            </button>
            <input type="text" id="clr_<?= $key ?>_hex" name="<?= $key ?>"
                   value="<?= htmlspecialchars($val) ?>"
                   placeholder="<?= $info['default'] ?>"
                   maxlength="7"
                   class="clr-hex-input"
                   oninput="clrHexTyped('<?= $key ?>')">
            <input type="hidden" id="clr_<?= $key ?>_opacity" name="<?= $key ?>_opacity" value="<?= $opVal ?>">
            <span class="clr-opacity-badge" id="clr_<?= $key ?>_opacity_val"><?= $opVal ?>%</span>
            <button type="button" class="clr-reset-btn" onclick="clrReset('<?= $key ?>')" title="Reset">
                <i class="fa-solid fa-rotate-left" style="font-size:9px;"></i>
            </button>
        </div>
    </div>
    <?php
}

 
function renderDarkColorField(string $key, array $info, array $settings): void {
    $val = $settings[$key] ?? '';
    $opVal = (int) ($settings[$key . '_opacity'] ?? '100');
    $tip = $info['tip'] ?? '';
    ?>
    <div class="clr-color-block" id="clr_<?= $key ?>_block">
        <label class="block text-xs font-medium text-gray-300 mb-1"><?= $info['label'] ?><?php if ($tip): ?><span class="clr-tip clr-tip--dark" data-tip="<?= htmlspecialchars($tip) ?>"><i class="fa-solid fa-circle-info"></i></span><?php endif; ?></label>
        <div class="clr-color-row">
            <button type="button" class="clr-color-swatch" id="clr_<?= $key ?>_swatch"
                    onclick="clrOpen('<?= $key ?>')" data-default="<?= $info['default'] ?>" style="border-color:#475569">
                <span class="clr-swatch-fill" id="clr_<?= $key ?>_fill"></span>
            </button>
            <input type="text" id="clr_<?= $key ?>_hex" name="<?= $key ?>"
                   value="<?= htmlspecialchars($val) ?>"
                   placeholder="<?= $info['default'] ?>"
                   maxlength="7"
                   class="clr-hex-input"
                   style="background:#1e293b;color:#e2e8f0;border-color:#475569"
                   oninput="clrHexTyped('<?= $key ?>')">
            <input type="hidden" id="clr_<?= $key ?>_opacity" name="<?= $key ?>_opacity" value="<?= $opVal ?>">
            <span class="clr-opacity-badge" id="clr_<?= $key ?>_opacity_val" style="background:#334155;color:#cbd5e1"><?= $opVal ?>%</span>
            <button type="button" class="clr-reset-btn" onclick="clrReset('<?= $key ?>')" title="Reset" style="border-color:#475569;color:#94a3b8">
                <i class="fa-solid fa-rotate-left" style="font-size:9px;"></i>
            </button>
        </div>
    </div>
    <?php
}
?>

<form method="POST" action="/admin/appearance">
    <?= Router::csrfField() ?>
    <input type="hidden" name="_tab" value="appearance">
    <input type="hidden" name="_sub" value="colors">

    
    <div class="bg-white rounded-lg shadow-sm border border-gray-200 mb-6" id="tp-darkmode">
        <div class="px-5 py-3.5 flex items-center justify-between flex-wrap gap-4">
            <div class="flex items-center gap-3">
                <span class="text-gray-400"><i class="fa-solid fa-circle-half-stroke"></i></span>
                <div>
                    <h3 class="text-sm font-semibold text-gray-900">Dark Mode</h3>
                    <p class="text-xs text-gray-500 mt-0.5">Enable a dark theme and choose what visitors see first. The Light / Dark palettes below apply to each theme.</p>
                </div>
            </div>
            <div class="flex items-center gap-6 flex-wrap">
                <label class="flex items-center gap-2.5 cursor-pointer">
                    <div class="relative">
                        <input type="checkbox" name="hentai_dark_mode_enabled" value="1" <?= $dmEnabled ? 'checked' : '' ?> class="sr-only peer" id="dmToggle">
                        <div class="w-9 h-5 bg-gray-300 rounded-full peer-checked:bg-primary-600 transition-colors"></div>
                        <div class="absolute left-0.5 top-0.5 w-4 h-4 bg-white rounded-full shadow transition-transform peer-checked:translate-x-4"></div>
                    </div>
                    <span class="text-xs text-gray-600">User toggle</span>
                </label>
                <div class="flex items-center gap-2">
                    <span class="text-xs text-gray-500" id="dmDefaultLabel">Default:</span>
                    <div class="flex rounded-md border border-gray-200 overflow-hidden">
                        <label class="cursor-pointer">
                            <input type="radio" name="hentai_dark_mode_default" value="light" class="sr-only peer" <?= $dmDefault === 'light' ? 'checked' : '' ?>>
                            <div class="px-3 py-1.5 text-xs font-medium transition-all peer-checked:bg-primary-600 peer-checked:text-white bg-white text-gray-600 hover:bg-gray-50 flex items-center gap-1.5">
                                <i class="fa-regular fa-sun" style="font-size:11px;"></i> Light
                            </div>
                        </label>
                        <label class="cursor-pointer border-l border-gray-200">
                            <input type="radio" name="hentai_dark_mode_default" value="dark" class="sr-only peer" <?= $dmDefault === 'dark' ? 'checked' : '' ?>>
                            <div class="px-3 py-1.5 text-xs font-medium transition-all peer-checked:bg-primary-600 peer-checked:text-white bg-white text-gray-600 hover:bg-gray-50 flex items-center gap-1.5">
                                <i class="fa-regular fa-moon" style="font-size:11px;"></i> Dark
                            </div>
                        </label>
                    </div>
                </div>
            </div>
        </div>
        <p id="dmNote" style="margin:0;padding:8px 20px;font-size:11px;color:#9ca3af;border-top:1px solid #f3f4f6;display:none;align-items:center;gap:6px;flex-wrap:wrap"><i class="fa-solid fa-circle-info" style="font-size:10px"></i> <span id="dmNoteText"></span></p>
    </div>

    
    <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">

        
        <div id="clrLightCard" class="bg-white rounded-lg shadow-sm border border-gray-200<?php if (!$lightNeeded): ?> clr-card--disabled<?php endif; ?>">
            <div class="clr-disabled-banner"<?php if ($lightNeeded): ?> style="display:none"<?php endif; ?>><i class="fa-solid fa-circle-info" style="font-size:10px"></i> This palette isn't used with your current Dark Mode setting. <a href="#tp-darkmode" class="clr-activate-link">Adjust above</a></div>
            <div class="px-5 py-3 border-b border-gray-100">
                <div class="flex items-center gap-2.5">
                    <span class="flex items-center justify-center w-7 h-7 rounded-full bg-amber-50 text-amber-500">
                        <i class="fa-solid fa-sun text-xs"></i>
                    </span>
                    <h3 class="text-sm font-semibold text-gray-800">Light Theme</h3>
                </div>
            </div>
            <div class="px-5 pt-3 pb-1">
                <div class="clr-preview" id="clrPreviewLight">
                    <?php foreach ($lightColors as $key => $info): if ($key === 'color_primary' || str_starts_with($key, 'color_bg') || str_starts_with($key, 'color_text') || $key === 'color_border'): ?>
                    <div class="clr-preview__slab" id="clr_<?= $key ?>_preview" title="<?= $info['label'] ?>"></div>
                    <?php endif; endforeach; ?>
                </div>
            </div>
            <div class="px-5 pb-5 pt-3 grid grid-cols-2 gap-x-4 gap-y-3">
                <?php foreach ($lightColors as $key => $info): ?>
                    <?php renderColorField($key, $info, $settings); ?>
                <?php endforeach; ?>
            </div>
        </div>

        
        <div id="clrDarkCard" class="bg-gray-900 rounded-lg shadow-sm border border-gray-700<?php if (!$darkNeeded): ?> clr-card--disabled<?php endif; ?>">
            <div class="clr-disabled-banner clr-disabled-banner--dark"<?php if ($darkNeeded): ?> style="display:none"<?php endif; ?>><i class="fa-solid fa-circle-info" style="font-size:10px"></i> This palette isn't used with your current Dark Mode setting. <a href="#tp-darkmode" class="clr-activate-link">Adjust above</a></div>
            <div class="px-5 py-3 border-b border-gray-700/50">
                <div class="flex items-center gap-2.5">
                    <span class="flex items-center justify-center w-7 h-7 rounded-full bg-indigo-500/10 text-indigo-400">
                        <i class="fa-solid fa-moon text-xs"></i>
                    </span>
                    <h3 class="text-sm font-semibold text-gray-100">Dark Theme</h3>
                </div>
            </div>
            <div class="px-5 pt-3 pb-1">
                <div class="clr-preview" id="clrPreviewDark" style="border-color:#334155">
                    <?php foreach ($darkColors as $key => $info): if ($key === 'dk_color_primary' || str_starts_with($key, 'dk_color_bg') || str_starts_with($key, 'dk_color_text') || $key === 'dk_color_border'): ?>
                    <div class="clr-preview__slab" id="clr_<?= $key ?>_preview" title="<?= $info['label'] ?>"></div>
                    <?php endif; endforeach; ?>
                </div>
            </div>
            <div class="px-5 pb-5 pt-3 grid grid-cols-2 gap-x-4 gap-y-3">
                <?php foreach ($darkColors as $key => $info): ?>
                    <?php renderDarkColorField($key, $info, $settings); ?>
                <?php endforeach; ?>
            </div>
        </div>
    </div>

    <div>
        <button type="submit" class="inline-flex items-center px-5 py-2.5 bg-primary-600 text-white text-sm font-medium rounded-lg hover:bg-primary-700 transition-colors shadow-sm">
            <i class="fa-solid fa-check" style="margin-right:6px;font-size:12px;"></i> Save changes
        </button>
    </div>
</form>


<div class="clr-picker" id="clrPicker">
    <div class="clr-picker__sv-wrap" id="clrSvWrap">
        <canvas id="clrSvCanvas" width="232" height="150"></canvas>
        <div class="clr-picker__sv-cursor" id="clrCursor"></div>
    </div>
    <div class="clr-picker__row">
        <span class="clr-picker__label">H</span>
        <input type="range" class="clr-picker__hue" id="clrHue" min="0" max="360" step="1" value="0">
    </div>
    <div class="clr-picker__row">
        <span class="clr-picker__label">A</span>
        <div class="clr-picker__alpha-track">
            <div class="clr-picker__alpha-fill" id="clrAlphaFill"></div>
            <input type="range" class="clr-picker__alpha" id="clrAlpha" min="0" max="100" step="1" value="100">
        </div>
        <span class="clr-picker__alpha-val" id="clrAlphaVal">100%</span>
    </div>
    <div class="clr-picker__hex-row">
        <span class="clr-picker__label">#</span>
        <input type="text" class="clr-picker__hex-input" id="clrHexIn" maxlength="7" placeholder="#000000">
        <button type="button" class="clr-picker__default" id="clrDefaultBtn" onclick="clrSetDefault()">Default</button>
    </div>
</div>

<script>
(function() {
    
    function hexToRgb(hex) {
        var h = hex.replace('#','');
        if (h.length === 3) h = h[0]+h[0]+h[1]+h[1]+h[2]+h[2];
        return [parseInt(h.substr(0,2),16), parseInt(h.substr(2,2),16), parseInt(h.substr(4,2),16)];
    }
    function rgbToHex(r, g, b) {
        return '#' + ((1<<24)+(r<<16)+(g<<8)+b).toString(16).slice(1);
    }
    function hsvToRgb(h, s, v) {
        var i = Math.floor(h/60)%6, f = h/60-Math.floor(h/60);
        var p = v*(1-s), q = v*(1-f*s), t = v*(1-(1-f)*s);
        var r, g, b;
        switch(i) {
            case 0: r=v;g=t;b=p;break; case 1: r=q;g=v;b=p;break;
            case 2: r=p;g=v;b=t;break; case 3: r=p;g=q;b=v;break;
            case 4: r=t;g=p;b=v;break; default: r=v;g=p;b=q;
        }
        return [Math.round(r*255), Math.round(g*255), Math.round(b*255)];
    }
    function rgbToHsv(r, g, b) {
        r/=255; g/=255; b/=255;
        var mx = Math.max(r,g,b), mn = Math.min(r,g,b), d = mx-mn;
        var h = 0, s = mx === 0 ? 0 : d/mx, v = mx;
        if (d !== 0) {
            if (mx === r) h = ((g-b)/d + 6) % 6;
            else if (mx === g) h = (b-r)/d + 2;
            else h = (r-g)/d + 4;
            h *= 60;
        }
        return [h, s, v];
    }

    
    var pk = { key: null, h: 0, s: 0, v: 1, alpha: 100, dragging: false };
    var pkEl = document.getElementById('clrPicker');
    var pkCanvas = document.getElementById('clrSvCanvas');
    var pkCtx = pkCanvas.getContext('2d');
    var pkCursor = document.getElementById('clrCursor');
    var pkHue = document.getElementById('clrHue');
    var pkAlphaSlider = document.getElementById('clrAlpha');
    var pkAlphaFill = document.getElementById('clrAlphaFill');
    var pkAlphaVal = document.getElementById('clrAlphaVal');
    var pkHexIn = document.getElementById('clrHexIn');
    var pkDefBtn = document.getElementById('clrDefaultBtn');

    function pkDrawSV() {
        var w = pkCanvas.width, h = pkCanvas.height;
        var rgb = hsvToRgb(pk.h, 1, 1);
        pkCtx.fillStyle = 'rgb('+rgb[0]+','+rgb[1]+','+rgb[2]+')';
        pkCtx.fillRect(0, 0, w, h);
        var wGrad = pkCtx.createLinearGradient(0, 0, w, 0);
        wGrad.addColorStop(0, 'rgba(255,255,255,1)');
        wGrad.addColorStop(1, 'rgba(255,255,255,0)');
        pkCtx.fillStyle = wGrad;
        pkCtx.fillRect(0, 0, w, h);
        var bGrad = pkCtx.createLinearGradient(0, 0, 0, h);
        bGrad.addColorStop(0, 'rgba(0,0,0,0)');
        bGrad.addColorStop(1, 'rgba(0,0,0,1)');
        pkCtx.fillStyle = bGrad;
        pkCtx.fillRect(0, 0, w, h);
    }

    function pkPositionCursor() {
        pkCursor.style.left = (pk.s * 100) + '%';
        pkCursor.style.top = ((1 - pk.v) * 100) + '%';
    }

    function pkSVPick(e) {
        var rect = pkCanvas.getBoundingClientRect();
        var clientX = e.touches ? e.touches[0].clientX : e.clientX;
        var clientY = e.touches ? e.touches[0].clientY : e.clientY;
        var x = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
        var y = Math.max(0, Math.min(1, (clientY - rect.top) / rect.height));
        pk.s = x;
        pk.v = 1 - y;
        pkPositionCursor();
        syncFromHSV();
    }

    function syncFromHSV() {
        if (!pk.key) return;
        var rgb = hsvToRgb(pk.h, pk.s, pk.v);
        var hex = rgbToHex(rgb[0], rgb[1], rgb[2]);
        document.getElementById('clr_' + pk.key + '_hex').value = hex;
        document.getElementById('clr_' + pk.key + '_opacity').value = pk.alpha;
        pkHexIn.value = hex;
        pkAlphaSlider.value = pk.alpha;
        pkAlphaVal.textContent = pk.alpha + '%';
        pkAlphaFill.style.background = 'linear-gradient(to right, rgba('+rgb[0]+','+rgb[1]+','+rgb[2]+',0), rgb('+rgb[0]+','+rgb[1]+','+rgb[2]+'))';
        document.getElementById('clr_' + pk.key + '_opacity_val').textContent = pk.alpha + '%';
        updateSwatch(pk.key);
        updatePreview(pk.key);
    }

    function updateSwatch(key) {
        var hex = document.getElementById('clr_' + key + '_hex').value;
        var op = document.getElementById('clr_' + key + '_opacity').value;
        var fill = document.getElementById('clr_' + key + '_fill');
        var swatch = document.getElementById('clr_' + key + '_swatch');
        var displayHex = hex || swatch.dataset.default;
        var c = hexToRgb(displayHex);
        fill.style.background = 'rgba('+c[0]+','+c[1]+','+c[2]+','+(op/100)+')';
    }

    function updatePreview(key) {
        var prev = document.getElementById('clr_' + key + '_preview');
        if (!prev) return;
        var hex = document.getElementById('clr_' + key + '_hex').value;
        var swatch = document.getElementById('clr_' + key + '_swatch');
        prev.style.background = hex || swatch.dataset.default;
    }

    
    window.clrOpen = function(key) {
        if (pk.key === key && pkEl.classList.contains('open')) { clrClose(); return; }
        pk.key = key;
        var input = document.getElementById('clr_' + key + '_hex');
        var swatch = document.getElementById('clr_' + key + '_swatch');
        var hex = input.value || swatch.dataset.default;
        pk.alpha = parseInt(document.getElementById('clr_' + key + '_opacity').value) || 100;
        var rgb = hexToRgb(hex);
        var hsv = rgbToHsv(rgb[0], rgb[1], rgb[2]);
        pk.h = hsv[0]; pk.s = hsv[1]; pk.v = hsv[2];
        var block = document.getElementById('clr_' + key + '_block');
        if (pkEl.parentNode !== block) block.appendChild(pkEl);
        pkHue.value = Math.round(pk.h);
        pkAlphaSlider.value = pk.alpha;
        pkAlphaVal.textContent = pk.alpha + '%';
        pkHexIn.value = hex;
        pkDefBtn.textContent = swatch.dataset.default;
        pkDrawSV();
        pkPositionCursor();
        var rgbCur = hsvToRgb(pk.h, pk.s, pk.v);
        pkAlphaFill.style.background = 'linear-gradient(to right, rgba('+rgbCur[0]+','+rgbCur[1]+','+rgbCur[2]+',0), rgb('+rgbCur[0]+','+rgbCur[1]+','+rgbCur[2]+'))';
        pkEl.classList.add('open');
    };

    function clrClose() {
        pkEl.classList.remove('open');
        pk.key = null;
    }

    
    pkCanvas.addEventListener('mousedown', function(e) { e.preventDefault(); pk.dragging = true; pkSVPick(e); });
    document.addEventListener('mousemove', function(e) { if (pk.dragging) pkSVPick(e); });
    document.addEventListener('mouseup', function() { pk.dragging = false; });
    pkCanvas.addEventListener('touchstart', function(e) { e.preventDefault(); pk.dragging = true; pkSVPick(e); }, {passive:false});
    document.addEventListener('touchmove', function(e) { if (pk.dragging) pkSVPick(e); });
    document.addEventListener('touchend', function() { pk.dragging = false; });

    pkHue.addEventListener('input', function() {
        pk.h = parseInt(this.value);
        pkDrawSV();
        syncFromHSV();
    });

    pkAlphaSlider.addEventListener('input', function() {
        pk.alpha = parseInt(this.value);
        syncFromHSV();
    });

    pkHexIn.addEventListener('input', function() {
        var val = this.value.trim();
        if (!val.startsWith('#')) val = '#' + val;
        if (val.match(/^#[0-9a-fA-F]{6}$/)) {
            var rgb = hexToRgb(val);
            var hsv = rgbToHsv(rgb[0], rgb[1], rgb[2]);
            pk.h = hsv[0]; pk.s = hsv[1]; pk.v = hsv[2];
            pkHue.value = Math.round(pk.h);
            pkDrawSV();
            pkPositionCursor();
            syncFromHSV();
        }
    });

    window.clrSetDefault = function() {
        if (!pk.key) return;
        var swatch = document.getElementById('clr_' + pk.key + '_swatch');
        var def = swatch.dataset.default;
        document.getElementById('clr_' + pk.key + '_hex').value = '';
        document.getElementById('clr_' + pk.key + '_opacity').value = 100;
        document.getElementById('clr_' + pk.key + '_opacity_val').textContent = '100%';
        pk.alpha = 100;
        pkHexIn.value = def;
        pkAlphaSlider.value = 100;
        pkAlphaVal.textContent = '100%';
        var rgb = hexToRgb(def);
        var hsv = rgbToHsv(rgb[0], rgb[1], rgb[2]);
        pk.h = hsv[0]; pk.s = hsv[1]; pk.v = hsv[2];
        pkHue.value = Math.round(pk.h);
        pkDrawSV();
        pkPositionCursor();
        pkAlphaFill.style.background = 'linear-gradient(to right, rgba('+rgb[0]+','+rgb[1]+','+rgb[2]+',0), rgb('+rgb[0]+','+rgb[1]+','+rgb[2]+'))';
        updateSwatch(pk.key);
        updatePreview(pk.key);
    };

    window.clrReset = function(key) {
        document.getElementById('clr_' + key + '_hex').value = '';
        document.getElementById('clr_' + key + '_opacity').value = 100;
        document.getElementById('clr_' + key + '_opacity_val').textContent = '100%';
        updateSwatch(key);
        updatePreview(key);
        if (pk.key === key) clrClose();
    };

    window.clrHexTyped = function(key) {
        var hex = document.getElementById('clr_' + key + '_hex').value;
        if (hex.match(/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/)) {
            updateSwatch(key);
            updatePreview(key);
            if (pk.key === key && pkEl.classList.contains('open')) {
                var full = hex.length === 4 ? '#'+hex[1]+hex[1]+hex[2]+hex[2]+hex[3]+hex[3] : hex;
                var rgb = hexToRgb(full);
                var hsv = rgbToHsv(rgb[0], rgb[1], rgb[2]);
                pk.h = hsv[0]; pk.s = hsv[1]; pk.v = hsv[2];
                pkHue.value = Math.round(pk.h);
                pkHexIn.value = full;
                pkDrawSV();
                pkPositionCursor();
            }
        }
    };

    
    document.addEventListener('mousedown', function(e) {
        if (!pkEl.classList.contains('open')) return;
        if (pkEl.contains(e.target)) return;
        if (e.target.closest && e.target.closest('.clr-color-swatch')) return;
        clrClose();
    });
    document.addEventListener('keydown', function(e) {
        if (e.key === 'Escape' && pkEl.classList.contains('open')) clrClose();
    });

    
    <?php foreach ($allColors as $key => $info): ?>
    updateSwatch('<?= $key ?>');
    updatePreview('<?= $key ?>');
    <?php endforeach; ?>
})();
</script>

<script>
(function() {
    var dmToggle = document.getElementById('dmToggle');
    if (!dmToggle) return;
    var dmNote = document.getElementById('dmNote');
    var dmNoteText = document.getElementById('dmNoteText');
    var dmLabel = document.getElementById('dmDefaultLabel');
    var lightCard = document.getElementById('clrLightCard');
    var darkCard = document.getElementById('clrDarkCard');

    function setCard(card, disabled) {
        if (!card) return;
        card.classList.toggle('clr-card--disabled', disabled);
        var banner = card.querySelector('.clr-disabled-banner');
        if (banner) banner.style.display = disabled ? '' : 'none';
    }

    function dmUpdate() {
        var enabled = dmToggle.checked;
        var defRadio = document.querySelector('input[name="hentai_dark_mode_default"]:checked');
        var def = defRadio ? defRadio.value : 'light';
        var lightNeeded = enabled || def === 'light';
        var darkNeeded = enabled || def === 'dark';
        setCard(lightCard, !lightNeeded);
        setCard(darkCard, !darkNeeded);
        if (enabled) {
            dmLabel.textContent = 'Default:';
            if (dmNote) dmNote.style.display = 'none';
        } else {
            dmLabel.textContent = 'Theme:';
            var themeName = def === 'dark' ? 'Dark' : 'Light';
            var unusedName = def === 'dark' ? 'Light' : 'Dark';
            if (dmNoteText) dmNoteText.textContent = 'User toggle is off — the site always uses the ' + themeName + ' theme, so the ' + unusedName + ' palette below is disabled.';
            if (dmNote) dmNote.style.display = 'flex';
        }
    }

    dmToggle.addEventListener('change', dmUpdate);
    document.querySelectorAll('input[name="hentai_dark_mode_default"]').forEach(function(r) {
        r.addEventListener('change', dmUpdate);
    });
    dmUpdate();
})();
</script>
