import React, { useEffect, useState } from 'react';
import { getBlockType } from './engine/BlockTypes';
import { getModelType } from './engine/ModelTypes';
import { getPrimitiveType } from './engine/PrimitiveTypes';
import Icon from './Icon';
import cl from './InspectorPanel.module.css';

/**
 * True если nodeId является (косвенным) потомком candidateAncestorId
 * в дереве GUI-элементов. Защищает от циклов в выпадашке «Родитель».
 */
function _isAncestorOf(guiList, candidateAncestorId, nodeId) {
    let cur = guiList.find(g => g.id === nodeId);
    let safety = 0;
    while (cur && cur.parentId && safety++ < 100) {
        if (cur.parentId === candidateAncestorId) return true;
        cur = guiList.find(g => g.id === cur.parentId);
    }
    return false;
}

/**
 * AssetPicker — выбор картинки из библиотеки проекта + загрузка новой.
 * Используется для текстуры примитива и для image-GUI.
 *
 * Props:
 *   assetList    — [{id, name, dataUrl}] библиотека картинок проекта
 *   value        — id выбранного ассета (или null)
 *   onPick(id)   — выбрана картинка (id или null чтобы снять)
 *   onUpload(file) → Promise<{ok, id?, error?}> — загрузить файл
 *   onRemove(id) — удалить картинку из библиотеки
 */
function AssetPicker({ assetList = [], value, onPick, onUpload, onRemove }) {
    const fileRef = React.useRef(null);
    const [error, setError] = useState('');
    const [busy, setBusy] = useState(false);

    const handleFile = async (e) => {
        const file = e.target.files && e.target.files[0];
        e.target.value = '';            // позволяем выбрать тот же файл повторно
        if (!file || !onUpload) return;
        setError('');
        setBusy(true);
        const res = await onUpload(file);
        setBusy(false);
        if (res && res.ok) {
            onPick?.(res.id);             // сразу применяем загруженную картинку
        } else {
            setError((res && res.error) || 'Не удалось загрузить');
        }
    };

    return (
        <div>
            <input
                ref={fileRef}
                type="file"
                accept="image/png,image/jpeg,image/webp,image/gif"
                style={{ display: 'none' }}
                onChange={handleFile}
            />
            {/* Сетка превью картинок библиотеки */}
            <div style={{
                display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 4,
                marginBottom: 6,
            }}>
                {/* Кнопка «нет картинки» */}
                <button
                    type="button"
                    title="Без картинки"
                    onClick={() => onPick?.(null)}
                    style={{
                        aspectRatio: '1', borderRadius: 4, cursor: 'pointer',
                        border: !value ? '2px solid var(--accent)' : '1px solid var(--border)',
                        background: 'var(--bg-light)', color: 'var(--text-dim)',
                        fontSize: 16, display: 'flex', alignItems: 'center', justifyContent: 'center',
                    }}
                >∅</button>
                {assetList.map(a => (
                    <div key={a.id} style={{ position: 'relative' }}>
                        <button
                            type="button"
                            title={a.name}
                            onClick={() => onPick?.(a.id)}
                            style={{
                                width: '100%', aspectRatio: '1', borderRadius: 4, cursor: 'pointer',
                                border: value === a.id ? '2px solid var(--accent)' : '1px solid var(--border, #4a3a2a)',
                                background: '#0008', padding: 0, overflow: 'hidden',
                            }}
                        >
                            <img
                                src={a.dataUrl}
                                alt={a.name}
                                style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
                            />
                        </button>
                        {onRemove && (
                            <button
                                type="button"
                                title="Удалить картинку из проекта"
                                onClick={(e) => {
                                    e.stopPropagation();
                                    if (window.confirm(`Удалить картинку «${a.name}»? Она пропадёт со всех объектов.`)) {
                                        onRemove(a.id);
                                    }
                                }}
                                style={{
                                    position: 'absolute', top: -4, right: -4,
                                    width: 16, height: 16, borderRadius: 8,
                                    border: 'none', background: '#c0392b', color: '#fff',
                                    fontSize: 10, lineHeight: '16px', cursor: 'pointer', padding: 0,
                                }}
                            >×</button>
                        )}
                    </div>
                ))}
            </div>
            <button
                type="button"
                onClick={() => fileRef.current?.click()}
                disabled={busy}
                style={{
                    width: '100%', padding: '6px 8px', borderRadius: 4,
                    border: '1px dashed var(--accent)', background: 'transparent',
                    color: 'var(--accent)', cursor: busy ? 'wait' : 'pointer', fontSize: 12,
                }}
            >
                {busy ? 'Загрузка…' : '+ Загрузить картинку'}
            </button>
            {error && (
                <div style={{ color: '#e07a5a', fontSize: 11, marginTop: 4 }}>{error}</div>
            )}
        </div>
    );
}

/**
 * GameplayInspector — настройки враг/спавнер из data.gameplay модели.
 * Меняет данные через onSetModelProps({ gameplayParams: {...} }).
 */
function GameplayInspector({ selection, onSetModelProps, onAddWeaponToInventory }) {
    const gp = selection.gameplay;
    if (!gp) return null;
    const defaults = gp.defaultParams || {};
    const current = selection.gameplayParams || {};
    const merged = { ...defaults, ...current };

    const setParam = (key, value) => {
        const next = { ...merged, [key]: value };
        onSetModelProps?.({ gameplayParams: next });
    };

    const numberInput = (label, key, opts = {}) => {
        const val = merged[key];
        return (
            <label style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                <span style={{ fontSize: 11, opacity: 0.75 }}>
                    {label}
                    {opts.unit && <span style={{ opacity: 0.5 }}> ({opts.unit})</span>}
                </span>
                <input
                    type="number"
                    value={val ?? ''}
                    onChange={(e) => {
                        const v = e.target.value === '' ? defaults[key] : parseFloat(e.target.value);
                        if (Number.isFinite(v)) setParam(key, v);
                    }}
                    min={opts.min}
                    max={opts.max}
                    step={opts.step ?? 1}
                    className={cl.numInput}
                />
            </label>
        );
    };

    return (
        <div className={cl.section}>
            <div className={cl.sectionTitle}>
                {gp.isZombie ? <><Icon name="zombie" size={12} /> Параметры врага</>
                 : gp.isZombieSpawner ? <><Icon name="spawner" size={12} /> Параметры спавнера</>
                 : gp.isWeapon ? (gp.weaponKind === 'melee'
                    ? <><Icon name="sword" size={12} /> Параметры оружия</>
                    : <><Icon name="crosshair" size={12} /> Параметры оружия</>)
                 : <><Icon name="settings" size={12} /> Параметры</>}
            </div>
            <div style={{
                fontSize: 11, color: 'var(--text-dim)', fontStyle: 'italic',
                marginBottom: 8, lineHeight: 1.4,
            }}>
                {gp.description}
            </div>

            {gp.isZombie && (
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6 }}>
                    {numberInput('Жизни', 'hp', { min: 1, max: 9999 })}
                    {numberInput('Урон', 'attackDamage', { min: 0, max: 999 })}
                    {numberInput('Скорость', 'speed', { min: 0.1, max: 20, step: 0.1, unit: 'м/с' })}
                    {numberInput('Скорость пат.', 'wanderSpeed', { min: 0.1, max: 20, step: 0.1, unit: 'м/с' })}
                    {numberInput('Радиус обнар.', 'detectionRadius', { min: 1, max: 100, unit: 'м' })}
                    {numberInput('Дистанция атаки', 'attackRange', { min: 0.5, max: 20, step: 0.1, unit: 'м' })}
                    {numberInput('Кулдаун атаки', 'attackCooldown', { min: 0.1, max: 10, step: 0.1, unit: 'с' })}
                    {numberInput('Радиус патруля', 'wanderRadius', { min: 1, max: 100, unit: 'м' })}
                </div>
            )}

            {gp.isZombieSpawner && (
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6 }}>
                    {numberInput('Лимит живых', 'maxAlive', { min: 1, max: 100 })}
                    {numberInput('Интервал', 'spawnInterval', { min: 0.5, max: 600, step: 0.5, unit: 'с' })}
                    {numberInput('Радиус спавна', 'radius', { min: 1, max: 100, unit: 'м' })}
                    {numberInput('HP зомби', 'zombieHp', { min: 1, max: 9999 })}
                    {numberInput('Скорость зомби', 'zombieSpeed', { min: 0.1, max: 20, step: 0.1, unit: 'м/с' })}
                    {numberInput('Урон зомби', 'zombieDamage', { min: 0, max: 999 })}
                </div>
            )}

            {gp.isWeapon && (
                <>
                    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6 }}>
                        {numberInput('Урон', 'damage', { min: 0, max: 9999 })}
                        {gp.weaponKind === 'melee' ? (
                            <>
                                {numberInput('Кулдаун', 'fireRate', { min: 0.05, max: 5, step: 0.05, unit: 'с' })}
                                {numberInput('Дистанция', 'range', { min: 0.5, max: 10, step: 0.1, unit: 'м' })}
                                {numberInput('Угол атаки', 'meleeArc', { min: 0.1, max: 3.14, step: 0.1, unit: 'рад' })}
                            </>
                        ) : (
                            <>
                                {numberInput('Скорострел.', 'fireRate', { min: 0.05, max: 5, step: 0.05, unit: 'с' })}
                                {numberInput('Дальность', 'range', { min: 5, max: 500, unit: 'м' })}
                                {numberInput('Магазин', 'magazine', { min: 1, max: 999 })}
                                {numberInput('Запас', 'reserve', { min: 0, max: 9999 })}
                                {numberInput('Перезарядка', 'reloadTime', { min: 0.1, max: 10, step: 0.1, unit: 'с' })}
                            </>
                        )}
                    </div>
                    <button
                        onClick={() => onAddWeaponToInventory?.(selection.modelTypeId, merged)}
                        className={cl.smallBtn}
                        style={{
                            marginTop: 10,
                            width: '100%',
                            padding: '8px',
                            background: 'rgba(102, 176, 74, 0.18)',
                            color: '#7bb84e',
                            border: '1px solid #5a8c3e',
                            borderRadius: 4,
                            fontWeight: 600,
                            cursor: 'pointer',
                        }}
                    >
                        <Icon name="add" size={13} /> Добавить в инвентарь игрока
                    </button>
                </>
            )}

            <div style={{ marginTop: 8, fontSize: 10, color: 'var(--text-dim)', fontStyle: 'italic' }}>
                Изменения вступают в силу после старта игры (<Icon name="play" size={12} />).
            </div>
        </div>
    );
}

const PRIMITIVE_MATERIALS = [
    { id: 'matte', name: 'Матовый' },
    { id: 'metal', name: 'Металл' },
    { id: 'glass', name: 'Стекло' },
    { id: 'neon',  name: 'Неон' },
    { id: 'studs', name: 'Studs' },   // задача 09 — лего-кружки (любой цвет)
];

/** Форматирование массы — без хвоста из десятичных. Целые без запятой. */
function formatMass(m) {
    const n = Number(m) || 1;
    if (Math.abs(n - Math.round(n)) < 0.01) return String(Math.round(n));
    return n.toFixed(2);
}

/**
 * Inspector — свойства выделенного объекта.
 * Поддерживает редактирование позиции, поворота, масштаба, удаление.
 *
 * Props:
 *   selection — { type:'block'|'model', ... } | null
 *   onMoveTo(x, y, z)
 *   onRotateTo(angleRad)
 *   onScaleTo(scale)
 *   onDelete()
 *   onFocus
 */
const InspectorPanel = ({
    selection, onMoveTo, onRotateTo, onScaleTo, onDelete, onFocus,
    onResizePrimitive, onSetPrimitiveProps,
    onSetAnchored, onSetMass, onSetModelProps, onSetBlockProps,
    onSetLightingProps, onSetSoundProps, onSetPlayerProps, onSetFloorProps, onSetGuiProps, onDeleteGui,
    onAddWeaponToInventory,
    onEditBillboard,
    guiElements = [],
    // Этап 3.6 — библиотека пользовательских картинок.
    assetList = [],
    onUploadAsset,
    onRemoveAsset,
}) => {
    const props = {
        onSetLightingProps, onSetSoundProps, onSetPlayerProps, onSetFloorProps,
        onSetGuiProps, onDeleteGui, onAddWeaponToInventory,
    };
    const [localX, setLocalX] = useState('');
    const [localY, setLocalY] = useState('');
    const [localZ, setLocalZ] = useState('');
    const [localRot, setLocalRot] = useState('');
    const [localScale, setLocalScale] = useState('');
    // Для примитивов — отдельные размеры по осям и свойства
    const [localSx, setLocalSx] = useState('');
    const [localSy, setLocalSy] = useState('');
    const [localSz, setLocalSz] = useState('');
    const [localColor, setLocalColor] = useState('#888888');
    const [localMaterial, setLocalMaterial] = useState('matte');
    const [localStudDensity, setLocalStudDensity] = useState(1);   // плотность studs
    // Подпись над объектом (задача 10).
    const [localLabel, setLocalLabel] = useState(null);   // { enabled, binding, params, preset, height }
    const [localCanCollide, setLocalCanCollide] = useState(true);
    const [localVisible, setLocalVisible] = useState(true);
    const [localAnchored, setLocalAnchored] = useState(true);
    const [localMass, setLocalMass] = useState('1');
    const [localOpacity, setLocalOpacity] = useState(1);
    const [localTint, setLocalTint] = useState('');
    const [localBrightness, setLocalBrightness] = useState(1.5);
    const [localRange, setLocalRange] = useState(12);

    // Синхронизируем локальное состояние когда меняется selection
    useEffect(() => {
        if (!selection) return;
        if (selection.type === 'block') {
            setLocalX(String(selection.gridX));
            setLocalY(String(selection.gridY));
            setLocalZ(String(selection.gridZ));
            setLocalAnchored(selection.anchored !== false);
            setLocalMass(formatMass(selection.mass ?? 1));
            setLocalCanCollide(selection.canCollide !== false);
            setLocalVisible(selection.visible !== false);
        } else if (selection.type === 'model' || selection.type === 'userModel') {
            setLocalX(selection.x.toFixed(2));
            setLocalY(selection.y.toFixed(2));
            setLocalZ(selection.z.toFixed(2));
            setLocalRot(((selection.rotationY || 0) * 180 / Math.PI).toFixed(0));
            setLocalScale((selection.scale || 1).toFixed(2));
            setLocalAnchored(selection.anchored !== false);
            setLocalMass(formatMass(selection.mass ?? 1));
            setLocalCanCollide(selection.canCollide !== false);
            setLocalVisible(selection.visible !== false);
            setLocalOpacity(typeof selection.opacity === 'number' ? selection.opacity : 1);
            setLocalTint(selection.tint || '');
        } else if (selection.type === 'spawn') {
            setLocalX(selection.x.toFixed(2));
            setLocalY(selection.y.toFixed(2));
            setLocalZ(selection.z.toFixed(2));
        } else if (selection.type === 'primitive') {
            setLocalX(selection.x.toFixed(2));
            setLocalY(selection.y.toFixed(2));
            setLocalZ(selection.z.toFixed(2));
            setLocalSx((selection.sx || 1).toFixed(2));
            setLocalSy((selection.sy || 1).toFixed(2));
            setLocalSz((selection.sz || 1).toFixed(2));
            setLocalColor(selection.color || '#888888');
            setLocalMaterial(selection.material || 'matte');
            setLocalStudDensity(selection.studDensity || 1);
            setLocalLabel(selection.label || null);
            setLocalCanCollide(selection.canCollide !== false);
            setLocalVisible(selection.visible !== false);
            setLocalAnchored(selection.anchored !== false);
            setLocalMass(formatMass(selection.mass ?? 1));
            // Параметры лампы
            setLocalBrightness(selection.brightness ?? 1.5);
            setLocalRange(selection.range ?? 12);
        }
    }, [selection]);

    if (!selection) {
        return (
            <div className={cl.empty}>
                Выберите объект чтобы увидеть его свойства
                <div className={cl.emptyHint} style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                    <Icon name="cursor" size={13} /> Инструмент «Выделить» + ЛКМ или клик в Иерархии
                </div>
            </div>
        );
    }

    const isBlock = selection.type === 'block';
    const isSpawn = selection.type === 'spawn';
    const isPrimitive = selection.type === 'primitive';
    const isUserModel = selection.type === 'userModel';
    // isModel включает и обычные GLB-модели и пользовательские voxel-модели —
    // у них одинаковый набор полей (position/rotation/scale/anchored/...).
    const isModel = selection.type === 'model' || isUserModel;
    const isLighting = selection.type === 'lighting';
    const isScript = selection.type === 'script';
    // Жидкие блоки (вода/лава) — у них нет свойств физики; они работают по
    // своим правилам (canCollide=false, плавание, и т.п.)
    const isLiquid = isBlock && (selection.blockTypeId === 'water' || selection.blockTypeId === 'lava');
    const blockType = isBlock ? getBlockType(selection.blockTypeId) : null;
    const modelType = isModel ? getModelType(selection.modelTypeId) : null;
    const primitiveType = isPrimitive ? getPrimitiveType(selection.primitiveType) : null;

    const commitResize = () => {
        const sx = parseFloat(localSx), sy = parseFloat(localSy), sz = parseFloat(localSz);
        if (Number.isFinite(sx) && Number.isFinite(sy) && Number.isFinite(sz)
            && sx > 0.05 && sy > 0.05 && sz > 0.05) {
            onResizePrimitive?.(sx, sy, sz);
        }
    };

    /** Применить введённые X/Y/Z. */
    const commitPosition = () => {
        const x = parseFloat(localX);
        const y = parseFloat(localY);
        const z = parseFloat(localZ);
        if (Number.isFinite(x) && Number.isFinite(y) && Number.isFinite(z)) {
            onMoveTo(x, y, z);
        }
    };

    const commitRotation = () => {
        const deg = parseFloat(localRot);
        if (Number.isFinite(deg)) {
            onRotateTo(deg * Math.PI / 180);
        }
    };

    const commitScale = () => {
        const s = parseFloat(localScale);
        if (Number.isFinite(s) && s > 0.01) {
            onScaleTo(s);
        }
    };

    // === Тип «lighting» — отдельный layout без позиции/физики ===
    if (isLighting) {
        return (
            <div className={cl.inspector}>
                <div className={cl.headerCard}>
                    <div className={cl.iconBig}><Icon name="sun" size={32} strokeWidth={1.8} /></div>
                    <div className={cl.headerText}>
                        <div className={cl.typeLabel}>Освещение</div>
                        <div className={cl.typeName}>Свет, время суток, туман, тени</div>
                    </div>
                </div>

                {/* Время суток */}
                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="clock" size={12} /> Время суток</div>
                    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 4, marginBottom: 8 }}>
                        {[
                            { id: 'day',    label: 'День',    iconName: 'sun'     },
                            { id: 'sunset', label: 'Закат',   iconName: 'sunset'  },
                            { id: 'night',  label: 'Ночь',    iconName: 'moon'    },
                            { id: 'dawn',   label: 'Рассвет', iconName: 'sunrise' },
                            { id: 'cycle',  label: 'Цикл',    iconName: 'cycle'   },
                        ].map(t => (
                            <button
                                key={t.id}
                                className={cl.smallBtn}
                                style={{
                                    background: (selection.envPreset || 'day') === t.id ? 'var(--accent-bright, #2E7D32)' : undefined,
                                    color: (selection.envPreset || 'day') === t.id ? '#fff' : undefined,
                                    fontSize: 11,
                                    display: 'inline-flex', alignItems: 'center', gap: 4, justifyContent: 'center',
                                }}
                                onClick={() => props.onSetLightingProps?.({ envPreset: t.id })}
                            >
                                <Icon name={t.iconName} size={12} /> {t.label}
                            </button>
                        ))}
                    </div>
                    {(selection.envPreset || 'day') === 'cycle' && (
                        <div style={{ display: 'grid', gridTemplateColumns: '1fr auto', gap: '6px 8px', alignItems: 'center', fontSize: 12 }}>
                            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}><Icon name="sun" size={12} /> День (мин):</span>
                            <input
                                type="number" min="0.5" step="0.5"
                                value={selection.dayDurationMin ?? 5}
                                onChange={(e) => props.onSetLightingProps?.({ dayDurationMin: parseFloat(e.target.value) || 0 })}
                                style={{ width: 60, padding: '4px 6px', background: '#0f0a05', border: '1px solid #5a4a3a', borderRadius: 3, color: '#f0e6d8' }}
                            />
                            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}><Icon name="moon" size={12} /> Ночь (мин):</span>
                            <input
                                type="number" min="0.5" step="0.5"
                                value={selection.nightDurationMin ?? 3}
                                onChange={(e) => props.onSetLightingProps?.({ nightDurationMin: parseFloat(e.target.value) || 0 })}
                                style={{ width: 60, padding: '4px 6px', background: '#0f0a05', border: '1px solid #5a4a3a', borderRadius: 3, color: '#f0e6d8' }}
                            />
                        </div>
                    )}
                </div>

                {/* Солнце */}
                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="sun" size={12} /> Солнце</div>
                    <div style={{ padding: '4px 0' }}>
                        <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 }}>
                            <span>Интенсивность</span>
                            <span style={{ opacity: 0.6 }}>{(selection.sunIntensity || 0.8).toFixed(2)}</span>
                        </div>
                        <input
                            type="range" min="0" max="2" step="0.05"
                            value={selection.sunIntensity ?? 0.8}
                            onChange={(e) => props.onSetLightingProps?.({ sunIntensity: parseFloat(e.target.value) })}
                            style={{ width: '100%' }}
                        />
                    </div>
                </div>

                {/* Окружающий свет */}
                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="cloud" size={12} /> Окружающий свет</div>
                    <div style={{ padding: '4px 0' }}>
                        <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 }}>
                            <span>Интенсивность</span>
                            <span style={{ opacity: 0.6 }}>{(selection.hemiIntensity || 0.65).toFixed(2)}</span>
                        </div>
                        <input
                            type="range" min="0" max="2" step="0.05"
                            value={selection.hemiIntensity ?? 0.65}
                            onChange={(e) => props.onSetLightingProps?.({ hemiIntensity: parseFloat(e.target.value) })}
                            style={{ width: '100%' }}
                        />
                    </div>
                    <div style={{ padding: '4px 0' }}>
                        <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 }}>
                            <span>Заливка теней</span>
                            <span style={{ opacity: 0.6 }}>{(selection.sceneAmbient ?? 0.3).toFixed(2)}</span>
                        </div>
                        <input
                            type="range" min="0" max="1" step="0.05"
                            value={selection.sceneAmbient ?? 0.3}
                            onChange={(e) => props.onSetLightingProps?.({ sceneAmbient: parseFloat(e.target.value) })}
                            style={{ width: '100%' }}
                        />
                        <div style={{ fontSize: 10, color: 'var(--text-dim)', marginTop: 2 }}>
                            Подсветка теней — цвет в затенённых гранях. 0 = чёрные тени, 1 = плоско.
                        </div>
                    </div>
                    <div style={{ fontSize: 11, color: 'var(--text-dim)', fontStyle: 'italic', marginTop: 4 }}>
                        <Icon name="sparkle" size={11} /> Цвет окружающего света подбирается автоматически по времени суток.
                    </div>
                </div>

                {/* Цветокоррекция */}
                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="sparkle" size={12} /> Цветокоррекция</div>
                    <div style={{ padding: '4px 0' }}>
                        <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 }}>
                            <span>Экспозиция</span>
                            <span style={{ opacity: 0.6 }}>{(selection.exposure ?? 1.0).toFixed(2)}</span>
                        </div>
                        <input
                            type="range" min="0.3" max="2" step="0.05"
                            value={selection.exposure ?? 1.0}
                            onChange={(e) => props.onSetLightingProps?.({ exposure: parseFloat(e.target.value) })}
                            style={{ width: '100%' }}
                        />
                        <div style={{ fontSize: 10, color: 'var(--text-dim)', marginTop: 2 }}>
                            Общая яркость. &lt;1 = темнее, &gt;1 = светлее.
                        </div>
                    </div>
                    <div style={{ padding: '4px 0' }}>
                        <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 }}>
                            <span>Контраст</span>
                            <span style={{ opacity: 0.6 }}>{(selection.contrast ?? 1.0).toFixed(2)}</span>
                        </div>
                        <input
                            type="range" min="0.5" max="2" step="0.05"
                            value={selection.contrast ?? 1.0}
                            onChange={(e) => props.onSetLightingProps?.({ contrast: parseFloat(e.target.value) })}
                            style={{ width: '100%' }}
                        />
                    </div>
                    <div style={{ padding: '4px 0' }}>
                        <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 }}>
                            <span>Насыщенность</span>
                            <span style={{ opacity: 0.6 }}>{(selection.saturation ?? 1.0).toFixed(2)}</span>
                        </div>
                        <input
                            type="range" min="0" max="2" step="0.05"
                            value={selection.saturation ?? 1.0}
                            onChange={(e) => props.onSetLightingProps?.({ saturation: parseFloat(e.target.value) })}
                            style={{ width: '100%' }}
                        />
                        <div style={{ fontSize: 10, color: 'var(--text-dim)', marginTop: 2 }}>
                            0 = чёрно-белое, 1 = норма, 2 = очень сочно.
                        </div>
                    </div>
                </div>

                {/* Туман */}
                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="fog" size={12} /> Туман</div>
                    <label style={{ display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer', padding: '4px 0' }}>
                        <input
                            type="checkbox"
                            checked={selection.fogEnabled || false}
                            onChange={(e) => props.onSetLightingProps?.({ fogEnabled: e.target.checked })}
                        />
                        <span>Включён</span>
                    </label>
                    {selection.fogEnabled && (
                        <>
                            <div style={{ padding: '4px 0' }}>
                                <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 }}>
                                    <span>Плотность</span>
                                    <span style={{ opacity: 0.6 }}>{(selection.fogDensity || 0.005).toFixed(3)}</span>
                                </div>
                                <input
                                    type="range" min="0.001" max="0.05" step="0.001"
                                    value={selection.fogDensity ?? 0.005}
                                    onChange={(e) => props.onSetLightingProps?.({ fogDensity: parseFloat(e.target.value) })}
                                    style={{ width: '100%' }}
                                />
                            </div>
                            <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '4px 0' }}>
                                <span style={{ fontSize: 12, flex: 1 }}>Цвет</span>
                                <input
                                    type="color"
                                    value={selection.fogColor || '#b0c8e6'}
                                    onChange={(e) => props.onSetLightingProps?.({ fogColor: e.target.value })}
                                    style={{ width: 36, height: 24, padding: 0, border: 'none', background: 'transparent', cursor: 'pointer' }}
                                />
                            </div>
                        </>
                    )}
                </div>

                {/* Тени */}
                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="moon" size={12} /> Тени</div>
                    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 4 }}>
                        {[
                            { id: 'off',    label: 'Выкл' },
                            { id: 'hard',   label: 'Жёст' },
                            { id: 'soft',   label: 'Мягк' },
                            { id: 'medium', label: 'Сред' },
                            { id: 'high',   label: 'Выс' },
                        ].map(o => (
                            <button
                                key={o.id}
                                className={cl.smallBtn}
                                style={{
                                    background: (selection.shadowQuality || 'soft') === o.id ? 'var(--accent-bright, #2E7D32)' : undefined,
                                    color: (selection.shadowQuality || 'soft') === o.id ? '#fff' : undefined,
                                }}
                                onClick={() => props.onSetLightingProps?.({ shadowQuality: o.id })}
                            >
                                {o.label}
                            </button>
                        ))}
                    </div>
                    <div style={{ fontSize: 11, opacity: 0.7, marginTop: 4 }}>
                        Средние/Высокие — каскадные тени (CSM, тяжелее по FPS).
                    </div>
                </div>

                {/* SSAO — контактные тени */}
                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="moon" size={12} /> Контактные тени (SSAO)</div>
                    <label style={{ display: 'flex', alignItems: 'center', gap: 6, cursor: 'pointer' }}>
                        <input
                            type="checkbox"
                            checked={!!selection.ssaoEnabled}
                            onChange={(e) => props.onSetLightingProps?.({ ssaoEnabled: e.target.checked })}
                        />
                        <span>Тёмные углы и стыки (-15% FPS)</span>
                    </label>
                </div>
            </div>
        );
    }

    // === Тип «sound» — управление амбиентом и музыкой ===
    if (selection.type === 'sound') {
        return (
            <div className={cl.inspector}>
                <div className={cl.headerCard}>
                    <div className={cl.iconBig}><Icon name="music" size={32} strokeWidth={1.8} /></div>
                    <div className={cl.headerText}>
                        <div className={cl.typeLabel}>Звук</div>
                        <div className={cl.typeName}>Фоновый амбиент и музыка</div>
                    </div>
                </div>

                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="tree" size={12} /> Амбиент</div>
                    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 4 }}>
                        {(selection.ambientPresets || []).map(p => (
                            <button
                                key={p.id}
                                className={cl.smallBtn}
                                style={{
                                    background: (selection.ambientId || 'none') === p.id ? 'var(--accent-bright, #2E7D32)' : undefined,
                                    color: (selection.ambientId || 'none') === p.id ? '#fff' : undefined,
                                    fontSize: 11,
                                }}
                                onClick={() => props.onSetSoundProps?.({ ambientId: p.id })}
                            >
                                {p.name}
                            </button>
                        ))}
                    </div>
                </div>

                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="music2" size={12} /> Музыка</div>
                    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 4 }}>
                        {(selection.musicPresets || []).map(p => (
                            <button
                                key={p.id}
                                className={cl.smallBtn}
                                style={{
                                    background: (selection.musicId || 'none') === p.id ? 'var(--accent-bright, #2E7D32)' : undefined,
                                    color: (selection.musicId || 'none') === p.id ? '#fff' : undefined,
                                    fontSize: 11,
                                }}
                                onClick={() => props.onSetSoundProps?.({ musicId: p.id })}
                            >
                                {p.name}
                            </button>
                        ))}
                    </div>
                </div>
            </div>
        );
    }

    // === Тип «player» — скин персонажа (выбор — только через магазин) ===
    if (selection.type === 'player') {
        return (
            <div className={cl.inspector}>
                <div className={cl.headerCard}>
                    <div className={cl.iconBig}><Icon name="user" size={32} strokeWidth={1.8} /></div>
                    <div className={cl.headerText}>
                        <div className={cl.typeLabel}>Скин игрока</div>
                        <div className={cl.typeName}>Модель персонажа в режиме игры</div>
                    </div>
                </div>

                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="user" size={12} /> Скин</div>
                    <div style={{
                        display: 'flex', gap: 10, alignItems: 'flex-start',
                        padding: '12px 12px', borderRadius: 10,
                        background: 'var(--bg-mid, #2e2e2e)',
                        border: '1px solid var(--border, #3a3a3a)',
                    }}>
                        <span style={{ flexShrink: 0, color: 'var(--accent, #4f74ff)', display: 'flex' }}>
                            <Icon name="info" size={18} />
                        </span>
                        <div style={{ fontSize: 12, lineHeight: 1.5, color: 'var(--text-dim, #9a9a9e)' }}>
                            Скин персонажа выбирается игроком в&nbsp;магазине скинов.
                            В&nbsp;игре каждый увидит героя в&nbsp;своём купленном скине —
                            менять его в&nbsp;редакторе нельзя.
                        </div>
                    </div>
                </div>
            </div>
        );
    }

    // === Тип «playerProps» — поведение игрока (прыжок, прицел) ===
    if (selection.type === 'playerProps') {
        const jumpPower = Number.isFinite(selection.jumpPower) ? selection.jumpPower : 1;
        const crosshair = selection.crosshair || 'none';
        return (
            <div className={cl.inspector}>
                <div className={cl.headerCard}>
                    <div className={cl.iconBig}><Icon name="settings" size={32} strokeWidth={1.8} /></div>
                    <div className={cl.headerText}>
                        <div className={cl.typeLabel}>Свойства игрока</div>
                        <div className={cl.typeName}>Прыжок, прицел и поведение</div>
                    </div>
                </div>

                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="zap" size={12} /> Сила прыжка</div>
                    <div style={{ padding: '4px 0' }}>
                        <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 }}>
                            <span>Множитель</span>
                            <span style={{ opacity: 0.6 }}>×{jumpPower.toFixed(2)}</span>
                        </div>
                        <input
                            type="range" min="0.5" max="3" step="0.1"
                            value={jumpPower}
                            onChange={(e) => props.onSetPlayerProps?.({ jumpPower: parseFloat(e.target.value) })}
                            style={{ width: '100%' }}
                        />
                    </div>
                    <div style={{ fontSize: 11, color: 'var(--text-dim)', fontStyle: 'italic' }}>
                        1.0 = базовый прыжок, 1.5 = выше, 2.0 = очень высокий.
                    </div>
                </div>

                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="target" size={12} /> Прицел в Play</div>
                    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 4 }}>
                        {[
                            { id: 'none',   label: 'Нет' },
                            { id: 'dot',    label: '·' },
                            { id: 'cross',  label: '+' },
                            { id: 'circle', label: '○' },
                        ].map(c => (
                            <button
                                key={c.id}
                                className={cl.smallBtn}
                                style={{
                                    background: crosshair === c.id ? 'var(--accent-bright, #2E7D32)' : undefined,
                                    color: crosshair === c.id ? '#fff' : undefined,
                                    fontSize: c.id === 'none' ? 11 : 18,
                                    fontWeight: c.id === 'none' ? 600 : 400,
                                    padding: '6px',
                                }}
                                onClick={() => props.onSetPlayerProps?.({ crosshair: c.id })}
                            >
                                {c.label}
                            </button>
                        ))}
                    </div>
                    <div style={{ fontSize: 11, color: 'var(--text-dim)', fontStyle: 'italic', marginTop: 6 }}>
                        В скриптах: <code>game.player.crosshair = 'cross';</code>
                    </div>
                </div>
            </div>
        );
    }

    // === Тип «gui» — UI-элемент (Frame/Text/Button/Image) ===
    if (selection.type === 'gui') {
        const d = selection.data || {};
        const t = d.type;
        const setProp = (patch) => props.onSetGuiProps?.(d.id, patch);
        const isText = t === 'text' || t === 'button';
        const isImage = t === 'image';
        const isTextbox = t === 'textbox';
        // Контейнеры (frame/scroll) умеют авто-раскладку детей.
        const isContainer = t === 'frame' || t === 'scroll';
        const typeLabel = t === 'frame' ? 'Контейнер'
                        : t === 'scroll' ? 'Список'
                        : t === 'text' ? 'Надпись'
                        : t === 'button' ? 'Кнопка'
                        : t === 'textbox' ? 'Поле ввода'
                        : t === 'image' ? 'Картинка' : 'Интерфейс';
        const typeIconName = t === 'frame' ? 'square'
                           : t === 'scroll' ? 'align-left'
                           : t === 'text' ? 'type'
                           : t === 'button' ? 'circle'
                           : t === 'textbox' ? 'type'
                           : t === 'image' ? 'image' : 'palette';
        return (
            <div className={cl.inspector}>
                <div className={cl.headerCard}>
                    <div className={cl.iconBig}><Icon name={typeIconName} size={32} strokeWidth={1.8} /></div>
                    <div className={cl.headerText}>
                        <div className={cl.typeLabel}>{typeLabel}</div>
                        <input
                            type="text"
                            value={d.name || ''}
                            onChange={(e) => setProp({ name: e.target.value })}
                            className={cl.nameInput}
                            placeholder="Имя элемента"
                        />
                    </div>
                </div>

                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="ruler" size={12} /> Позиция и размер (% экрана)</div>
                    <div style={{ display: 'grid', gridTemplateColumns: 'auto 1fr 1fr', gap: 4, alignItems: 'center', fontSize: 12 }}>
                        <span>X</span>
                        <input type="number" step="1" value={Math.round(d.x ?? 50)}
                            onChange={(e) => setProp({ x: Math.round(parseFloat(e.target.value) || 0) })}
                            className={cl.numInput} />
                        <span style={{ opacity: 0.6, fontSize: 10 }}>{Math.round(d.x ?? 50)}%</span>

                        <span>Y</span>
                        <input type="number" step="1" value={Math.round(d.y ?? 50)}
                            onChange={(e) => setProp({ y: Math.round(parseFloat(e.target.value) || 0) })}
                            className={cl.numInput} />
                        <span style={{ opacity: 0.6, fontSize: 10 }}>{Math.round(d.y ?? 50)}%</span>

                        <span>Ш</span>
                        <input type="number" step="1" min="1" value={Math.round(d.w ?? 20)}
                            onChange={(e) => setProp({ w: Math.max(1, Math.round(parseFloat(e.target.value) || 1)) })}
                            className={cl.numInput} />
                        <span style={{ opacity: 0.6, fontSize: 10 }}>{Math.round(d.w ?? 20)}%</span>

                        <span>В</span>
                        <input type="number" step="1" min="1" value={Math.round(d.h ?? 10)}
                            onChange={(e) => setProp({ h: Math.max(1, Math.round(parseFloat(e.target.value) || 1)) })}
                            className={cl.numInput} />
                        <span style={{ opacity: 0.6, fontSize: 10 }}>{Math.round(d.h ?? 10)}%</span>
                    </div>
                    <div style={{ marginTop: 6 }}>
                        <div style={{ fontSize: 11, opacity: 0.7, marginBottom: 4 }}>Якорь (точка отсчёта)</div>
                        <select
                            value={d.anchor || 'center'}
                            onChange={(e) => setProp({ anchor: e.target.value })}
                            className={cl.numInput}
                            style={{ width: '100%' }}
                        >
                            <option value="center">Центр</option>
                            <option value="top-left">Верх-лево</option>
                            <option value="top-right">Верх-право</option>
                            <option value="bottom-left">Низ-лево</option>
                            <option value="bottom-right">Низ-право</option>
                        </select>
                    </div>
                    {/* Родитель — экран или другой контейнер.
                        Координаты считаются относительно него. */}
                    <div style={{ marginTop: 6 }}>
                        <div style={{ fontSize: 11, opacity: 0.7, marginBottom: 4 }}>Родитель</div>
                        <select
                            value={d.parentId || ''}
                            onChange={(e) => setProp({ parentId: e.target.value || null })}
                            className={cl.numInput}
                            style={{ width: '100%' }}
                        >
                            <option value="">Экран (корень)</option>
                            {guiElements
                                .filter(g => g.type === 'frame' && g.id !== d.id && !_isAncestorOf(guiElements, d.id, g.id))
                                .map(g => (
                                    <option key={g.id} value={g.id}>{g.name}</option>
                                ))}
                        </select>
                        <div style={{ fontSize: 10, color: 'var(--text-dim)', fontStyle: 'italic', marginTop: 2 }}>
                            Координаты теперь относительно родителя.
                        </div>
                    </div>
                </div>

                {isText && (
                    <div className={cl.section}>
                        <div className={cl.sectionTitle}><Icon name="rename" size={12} /> Текст</div>
                        <textarea
                            value={d.text || ''}
                            onChange={(e) => setProp({ text: e.target.value })}
                            rows={2}
                            style={{
                                width: '100%', fontFamily: 'inherit', fontSize: 13,
                                padding: 6, background: 'var(--bg-input, #2a1f15)',
                                color: 'var(--text-primary, #f0e6d8)',
                                border: '1px solid var(--border, #5a4a3a)', borderRadius: 4, resize: 'vertical',
                            }}
                        />
                        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 4, marginTop: 6, fontSize: 12 }}>
                            <label style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                                Цвет текста
                                <input type="color"
                                    value={d.textColor || '#f0e6d8'}
                                    onChange={(e) => setProp({ textColor: e.target.value })}
                                    style={{ height: 28, width: '100%', padding: 0, border: 0, background: 'transparent' }}
                                />
                            </label>
                            <label style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                                Размер
                                <input type="number" min="6" max="80" value={d.textSize ?? 16}
                                    onChange={(e) => setProp({ textSize: parseInt(e.target.value, 10) || 16 })}
                                    className={cl.numInput} />
                            </label>
                            <label style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                                Выравнивание
                                <select value={d.textAlign || 'center'}
                                    onChange={(e) => setProp({ textAlign: e.target.value })}
                                    className={cl.numInput}>
                                    <option value="left">Слева</option>
                                    <option value="center">По центру</option>
                                    <option value="right">Справа</option>
                                </select>
                            </label>
                            <label style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                                Жирность
                                <select value={d.fontWeight || 500}
                                    onChange={(e) => setProp({ fontWeight: parseInt(e.target.value, 10) })}
                                    className={cl.numInput}>
                                    <option value={300}>Тонкий</option>
                                    <option value={500}>Обычный</option>
                                    <option value={700}>Жирный</option>
                                    <option value={900}>Очень жирный</option>
                                </select>
                            </label>
                        </div>
                    </div>
                )}

                {/* Авто-раскладка детей — для контейнеров (Фаза 5.3). */}
                {isContainer && (
                    <div className={cl.section}>
                        <div className={cl.sectionTitle}>
                            <Icon name="align-left" size={12} /> Раскладка детей
                        </div>
                        <div className={cl.row3}>
                            {[
                                { id: 'none',       name: 'Свободно' },
                                { id: 'vertical',   name: 'В столбик' },
                                { id: 'horizontal', name: 'В строку' },
                            ].map(opt => (
                                <button
                                    key={opt.id}
                                    type="button"
                                    className={cl.smallBtn}
                                    onClick={() => setProp({ layout: opt.id })}
                                    style={{
                                        fontWeight: (d.layout || 'none') === opt.id ? 700 : 400,
                                        background: (d.layout || 'none') === opt.id ? 'var(--accent)' : undefined,
                                        color: (d.layout || 'none') === opt.id ? '#fff' : undefined,
                                    }}
                                >
                                    {opt.name}
                                </button>
                            ))}
                        </div>
                        {(d.layout === 'vertical' || d.layout === 'horizontal') && (
                            <div style={{ display: 'flex', gap: 8, marginTop: 6 }}>
                                <label style={{ flex: 1, fontSize: 11 }}>
                                    Отступ
                                    <input
                                        type="number" min="0" max="20" step="0.5"
                                        value={d.layoutGap ?? 2}
                                        onChange={(e) => setProp({ layoutGap: parseFloat(e.target.value) || 0 })}
                                        className={cl.numInput}
                                        style={{ width: '100%' }}
                                    />
                                </label>
                                <label style={{ flex: 1, fontSize: 11 }}>
                                    Внутр. поле
                                    <input
                                        type="number" min="0" max="20" step="0.5"
                                        value={d.layoutPad ?? 3}
                                        onChange={(e) => setProp({ layoutPad: parseFloat(e.target.value) || 0 })}
                                        className={cl.numInput}
                                        style={{ width: '100%' }}
                                    />
                                </label>
                            </div>
                        )}
                        {t === 'scroll' && (
                            <div style={{ fontSize: 11, color: 'var(--text-dim)', fontStyle: 'italic', marginTop: 6 }}>
                                Список прокручивается колесом мыши в игре.
                            </div>
                        )}
                    </div>
                )}

                {isImage && (
                    <div className={cl.section}>
                        <div className={cl.sectionTitle}><Icon name="image" size={12} /> Картинка</div>
                        <AssetPicker
                            assetList={assetList}
                            value={d.imageAsset || null}
                            onPick={(id) => setProp({ imageAsset: id })}
                            onUpload={onUploadAsset}
                            onRemove={onRemoveAsset}
                        />
                        <div style={{ fontSize: 11, color: 'var(--text-dim)', fontStyle: 'italic', margin: '8px 0 4px' }}>
                            …или вставь ссылку на картинку:
                        </div>
                        <input
                            type="text"
                            value={d.imageUrl || ''}
                            onChange={(e) => setProp({ imageUrl: e.target.value })}
                            placeholder="URL картинки (https://...)"
                            className={cl.numInput}
                            style={{ width: '100%' }}
                        />
                    </div>
                )}

                {isTextbox && (
                    <div className={cl.section}>
                        <div className={cl.sectionTitle}><Icon name="type" size={12} /> Поле ввода</div>
                        <div style={{ fontSize: 11, opacity: 0.7, marginBottom: 4 }}>
                            Подсказка (серый текст в пустом поле)
                        </div>
                        <input
                            type="text"
                            value={d.placeholder || ''}
                            onChange={(e) => setProp({ placeholder: e.target.value })}
                            placeholder="Введите текст…"
                            className={cl.numInput}
                            style={{ width: '100%' }}
                        />
                        <div style={{ fontSize: 11, opacity: 0.7, margin: '8px 0 4px' }}>
                            Начальный текст
                        </div>
                        <input
                            type="text"
                            value={d.text || ''}
                            onChange={(e) => setProp({ text: e.target.value })}
                            placeholder="(пусто)"
                            className={cl.numInput}
                            style={{ width: '100%' }}
                        />
                        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 4, marginTop: 6, fontSize: 12 }}>
                            <label style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                                Цвет текста
                                <input type="color"
                                    value={d.textColor || '#f0e6d8'}
                                    onChange={(e) => setProp({ textColor: e.target.value })}
                                    style={{ height: 28, width: '100%', padding: 0, border: 0, background: 'transparent' }}
                                />
                            </label>
                            <label style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                                Размер
                                <input type="number" min="6" max="80" value={d.textSize ?? 16}
                                    onChange={(e) => setProp({ textSize: parseInt(e.target.value, 10) || 16 })}
                                    className={cl.numInput} />
                            </label>
                        </div>
                        <div style={{ fontSize: 11, color: 'var(--text-dim)', fontStyle: 'italic', marginTop: 6 }}>
                            В скрипте: game.gui.onSubmit(id, fn) — fn получит
                            введённый текст когда игрок нажмёт Enter.
                        </div>
                    </div>
                )}

                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="palette" size={12} /> Фон и граница</div>
                    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 4, fontSize: 12 }}>
                        <label style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                            Цвет фона
                            <input type="color"
                                value={d.bgColor && d.bgColor !== 'transparent' ? d.bgColor : '#1f1810'}
                                onChange={(e) => setProp({ bgColor: e.target.value })}
                                style={{ height: 28, width: '100%', padding: 0, border: 0, background: 'transparent' }}
                            />
                        </label>
                        <label style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                            Прозрачность
                            <input type="range" min="0" max="1" step="0.05"
                                value={d.bgOpacity ?? 1}
                                onChange={(e) => setProp({ bgOpacity: parseFloat(e.target.value) })}
                            />
                        </label>
                        <label style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                            Цвет границы
                            <input type="color"
                                value={d.borderColor || '#5a4a3a'}
                                onChange={(e) => setProp({ borderColor: e.target.value })}
                                style={{ height: 28, width: '100%', padding: 0, border: 0, background: 'transparent' }}
                            />
                        </label>
                        <label style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                            Толщина гр.
                            <input type="number" min="0" max="10" value={d.borderWidth ?? 0}
                                onChange={(e) => setProp({ borderWidth: parseInt(e.target.value, 10) || 0 })}
                                className={cl.numInput} />
                        </label>
                        <label style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                            Скругление
                            <input type="number" min="0" max="40" value={d.borderRadius ?? 0}
                                onChange={(e) => setProp({ borderRadius: parseInt(e.target.value, 10) || 0 })}
                                className={cl.numInput} />
                        </label>
                        <button
                            onClick={() => setProp({ bgColor: 'transparent', bgOpacity: 0 })}
                            className={cl.smallBtn}
                            style={{ alignSelf: 'flex-end' }}
                            title="Сделать фон полностью прозрачным"
                        >
                            Без фона
                        </button>
                    </div>
                    {/* Тень под элементом (Фаза 5.4). */}
                    <label style={{
                        display: 'flex', alignItems: 'center', gap: 6,
                        fontSize: 12, cursor: 'pointer', marginTop: 8,
                    }}>
                        <input
                            type="checkbox"
                            checked={!!d.shadow}
                            onChange={(e) => setProp({ shadow: e.target.checked })}
                        />
                        Тень под элементом
                    </label>
                </div>

                {/* === Задача 03: Градиент фона === */}
                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="palette" size={12} /> Градиент фона</div>
                    <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, cursor: 'pointer' }}>
                        <input
                            type="checkbox"
                            checked={!!d.bgGradient}
                            onChange={(e) => setProp({
                                bgGradient: e.target.checked
                                    ? { stops: [d.bgColor || '#ff5a5a', '#ff8a3d'], angle: 90 }
                                    : null,
                            })}
                        />
                        Включить градиент (заменяет фон)
                    </label>
                    {d.bgGradient && (
                        <div style={{ marginTop: 6, display: 'flex', flexDirection: 'column', gap: 4 }}>
                            {(d.bgGradient.stops || []).map((s, i) => {
                                const c = typeof s === 'string' ? s : (s.c || '#000');
                                return (
                                    <div key={i} style={{ display: 'flex', gap: 4, alignItems: 'center', fontSize: 12 }}>
                                        <span>#{i + 1}</span>
                                        <input type="color" value={c}
                                            onChange={(e) => {
                                                const stops = [...(d.bgGradient.stops || [])];
                                                stops[i] = e.target.value;
                                                setProp({ bgGradient: { ...d.bgGradient, stops } });
                                            }} />
                                        {(d.bgGradient.stops || []).length > 2 && (
                                            <button onClick={() => {
                                                const stops = [...d.bgGradient.stops]; stops.splice(i, 1);
                                                setProp({ bgGradient: { ...d.bgGradient, stops } });
                                            }} className={cl.smallBtn}>×</button>
                                        )}
                                    </div>
                                );
                            })}
                            <button className={cl.smallBtn} onClick={() => {
                                const stops = [...(d.bgGradient.stops || []), '#80a0ff'];
                                setProp({ bgGradient: { ...d.bgGradient, stops } });
                            }}>+ цвет</button>
                            <label style={{ display: 'flex', gap: 4, alignItems: 'center', fontSize: 12 }}>
                                Угол
                                <input type="range" min="0" max="360" value={d.bgGradient.angle ?? 90}
                                    onChange={(e) => setProp({ bgGradient: { ...d.bgGradient, angle: parseInt(e.target.value, 10) } })}
                                    style={{ flex: 1 }} />
                                <span style={{ width: 36, textAlign: 'right' }}>{d.bgGradient.angle ?? 90}°</span>
                            </label>
                        </div>
                    )}
                </div>

                {/* === Задача 03: Обводка текста, поворот, scale === */}
                {(isText) && (
                    <div className={cl.section}>
                        <div className={cl.sectionTitle}><Icon name="type" size={12} /> Обводка текста</div>
                        <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, cursor: 'pointer' }}>
                            <input type="checkbox" checked={!!d.textStroke}
                                onChange={(e) => setProp({
                                    textStroke: e.target.checked ? { color: '#000000', width: 2 } : null,
                                })} />
                            Контур
                        </label>
                        {d.textStroke && (
                            <div style={{ display: 'flex', gap: 6, alignItems: 'center', marginTop: 4, fontSize: 12 }}>
                                <input type="color" value={d.textStroke.color || '#000000'}
                                    onChange={(e) => setProp({ textStroke: { ...d.textStroke, color: e.target.value } })} />
                                <span>Толщ.</span>
                                <input type="number" min="1" max="8" value={d.textStroke.width || 2}
                                    onChange={(e) => setProp({ textStroke: { ...d.textStroke, width: parseInt(e.target.value, 10) || 1 } })}
                                    className={cl.numInput} style={{ width: 50 }} />
                            </div>
                        )}
                    </div>
                )}

                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="rotate-cw" size={12} /> Поворот / масштаб</div>
                    <label style={{ display: 'flex', gap: 4, alignItems: 'center', fontSize: 12 }}>
                        Поворот
                        <input type="range" min="-180" max="180" value={d.rotation ?? 0}
                            onChange={(e) => setProp({ rotation: parseInt(e.target.value, 10) })}
                            style={{ flex: 1 }} />
                        <span style={{ width: 44, textAlign: 'right' }}>{d.rotation ?? 0}°</span>
                    </label>
                    <label style={{ display: 'flex', gap: 4, alignItems: 'center', fontSize: 12, marginTop: 4 }}>
                        Scale
                        <input type="range" min="0.1" max="3" step="0.05" value={d.scaleX ?? 1}
                            onChange={(e) => {
                                const v = parseFloat(e.target.value) || 1;
                                setProp({ scaleX: v, scaleY: v });
                            }}
                            style={{ flex: 1 }} />
                        <span style={{ width: 44, textAlign: 'right' }}>{(d.scaleX ?? 1).toFixed(2)}</span>
                    </label>
                </div>

                {/* === Задача 03: Бейдж в углу === */}
                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="award" size={12} /> Бейдж</div>
                    <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, cursor: 'pointer' }}>
                        <input type="checkbox" checked={!!d.badge}
                            onChange={(e) => setProp({
                                badge: e.target.checked ? { corner: 'top-right', icon: 'exclamation', color: '#fbbf24' } : null,
                            })} />
                        Показать бейдж
                    </label>
                    {d.badge && (
                        <div style={{ display: 'flex', flexDirection: 'column', gap: 4, marginTop: 4, fontSize: 12 }}>
                            <label>Иконка
                                <select value={d.badge.icon || 'exclamation'}
                                    onChange={(e) => setProp({ badge: { ...d.badge, icon: e.target.value } })}
                                    style={{ width: '100%' }}>
                                    <option value="exclamation">!</option>
                                    <option value="star">★</option>
                                    <option value="plus">+</option>
                                    <option value="new">NEW</option>
                                    <option value="sale">% (sale)</option>
                                </select>
                            </label>
                            <label>Угол
                                <select value={d.badge.corner || 'top-right'}
                                    onChange={(e) => setProp({ badge: { ...d.badge, corner: e.target.value } })}
                                    style={{ width: '100%' }}>
                                    <option value="top-right">↗</option>
                                    <option value="top-left">↖</option>
                                    <option value="bottom-right">↘</option>
                                    <option value="bottom-left">↙</option>
                                </select>
                            </label>
                            <label style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
                                Цвет <input type="color" value={d.badge.color || '#fbbf24'}
                                    onChange={(e) => setProp({ badge: { ...d.badge, color: e.target.value } })} />
                            </label>
                        </div>
                    )}
                </div>

                {/* === Задача 03: Hover/Active (только для button) === */}
                {t === 'button' && (
                    <div className={cl.section}>
                        <div className={cl.sectionTitle}><Icon name="mouse" size={12} /> Реакция на мышь</div>
                        <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, cursor: 'pointer' }}>
                            <input type="checkbox" checked={!!d.hover}
                                onChange={(e) => setProp({
                                    hover: e.target.checked ? { scale: 1.08, brightness: 1.15, duration: 0.15 } : null,
                                })} />
                            Hover (при наведении)
                        </label>
                        {d.hover && (
                            <div style={{ display: 'flex', flexDirection: 'column', gap: 3, marginTop: 4, fontSize: 12 }}>
                                <label>Scale {(d.hover.scale ?? 1.08).toFixed(2)}
                                    <input type="range" min="1" max="1.5" step="0.01" value={d.hover.scale ?? 1.08}
                                        onChange={(e) => setProp({ hover: { ...d.hover, scale: parseFloat(e.target.value) } })}
                                        style={{ width: '100%' }} />
                                </label>
                                <label>Яркость {(d.hover.brightness ?? 1.15).toFixed(2)}
                                    <input type="range" min="0.7" max="1.5" step="0.01" value={d.hover.brightness ?? 1.15}
                                        onChange={(e) => setProp({ hover: { ...d.hover, brightness: parseFloat(e.target.value) } })}
                                        style={{ width: '100%' }} />
                                </label>
                            </div>
                        )}
                        <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, cursor: 'pointer', marginTop: 6 }}>
                            <input type="checkbox" checked={!!d.active}
                                onChange={(e) => setProp({
                                    active: e.target.checked ? { scale: 0.94, duration: 0.08 } : null,
                                })} />
                            Active (при нажатии)
                        </label>
                        {d.active && (
                            <label style={{ fontSize: 12 }}>Scale {(d.active.scale ?? 0.94).toFixed(2)}
                                <input type="range" min="0.8" max="1" step="0.01" value={d.active.scale ?? 0.94}
                                    onChange={(e) => setProp({ active: { ...d.active, scale: parseFloat(e.target.value) } })}
                                    style={{ width: '100%' }} />
                            </label>
                        )}
                    </div>
                )}

                {/* === Задача 03: Анимация-пресет === */}
                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="play" size={12} /> Анимация (в Play)</div>
                    <select value={d.animationPreset || 'none'}
                        onChange={(e) => setProp({ animationPreset: e.target.value })}
                        style={{ width: '100%', padding: '4px 6px' }}>
                        <option value="none">Без анимации</option>
                        <option value="pulse">Пульсация (1.0 ↔ 1.1)</option>
                        <option value="rotate">Вращение (360° за 3с)</option>
                        <option value="sway">Качание (-8° ↔ +8°)</option>
                        <option value="glow">Подсветка (opacity 1 ↔ 0.7)</option>
                        <option value="bounce">Прыжок (y -1 ↔ 0)</option>
                    </select>
                </div>

                <div className={cl.section}>
                    <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 13, cursor: 'pointer' }}>
                        <input
                            type="checkbox"
                            checked={d.visible !== false}
                            onChange={(e) => setProp({ visible: e.target.checked })}
                        />
                        <span>Виден на сцене</span>
                    </label>
                </div>

                <div className={cl.section}>
                    <button
                        onClick={() => {
                            if (window.confirm('Удалить элемент?')) props.onDeleteGui?.(d.id);
                        }}
                        className={cl.smallBtn}
                        style={{
                            width: '100%',
                            background: 'rgba(168, 50, 50, 0.18)',
                            color: '#e88a8a',
                            border: '1px solid rgba(168, 50, 50, 0.4)',
                        }}
                    >
                        <Icon name="delete" size={13} /> Удалить элемент
                    </button>
                </div>
            </div>
        );
    }

    if (selection.type === 'floor') {
        const enabled = selection.enabled !== false;
        const ws = selection.worldSize || 80;
        return (
            <div className={cl.inspector}>
                <div className={cl.headerCard}>
                    <div className={cl.iconBig}><Icon name="square" size={32} strokeWidth={1.8} /></div>
                    <div className={cl.headerText}>
                        <div className={cl.typeLabel}>Пол</div>
                        <div className={cl.typeName}>Плоскость с сеткой в редакторе</div>
                    </div>
                </div>

                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="visible" size={12} /> Видимость</div>
                    <label style={{ display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer', padding: '4px 0' }}>
                        <input
                            type="checkbox"
                            checked={enabled}
                            onChange={(e) => props.onSetFloorProps?.({ enabled: e.target.checked })}
                        />
                        <span>Пол виден</span>
                    </label>
                    <div style={{ fontSize: 11, color: 'var(--text-dim)', fontStyle: 'italic', marginTop: 4 }}>
                        <Icon name="sparkle" size={11} /> При выключенном поле игрок будет падать в пустоту — эффектно для платформера.
                    </div>
                </div>

                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="ruler" size={12} /> Размер</div>
                    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 4 }}>
                        {[50, 100, 200, 500].map(sz => (
                            <button
                                key={sz}
                                className={cl.smallBtn}
                                style={{
                                    background: ws === sz ? 'var(--accent-bright, #2E7D32)' : undefined,
                                    color: ws === sz ? '#fff' : undefined,
                                    fontSize: 12,
                                }}
                                onClick={() => props.onSetFloorProps?.({ worldSize: sz })}
                            >
                                {sz}
                            </button>
                        ))}
                    </div>
                    <div style={{ fontSize: 11, color: 'var(--text-dim)', fontStyle: 'italic', marginTop: 4 }}>
                        Сторона прямоугольного пола в юнитах.
                    </div>
                </div>
            </div>
        );
    }

    // Тип «script» — лёгкий header без редактора кода (код редактируется в табе).
    if (isScript) {
        const targetLabel = (() => {
            const t = selection.target;
            if (!t) return 'Глобальный скрипт';
            if (t.kind === 'block') {
                const r = t.ref || t;
                return `Привязан к блоку (${r.x}, ${r.y}, ${r.z})`;
            }
            const id = t.id ?? t.ref;
            if (t.kind === 'model') return `Привязан к модели #${id}`;
            if (t.kind === 'primitive') return `Привязан к примитиву #${id}`;
            return 'Привязан к объекту';
        })();
        return (
            <div className={cl.inspector}>
                <div className={cl.headerCard}>
                    <div className={cl.iconBig}><Icon name="script" size={32} strokeWidth={1.8} /></div>
                    <div className={cl.headerText}>
                        <div className={cl.typeLabel}>Скрипт</div>
                        <div className={cl.typeName}>
                            {selection.scriptId === 'demo' ? 'Демо-скрипт' : selection.scriptId}
                        </div>
                    </div>
                </div>
                <div className={cl.section}>
                    <div className={cl.sectionTitle}>ℹ️ Информация</div>
                    <div style={{ fontSize: 12, color: 'var(--text-dim)', lineHeight: 1.6 }}>
                        {targetLabel}
                    </div>
                    <div style={{ fontSize: 11, color: 'var(--text-dim)', fontStyle: 'italic', marginTop: 10 }}>
                        <Icon name="sparkle" size={11} /> Редактирование — в табе скрипта над сценой.
                    </div>
                </div>
            </div>
        );
    }

    return (
        <div className={cl.inspector}>
            {/* Заголовок объекта */}
            <div className={cl.headerCard}>
                <div className={cl.iconBig}>
                    {isSpawn
                        ? <Icon name="flag" size={32} strokeWidth={1.8} />
                        : isBlock
                            ? <Icon name="boxes" size={32} strokeWidth={1.8} />
                            : isPrimitive
                                ? <Icon name={primitiveType?.icon || 'cube'} size={32} strokeWidth={1.8} />
                                : <Icon name="trees" size={32} strokeWidth={1.8} />}
                </div>
                <div className={cl.headerText}>
                    <div className={cl.typeLabel}>
                        {isSpawn ? 'Точка спавна'
                            : isBlock ? 'Блок'
                            : isPrimitive ? (
                                primitiveType?.kind === 'trigger' ? 'Триггер' :
                                primitiveType?.kind === 'checkpoint' ? 'Чек-поинт' :
                                'Примитив'
                            )
                            : 'Модель'}
                    </div>
                    <div className={cl.typeName}>
                        {isSpawn ? 'Где появляется игрок'
                            : isBlock ? blockType?.name
                            : isPrimitive ? primitiveType?.name
                            : isUserModel ? `Моя модель #${selection.userModelId}`
                            : modelType?.name || '—'}
                    </div>
                </div>
            </div>

            {/* Позиция */}
            <div className={cl.section}>
                <div className={cl.sectionTitle}><Icon name="pin" size={12} /> Позиция</div>
                <div className={cl.row3}>
                    <label className={cl.field}>
                        <span className={cl.axisLabel} style={{color:'#e85a5a'}}>X</span>
                        <input
                            type="number"
                            step={isBlock ? '1' : '0.1'}
                            className={cl.input}
                            value={localX}
                            onChange={(e) => setLocalX(e.target.value)}
                            onBlur={commitPosition}
                            onKeyDown={(e) => { if (e.key === 'Enter') commitPosition(); }}
                        />
                    </label>
                    <label className={cl.field}>
                        <span className={cl.axisLabel} style={{color:'#5ae85a'}}>Y</span>
                        <input
                            type="number"
                            step={isBlock ? '1' : '0.1'}
                            className={cl.input}
                            value={localY}
                            onChange={(e) => setLocalY(e.target.value)}
                            onBlur={commitPosition}
                            onKeyDown={(e) => { if (e.key === 'Enter') commitPosition(); }}
                        />
                    </label>
                    <label className={cl.field}>
                        <span className={cl.axisLabel} style={{color:'#5a8ce8'}}>Z</span>
                        <input
                            type="number"
                            step={isBlock ? '1' : '0.1'}
                            className={cl.input}
                            value={localZ}
                            onChange={(e) => setLocalZ(e.target.value)}
                            onBlur={commitPosition}
                            onKeyDown={(e) => { if (e.key === 'Enter') commitPosition(); }}
                        />
                    </label>
                </div>
            </div>

            {/* Свойства блока — Сталкивается / Видимый. Жидкости пропускаем. */}
            {isBlock && !isLiquid && (
                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="settings" size={12} /> Свойства</div>
                    <label style={{ display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer', padding: '4px 0' }}>
                        <input type="checkbox"
                            checked={localCanCollide}
                            onChange={(e) => {
                                setLocalCanCollide(e.target.checked);
                                onSetBlockProps?.({ canCollide: e.target.checked });
                            }} />
                        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}><Icon name="shield" size={12} /> Сталкивается</span>
                    </label>
                    <label style={{ display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer', padding: '4px 0' }}>
                        <input type="checkbox"
                            checked={localVisible}
                            onChange={(e) => {
                                setLocalVisible(e.target.checked);
                                onSetBlockProps?.({ visible: e.target.checked });
                            }} />
                        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}><Icon name="visible" size={12} /> Видимый</span>
                    </label>
                </div>
            )}

            {/* Подсказка для жидкостей */}
            {isLiquid && (
                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="water" size={12} /> Жидкость</div>
                    <div style={{ fontSize: 12, color: 'var(--text-dim)', lineHeight: 1.5 }}>
                        {selection.blockTypeId === 'water'
                            ? 'Через воду можно проходить и плавать. В режиме игры персонаж принимает горизонтальную позу.'
                            : 'Лава наносит урон при касании (скоро). Через неё можно проходить.'}
                    </div>
                </div>
            )}

            {/* Поворот / масштаб — только для моделей (не для блоков, spawn, primitive) */}
            {isModel && (
                <>
                    <div className={cl.section}>
                        <div className={cl.sectionTitle}><Icon name="refresh" size={12} /> Поворот по Y (°)</div>
                        <div className={cl.rowFull}>
                            <input
                                type="number"
                                step="15"
                                className={cl.input}
                                value={localRot}
                                onChange={(e) => setLocalRot(e.target.value)}
                                onBlur={commitRotation}
                                onKeyDown={(e) => { if (e.key === 'Enter') commitRotation(); }}
                            />
                            <button
                                className={cl.smallBtn}
                                onClick={() => {
                                    const cur = parseFloat(localRot) || 0;
                                    const next = (cur + 90) % 360;
                                    setLocalRot(String(next));
                                    onRotateTo(next * Math.PI / 180);
                                }}
                                title="Повернуть на 90° (клавиша R)"
                            >
                                +90°
                            </button>
                        </div>
                    </div>

                    <div className={cl.section}>
                        <div className={cl.sectionTitle}><Icon name="ruler" size={12} /> Масштаб</div>
                        <div className={cl.rowFull}>
                            <input
                                type="number"
                                step="0.1"
                                min="0.1"
                                max="10"
                                className={cl.input}
                                value={localScale}
                                onChange={(e) => setLocalScale(e.target.value)}
                                onBlur={commitScale}
                                onKeyDown={(e) => { if (e.key === 'Enter') commitScale(); }}
                            />
                            <button className={cl.smallBtn} onClick={() => { setLocalScale('1'); onScaleTo(1); }} style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
                                <Icon name="refresh" size={12} /> 1x
                            </button>
                        </div>
                    </div>

                    {/* Свойства модели */}
                    <div className={cl.section}>
                        <div className={cl.sectionTitle}><Icon name="settings" size={12} /> Свойства</div>
                        <label style={{ display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer', padding: '4px 0' }}>
                            <input type="checkbox"
                                checked={localCanCollide}
                                onChange={(e) => {
                                    setLocalCanCollide(e.target.checked);
                                    onSetModelProps?.({ canCollide: e.target.checked });
                                }} />
                            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}><Icon name="shield" size={12} /> Сталкивается</span>
                        </label>
                        <label style={{ display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer', padding: '4px 0' }}>
                            <input type="checkbox"
                                checked={localVisible}
                                onChange={(e) => {
                                    setLocalVisible(e.target.checked);
                                    onSetModelProps?.({ visible: e.target.checked });
                                }} />
                            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}><Icon name="visible" size={12} /> Видимый</span>
                        </label>
                    </div>

                    {/* Внешний вид: прозрачность и тинт.
                        Скрываем для user-моделей — там per-vertex color не
                        поддерживает opacity/tint через StandardMaterial.alpha. */}
                    {!isUserModel && (
                    <div className={cl.section}>
                        <div className={cl.sectionTitle}><Icon name="palette" size={12} /> Внешний вид</div>
                        <div style={{ padding: '4px 0' }}>
                            <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 }}>
                                <span>Прозрачность</span>
                                <span style={{ opacity: 0.6 }}>{Math.round(localOpacity * 100)}%</span>
                            </div>
                            <input
                                type="range" min="0" max="1" step="0.05"
                                value={localOpacity}
                                onChange={(e) => {
                                    const v = parseFloat(e.target.value);
                                    setLocalOpacity(v);
                                    onSetModelProps?.({ opacity: v });
                                }}
                                style={{ width: '100%' }}
                            />
                        </div>
                        <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '4px 0' }}>
                            <span style={{ fontSize: 12, flex: 1 }}>Цветовой тинт</span>
                            <input
                                type="color"
                                value={localTint || '#ffffff'}
                                onChange={(e) => {
                                    setLocalTint(e.target.value);
                                    onSetModelProps?.({ tint: e.target.value });
                                }}
                                style={{ width: 36, height: 24, padding: 0, border: 'none', background: 'transparent', cursor: 'pointer' }}
                            />
                            <button className={cl.smallBtn}
                                onClick={() => { setLocalTint(''); onSetModelProps?.({ tint: null }); }}
                                title="Убрать тинт"
                            ><Icon name="refresh" size={13} /></button>
                        </div>
                    </div>
                    )}

                    {/* === GAMEPLAY — настройки врагов, спавнеров, оружия === */}
                    {selection.gameplay && (
                        <GameplayInspector
                            selection={selection}
                            onSetModelProps={onSetModelProps}
                            onAddWeaponToInventory={props.onAddWeaponToInventory}
                        />
                    )}
                </>
            )}

            {/* Размер и материал — только для примитивов */}
            {isPrimitive && (
                <>
                    <div className={cl.section}>
                        <div className={cl.sectionTitle}><Icon name="ruler" size={12} /> Размер</div>
                        <div className={cl.row3}>
                            <label className={cl.field}>
                                <span className={cl.axisLabel} style={{color:'#e85a5a'}}>X</span>
                                <input
                                    type="number" step="0.1" min="0.1"
                                    className={cl.input}
                                    value={localSx}
                                    onChange={(e) => setLocalSx(e.target.value)}
                                    onBlur={commitResize}
                                    onKeyDown={(e) => { if (e.key === 'Enter') commitResize(); }}
                                />
                            </label>
                            <label className={cl.field}>
                                <span className={cl.axisLabel} style={{color:'#5ae85a'}}>Y</span>
                                <input
                                    type="number" step="0.1" min="0.1"
                                    className={cl.input}
                                    value={localSy}
                                    onChange={(e) => setLocalSy(e.target.value)}
                                    onBlur={commitResize}
                                    onKeyDown={(e) => { if (e.key === 'Enter') commitResize(); }}
                                />
                            </label>
                            <label className={cl.field}>
                                <span className={cl.axisLabel} style={{color:'#5a8ce8'}}>Z</span>
                                <input
                                    type="number" step="0.1" min="0.1"
                                    className={cl.input}
                                    value={localSz}
                                    onChange={(e) => setLocalSz(e.target.value)}
                                    onBlur={commitResize}
                                    onKeyDown={(e) => { if (e.key === 'Enter') commitResize(); }}
                                />
                            </label>
                        </div>
                    </div>

                    {/* Цвет и материал — только для геометрических примитивов */}
                    {primitiveType?.kind === 'geometry' && (
                        <>
                            <div className={cl.section}>
                                <div className={cl.sectionTitle}><Icon name="palette" size={12} /> Цвет</div>
                                <div className={cl.rowFull}>
                                    <input
                                        type="color"
                                        className={cl.input}
                                        value={localColor}
                                        onChange={(e) => {
                                            setLocalColor(e.target.value);
                                            onSetPrimitiveProps?.({ color: e.target.value });
                                        }}
                                        style={{ height: 36, padding: 0, cursor: 'pointer' }}
                                    />
                                </div>
                            </div>

                            <div className={cl.section}>
                                <div className={cl.sectionTitle}><Icon name="sparkles" size={12} /> Материал</div>
                                <div className={cl.row3}>
                                    {PRIMITIVE_MATERIALS.map(m => (
                                        <button
                                            key={m.id}
                                            type="button"
                                            className={cl.smallBtn}
                                            onClick={() => {
                                                setLocalMaterial(m.id);
                                                onSetPrimitiveProps?.({ material: m.id });
                                            }}
                                            style={{
                                                fontWeight: localMaterial === m.id ? 700 : 400,
                                                background: localMaterial === m.id ? 'var(--accent)' : undefined,
                                                color: localMaterial === m.id ? '#fff' : undefined,
                                            }}
                                        >
                                            {m.name}
                                        </button>
                                    ))}
                                </div>
                            </div>

                            {/* Размер studs — плотность лего-кружков (только для material studs) */}
                            {localMaterial === 'studs' && (
                                <div className={cl.section}>
                                    <div className={cl.sectionTitle}><Icon name="grid" size={12} /> Размер studs</div>
                                    <div className={cl.row3}>
                                        {[
                                            { label: 'Крупные', d: 0.5 },
                                            { label: 'Средние', d: 1 },
                                            { label: 'Мелкие', d: 2 },
                                            { label: 'Меньше', d: 4 },
                                        ].map(opt => (
                                            <button
                                                key={opt.d}
                                                type="button"
                                                className={cl.smallBtn}
                                                onClick={() => {
                                                    setLocalStudDensity(opt.d);
                                                    onSetPrimitiveProps?.({ studDensity: opt.d });
                                                }}
                                                style={{
                                                    fontWeight: localStudDensity === opt.d ? 700 : 400,
                                                    background: localStudDensity === opt.d ? 'var(--accent)' : undefined,
                                                    color: localStudDensity === opt.d ? '#fff' : undefined,
                                                }}
                                            >
                                                {opt.label}
                                            </button>
                                        ))}
                                    </div>
                                </div>
                            )}

                            {/* Подпись над объектом (задача 10) */}
                            {(() => {
                                const L = localLabel || { enabled: false, binding: 'static', params: {}, preset: 'gameui', height: 2.5 };
                                const applyLabel = (patch) => {
                                    const next = { ...L, ...patch, params: { ...(L.params || {}), ...(patch.params || {}) } };
                                    setLocalLabel(next);
                                    onSetPrimitiveProps?.({ label: next });
                                };
                                const inp = { background: 'var(--bg-input,#2a1f15)', color: 'var(--text-primary,#f0e6d8)', border: '1px solid var(--border,#5a4a3a)', borderRadius: 4, padding: '3px 6px', fontSize: 12, width: '100%' };
                                return (
                                <div className={cl.section}>
                                    <div className={cl.sectionTitle}><Icon name="type" size={12} /> Подпись над объектом</div>
                                    <label style={{ display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer', padding: '2px 0' }}>
                                        <input type="checkbox" checked={!!L.enabled}
                                            onChange={(e) => applyLabel({ enabled: e.target.checked })} />
                                        <span style={{ fontSize: 13 }}>Показывать подпись</span>
                                    </label>
                                    {L.enabled && (<>
                                        <div style={{ display: 'flex', gap: 6, alignItems: 'center', marginTop: 6 }}>
                                            <span style={{ fontSize: 12, flex: 1 }}>Связать с</span>
                                            <select value={L.binding} onChange={(e) => applyLabel({ binding: e.target.value })} style={{ ...inp, flex: 1.5 }}>
                                                <option value="static">Статический текст</option>
                                                <option value="timer">Таймер</option>
                                                <option value="save">Счётчик из save</option>
                                                <option value="hp">HP</option>
                                                <option value="formula">Своя формула</option>
                                            </select>
                                        </div>
                                        {(L.binding === 'static' || L.binding === 'formula') && (
                                            <input type="text" placeholder="Текст" value={L.params?.text || ''}
                                                onChange={(e) => applyLabel({ params: { text: e.target.value } })}
                                                style={{ ...inp, marginTop: 6 }} />
                                        )}
                                        {L.binding === 'timer' && (
                                            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6, marginTop: 6 }}>
                                                <label style={{ fontSize: 11, display: 'flex', flexDirection: 'column', gap: 2 }}>Секунд
                                                    <input type="number" value={L.params?.duration ?? 960}
                                                        onChange={(e) => applyLabel({ params: { duration: Number(e.target.value) } })} style={inp} /></label>
                                                <label style={{ fontSize: 11, display: 'flex', flexDirection: 'column', gap: 2 }}>Формат
                                                    <select value={L.params?.format || 'mm:ss'} onChange={(e) => applyLabel({ params: { format: e.target.value } })} style={inp}>
                                                        <option value="mm:ss">мм:сс</option>
                                                        <option value="hh:mm:ss">чч:мм:сс</option>
                                                        <option value="auto">авто</option>
                                                    </select></label>
                                                <input type="text" placeholder="Префикс" value={L.params?.prefix || ''}
                                                    onChange={(e) => applyLabel({ params: { prefix: e.target.value } })} style={{ ...inp, gridColumn: '1 / 3' }} />
                                            </div>
                                        )}
                                        {L.binding === 'save' && (
                                            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6, marginTop: 6 }}>
                                                <input type="text" placeholder="Ключ (coins)" value={L.params?.key || ''}
                                                    onChange={(e) => applyLabel({ params: { key: e.target.value } })} style={inp} />
                                                <input type="text" placeholder="Суффикс" value={L.params?.suffix || ''}
                                                    onChange={(e) => applyLabel({ params: { suffix: e.target.value } })} style={inp} />
                                            </div>
                                        )}
                                        <div style={{ display: 'flex', gap: 6, alignItems: 'center', marginTop: 6 }}>
                                            <span style={{ fontSize: 12, flex: 1 }}>Стиль</span>
                                            <select value={L.preset || 'gameui'} onChange={(e) => applyLabel({ preset: e.target.value })} style={{ ...inp, flex: 1.5 }}>
                                                <option value="gameui">Игровой (синий/жёлтый)</option>
                                                <option value="warning">Предупреждение</option>
                                                <option value="reward">Награда (золото)</option>
                                                <option value="boss-hp">Босс HP</option>
                                                <option value="plain">Простой</option>
                                            </select>
                                        </div>
                                        <div style={{ display: 'flex', gap: 6, alignItems: 'center', marginTop: 6 }}>
                                            <span style={{ fontSize: 12, flex: 1 }}>Крепление</span>
                                            <select value={L.attachFace || 'over'}
                                                onChange={(e) => {
                                                    const v = e.target.value;
                                                    // 'over' — billboard над верхом (к камере); иначе — на грань.
                                                    applyLabel({ attachFace: v === 'over' ? null : v });
                                                }}
                                                style={{ ...inp, flex: 1.5 }}>
                                                <option value="over">Над объектом (к камере)</option>
                                                <option value="front">На грань: перёд</option>
                                                <option value="back">На грань: зад</option>
                                                <option value="left">На грань: лево</option>
                                                <option value="right">На грань: право</option>
                                                <option value="top">На грань: верх</option>
                                                <option value="bottom">На грань: низ</option>
                                            </select>
                                        </div>
                                        <label style={{ fontSize: 11, display: 'flex', flexDirection: 'column', gap: 2, marginTop: 6 }}>
                                            {L.attachFace ? 'Отступ от грани' : 'Высота над объектом'}
                                            <input type="number" step={L.attachFace ? 0.05 : 0.5}
                                                value={L.height ?? (L.attachFace ? 0.05 : 2.5)}
                                                onChange={(e) => applyLabel({ height: Number(e.target.value) })} style={inp} /></label>
                                    </>)}
                                </div>
                                );
                            })()}

                            {/* Текстура — своя картинка на гранях примитива */}
                            <div className={cl.section}>
                                <div className={cl.sectionTitle}>
                                    <Icon name="image" size={12} /> Текстура
                                </div>
                                <AssetPicker
                                    assetList={assetList}
                                    value={selection.textureAsset || null}
                                    onPick={(id) => onSetPrimitiveProps?.({ textureAsset: id })}
                                    onUpload={onUploadAsset}
                                    onRemove={onRemoveAsset}
                                />
                            </div>
                        </>
                    )}

                    {/* Лампа — цвет, яркость, радиус свечения */}
                    {primitiveType?.kind === 'light' && (
                        <div className={cl.section}>
                            <div className={cl.sectionTitle}><Icon name="sparkle" size={12} /> Лампа</div>
                            <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '4px 0' }}>
                                <span style={{ fontSize: 12, flex: 1 }}>Цвет света</span>
                                <input
                                    type="color"
                                    value={localColor || '#ffe9a0'}
                                    onChange={(e) => {
                                        setLocalColor(e.target.value);
                                        onSetPrimitiveProps?.({ color: e.target.value });
                                    }}
                                    style={{ width: 36, height: 24, padding: 0, border: 'none', background: 'transparent', cursor: 'pointer' }}
                                />
                            </div>
                            <div style={{ padding: '4px 0' }}>
                                <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 }}>
                                    <span>Яркость</span>
                                    <span style={{ opacity: 0.6 }}>{Number(localBrightness).toFixed(1)}</span>
                                </div>
                                <input
                                    type="range" min="0" max="6" step="0.25"
                                    value={localBrightness}
                                    onChange={(e) => {
                                        const v = parseFloat(e.target.value);
                                        setLocalBrightness(v);
                                        onSetPrimitiveProps?.({ brightness: v });
                                    }}
                                    style={{ width: '100%' }}
                                />
                            </div>
                            <div style={{ padding: '4px 0' }}>
                                <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 }}>
                                    <span>Радиус (м)</span>
                                    <span style={{ opacity: 0.6 }}>{Math.round(localRange)}</span>
                                </div>
                                <input
                                    type="range" min="2" max="50" step="1"
                                    value={localRange}
                                    onChange={(e) => {
                                        const v = parseFloat(e.target.value);
                                        setLocalRange(v);
                                        onSetPrimitiveProps?.({ range: v });
                                    }}
                                    style={{ width: '100%' }}
                                />
                            </div>
                        </div>
                    )}

                    {/* Эмиттер частиц — выбор эффекта + цвет */}
                    {primitiveType?.kind === 'emitter' && (
                        <div className={cl.section}>
                            <div className={cl.sectionTitle}><Icon name="sparkle" size={12} /> Эффект частиц</div>
                            <div className={cl.row3}>
                                {[
                                    { id: 'fire',   name: 'Огонь' },
                                    { id: 'smoke',  name: 'Дым' },
                                    { id: 'sparks', name: 'Искры' },
                                    { id: 'magic',  name: 'Магия' },
                                ].map(eff => (
                                    <button
                                        key={eff.id}
                                        type="button"
                                        className={cl.smallBtn}
                                        onClick={() => onSetPrimitiveProps?.({ effect: eff.id })}
                                        style={{
                                            fontWeight: (selection.effect || 'fire') === eff.id ? 700 : 400,
                                            background: (selection.effect || 'fire') === eff.id ? 'var(--accent)' : undefined,
                                            color: (selection.effect || 'fire') === eff.id ? '#fff' : undefined,
                                        }}
                                    >
                                        {eff.name}
                                    </button>
                                ))}
                            </div>
                            <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '6px 0' }}>
                                <span style={{ fontSize: 12, flex: 1 }}>Цвет частиц</span>
                                <input
                                    type="color"
                                    value={localColor || '#ff8833'}
                                    onChange={(e) => {
                                        setLocalColor(e.target.value);
                                        onSetPrimitiveProps?.({ color: e.target.value });
                                    }}
                                    style={{ width: 36, height: 24, padding: 0, border: 'none', background: 'transparent', cursor: 'pointer' }}
                                />
                            </div>
                        </div>
                    )}

                    {/* 3D-табличка (billboard) — кнопка «Редактировать табличку» */}
                    {primitiveType?.kind === 'billboard' && (
                        <div className={cl.section}>
                            <div className={cl.sectionTitle}><Icon name="prim-billboard" size={12} /> Контент таблички</div>
                            <button
                                type="button"
                                className={cl.smallBtn}
                                onClick={() => onEditBillboard?.()}
                                style={{ width: '100%', padding: '8px 12px', fontWeight: 600 }}
                            >
                                Редактировать табличку…
                            </button>
                            <div style={{ fontSize: 11, color: '#9ca3af', marginTop: 6, lineHeight: 1.4 }}>
                                {(selection.template || 'shop-item')} · {(selection.face || 'camera') === 'camera' ? 'смотрит на камеру' : 'фиксирована'}
                            </div>
                        </div>
                    )}

                    {/* Стрелка-указатель (задача 08) — пресет, источник, цель, дуга */}
                    {primitiveType?.kind === 'pointer' && (
                        <div className={cl.section}>
                            <div className={cl.sectionTitle}><Icon name="arrow-right" size={12} /> Стрелка-указатель</div>
                            {/* Пресет внешнего вида */}
                            <div style={{ fontSize: 12, marginBottom: 4 }}>Стиль</div>
                            <div className={cl.row3}>
                                {[
                                    { id: 'guide',  name: 'Красная' },
                                    { id: 'quest',  name: 'Жёлтая' },
                                    { id: 'danger', name: 'Молнии' },
                                    { id: 'gift',   name: 'Радуга' },
                                ].map(pr => (
                                    <button
                                        key={pr.id}
                                        type="button"
                                        className={cl.smallBtn}
                                        onClick={() => onSetPrimitiveProps?.({ pointerPreset: pr.id })}
                                        style={{
                                            fontWeight: (selection.pointerPreset || 'guide') === pr.id ? 700 : 400,
                                            background: (selection.pointerPreset || 'guide') === pr.id ? 'var(--accent)' : undefined,
                                            color: (selection.pointerPreset || 'guide') === pr.id ? '#fff' : undefined,
                                        }}
                                    >
                                        {pr.name}
                                    </button>
                                ))}
                            </div>
                            {/* Откуда */}
                            <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '6px 0' }}>
                                <span style={{ fontSize: 12, flex: 1 }}>Откуда</span>
                                <select
                                    value={selection.pointerFrom ?? 'player'}
                                    onChange={(e) => onSetPrimitiveProps?.({ pointerFrom: e.target.value })}
                                    style={{ flex: 1.4 }}
                                >
                                    <option value="player">Игрок</option>
                                    <option value="">Эта точка</option>
                                </select>
                            </div>
                            {/* Куда — id объекта-цели или эта точка */}
                            <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '6px 0' }}>
                                <span style={{ fontSize: 12, flex: 1 }}>Куда (id)</span>
                                <input
                                    type="text"
                                    placeholder="напр. 42 или player"
                                    value={selection.pointerTo ?? ''}
                                    onChange={(e) => onSetPrimitiveProps?.({ pointerTo: e.target.value })}
                                    style={{ flex: 1.4, fontSize: 12, padding: '4px 6px' }}
                                />
                            </div>
                            <div style={{ fontSize: 11, color: '#9ca3af', marginTop: 2, lineHeight: 1.4 }}>
                                Пусто = стрелка указывает вперёд (+4 по Z). Можно вписать id примитива/модели или «player».
                            </div>
                            {/* Скорость анимации текстуры */}
                            <div style={{ padding: '6px 0' }}>
                                <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 }}>
                                    <span>Скорость бега</span>
                                    <span style={{ opacity: 0.6 }}>{(selection.textureSpeed ?? 3)}</span>
                                </div>
                                <input
                                    type="range" min="0" max="8" step="0.5"
                                    value={selection.textureSpeed ?? 3}
                                    onChange={(e) => onSetPrimitiveProps?.({ textureSpeed: parseFloat(e.target.value) })}
                                    style={{ width: '100%' }}
                                />
                            </div>
                            {/* Дугой */}
                            <label style={{ display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer', padding: '4px 0' }}>
                                <input type="checkbox"
                                    checked={!!selection.curved}
                                    onChange={(e) => onSetPrimitiveProps?.({ curved: e.target.checked })} />
                                <span style={{ fontSize: 12 }}>Изогнуть дугой</span>
                            </label>
                            {selection.curved && (
                                <div style={{ padding: '4px 0' }}>
                                    <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 }}>
                                        <span>Высота дуги</span>
                                        <span style={{ opacity: 0.6 }}>{(selection.curveHeight ?? 2)}</span>
                                    </div>
                                    <input
                                        type="range" min="1" max="10" step="0.5"
                                        value={selection.curveHeight ?? 2}
                                        onChange={(e) => onSetPrimitiveProps?.({ curveHeight: parseFloat(e.target.value) })}
                                        style={{ width: '100%' }}
                                    />
                                </div>
                            )}
                            <div style={{ fontSize: 11, color: '#9ca3af', marginTop: 6, fontStyle: 'italic', lineHeight: 1.4 }}>
                                Стрелка появляется при запуске игры (▶). В редакторе показан маркер позиции.
                            </div>
                        </div>
                    )}

                    {/* Свойства — для всех примитивов */}
                    <div className={cl.section}>
                        <div className={cl.sectionTitle}><Icon name="settings" size={12} /> Свойства</div>
                        <label style={{ display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer', padding: '4px 0' }}>
                            <input type="checkbox"
                                checked={localCanCollide}
                                onChange={(e) => {
                                    setLocalCanCollide(e.target.checked);
                                    onSetPrimitiveProps?.({ canCollide: e.target.checked });
                                }} />
                            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}><Icon name="shield" size={12} /> Сталкивается</span>
                        </label>
                        <label style={{ display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer', padding: '4px 0' }}>
                            <input type="checkbox"
                                checked={localVisible}
                                onChange={(e) => {
                                    setLocalVisible(e.target.checked);
                                    onSetPrimitiveProps?.({ visible: e.target.checked });
                                }} />
                            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}><Icon name="visible" size={12} /> Видимый</span>
                        </label>
                        {/* Заблокировать — защита от выделения/перемещения (Фаза 5.11). */}
                        <label style={{ display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer', padding: '4px 0' }}>
                            <input type="checkbox"
                                checked={!!selection.locked}
                                onChange={(e) => onSetPrimitiveProps?.({ locked: e.target.checked })} />
                            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
                                <Icon name="settings" size={12} /> Заблокировать
                            </span>
                        </label>
                    </div>
                </>
            )}

            {/* Физика — для всех типов кроме spawn */}
            {!isSpawn && !isLiquid && (
                <div className={cl.section}>
                    <div className={cl.sectionTitle}><Icon name="anchor" size={12} /> Физика</div>
                    <label style={{ display: 'flex', gap: 8, alignItems: 'center', cursor: 'pointer', padding: '4px 0' }}>
                        <input
                            type="checkbox"
                            checked={localAnchored}
                            onChange={(e) => {
                                setLocalAnchored(e.target.checked);
                                onSetAnchored?.(e.target.checked);
                            }}
                        />
                        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}><Icon name="anchor" size={12} /> Заякорен</span>
                    </label>
                    <div style={{ fontSize: 11, color: 'var(--text-dim)', padding: '2px 0 6px 26px', lineHeight: 1.4 }}>
                        {localAnchored
                            ? 'Объект неподвижен. В режиме игры стоит на месте.'
                            : 'Объект падает под гравитацией и реагирует на столкновения.'}
                    </div>
                    {!localAnchored && (
                        <>
                            <div className={cl.row}>
                                <label className={cl.label} style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}><Icon name="sliders" size={12} /> Вес</label>
                                <input
                                    type="number"
                                    className={cl.input}
                                    step="0.1"
                                    min="0.1"
                                    value={localMass}
                                    onChange={(e) => setLocalMass(e.target.value)}
                                    onBlur={() => {
                                        const m = parseFloat(localMass);
                                        if (Number.isFinite(m) && m > 0) {
                                            const rounded = Math.round(m * 100) / 100;
                                            onSetMass?.(rounded);
                                            setLocalMass(formatMass(rounded));
                                        } else {
                                            setLocalMass(formatMass(selection.mass ?? 1));
                                        }
                                    }}
                                />
                            </div>
                            <div style={{ fontSize: 11, color: 'var(--text-dim)', padding: '2px 0 0 26px', lineHeight: 1.4 }}>
                                Чем больше вес, тем слабее толкается. Мячик 0.1, ящик 1, валун 10.
                            </div>
                        </>
                    )}
                </div>
            )}


            {/* Действия */}
            <div className={cl.actions}>
                <button className={cl.actionBtn} onClick={onFocus} title="Сфокусировать камеру" style={{ display: 'inline-flex', alignItems: 'center', gap: 4, justifyContent: 'center' }}>
                    <Icon name="target" size={13} /> Фокус
                </button>
                {/* Спавн и освещение нельзя удалить */}
                {!isSpawn && !isLighting && !isScript && (
                    <button className={`${cl.actionBtn} ${cl.deleteBtn}`} onClick={onDelete} style={{ display: 'inline-flex', alignItems: 'center', gap: 4, justifyContent: 'center' }}>
                        <Icon name="delete" size={13} /> Удалить
                    </button>
                )}
            </div>

            <div className={cl.hint}>
                <Icon name="sparkle" size={11} /> R — поворот · Del — удалить · Esc — снять выделение
            </div>
        </div>
    );
};

export default InspectorPanel;
