/* ============================================================
   Rigging — Rigging View (Phase 7)
   
   Three sub-tabs: Vehicles, Drones, RCC Status.
   Nuyen ribbon across the top mirrors the Gear view. Control rig
   rating from cyberware is surfaced here since it's central to
   rigger mechanics.
   ============================================================ */
const { useState, useEffect, useRef, useMemo, useCallback, Fragment } = React;

window.RiggingView = function RiggingView({ character, onChange }) {
    const C = SR5_CALC;
    const V = SR5_VEHICLES;
    const [subtab, setSubtab] = useState('vehicles');

    const nuyenTotal = C.startingNuyen(character);
    const spent = C.nuyenSpent(character);
    const remaining = C.nuyenRemaining(character);
    const vehicles = C.characterVehicles(character);
    const drones = C.characterDrones(character);
    const rccs = C.characterRCCs(character);
    const rigRating = C.controlRigRating(character);

    if (nuyenTotal === 0) {
        return (
            <>
                <ContentHeader title="09 / Rigging" heading="Vehicles · Drones · RCCs" />
                <div className="card"><div className="card-body muted">
                    Assign a priority letter to <strong className="accent">Resources</strong> first. That's what gives you starting nuyen to buy vehicles, drones, and rigger gear.
                </div></div>
            </>
        );
    }

    const nuyenStateRemaining = remaining < 0 ? 'over' : (remaining === 0 ? 'done' : 'free');

    return (
        <>
            <ContentHeader title="09 / Rigging" heading="Vehicles · Drones · RCCs" />

            <div className="nuyen-summary">
                <div className="nuyen-stat">
                    <span className="n-label">Starting Nuyen</span>
                    <span className="n-value">{nuyenTotal.toLocaleString()}¥</span>
                </div>
                <div className="nuyen-stat">
                    <span className="n-label">Spent</span>
                    <span className="n-value">{spent.toLocaleString()}¥</span>
                </div>
                <div className={`nuyen-stat remaining ${nuyenStateRemaining}`}>
                    <span className="n-label">Remaining</span>
                    <span className="n-value">{remaining.toLocaleString()}¥</span>
                </div>
                <div className="nuyen-stat">
                    <span className="n-label">Control Rig</span>
                    <span className="n-value" style={{ color: rigRating > 0 ? 'var(--accent)' : 'var(--text-muted)' }}>
                        {rigRating > 0 ? `R${rigRating}` : '—'}
                    </span>
                </div>
            </div>

            <div className="gear-tabs">
                <button className={`gear-tab ${subtab === 'vehicles' ? 'active' : ''}`}
                        onClick={() => setSubtab('vehicles')}>
                    Vehicles <span className="tab-count">{vehicles.length}</span>
                </button>
                <button className={`gear-tab ${subtab === 'drones' ? 'active' : ''}`}
                        onClick={() => setSubtab('drones')}>
                    Drones <span className="tab-count">{drones.length}</span>
                </button>
                <button className={`gear-tab ${subtab === 'rcc' ? 'active' : ''}`}
                        onClick={() => setSubtab('rcc')}>
                    RCC Status <span className="tab-count">{rccs.length}</span>
                </button>
            </div>

            {subtab === 'vehicles' && (
                <VehiclesTab character={character} onChange={onChange} />
            )}
            {subtab === 'drones' && (
                <DronesTab character={character} onChange={onChange} />
            )}
            {subtab === 'rcc' && (
                <RCCStatusTab character={character} onChange={onChange} />
            )}

            <div className="phase-note" style={{ marginTop: 20 }}>
                <strong>Phase 7.</strong> Rigger core — {V.VEHICLES.length} vehicles across 5 categories,
                {' '}{V.DRONES.length} drones across 5 size classes, 6 autosoft types. Control rigs are
                detected automatically from your cyberware. RCC stats (Device Rating, Data Processing,
                Firewall) are shown on the RCC Status tab. Vehicle modifications and Rigger 5.0 content
                are deferred to a future polish pass.
            </div>
        </>
    );
};

/* ============================================================
   VehiclesTab — owned vehicles with picker + custom
   ============================================================ */
window.VehiclesTab = function VehiclesTab({ character, onChange }) {
    const C = SR5_CALC;
    const V = SR5_VEHICLES;
    const [pickerOpen, setPickerOpen] = useState(false);
    const [customOpen, setCustomOpen] = useState(false);

    const inCareer = C.isCareerMode(character);
    const pendingGear = inCareer ? window.CareerGear.pendingOfKind(character, 'vehicle') : [];

    const vehicles = C.characterVehicles(character);

    function onPick(tpl) {
        if (inCareer) {
            const cost = tpl.cost || 0;
            if (!window.CareerGear.canAfford(character, cost)) {
                alert(`Not enough nuyen: ${tpl.name} costs ${cost.toLocaleString()}¥.`);
                return;
            }
            onChange(C.stagePendingGear(character, {
                kind: 'vehicle',
                templateKey: tpl.key,
                name: tpl.name,
                nuyenCost: cost,
            }));
        } else {
            onChange(C.addVehicleFromTemplate(character, tpl.key));
        }
        setPickerOpen(false);
    }
    function onCustomSubmit(payload) {
        onChange(C.addCustomVehicle(character, payload));
        setCustomOpen(false);
    }
    function onRemove(id) {
        if (inCareer) { alert("Totaled/sold? Log it in the career log."); return; }
        onChange(C.removeVehicle(character, id));
    }
    function onUnstage(tempId) {
        onChange(C.unstagePendingGear(character, tempId));
    }
    function onUpdateNotes(id, notes) {
        if (inCareer) return;
        onChange(C.updateVehicle(character, id, { notes }));
    }

    return (
        <>
            <div className="card">
                <div className="card-header">
                    <h3 className="card-title">Owned vehicles</h3>
                    <div className="card-actions">
                        <button className="btn btn-primary" onClick={() => setPickerOpen(true)}>+ Browse Vehicles</button>
                        {!inCareer && (
                            <button className="btn btn-ghost" onClick={() => setCustomOpen(true)}>+ Custom</button>
                        )}
                    </div>
                </div>
                <div className="card-body" style={{ padding: 0 }}>
                    {vehicles.length === 0 && pendingGear.length === 0 ? (
                        <div className="spell-empty">
                            No vehicles yet. Browse the Core Rulebook catalog or add a custom vehicle.
                            Bikes are cheap, trucks make great mobile bases, and aircraft need a pilot skill
                            with specializations for airplanes or rotorcraft.
                        </div>
                    ) : (
                        <>
                            <div className="veh-head">
                                <span>Name / Category</span>
                                <span>Hand</span>
                                <span>Spd</span>
                                <span>Acl</span>
                                <span>Body</span>
                                <span>Arm</span>
                                <span>Pilot</span>
                                <span>Sens</span>
                                <span>Seats</span>
                                <span>Cost</span>
                                <span></span>
                            </div>
                            {vehicles.map(v => (
                                <VehicleRow key={v.id} vehicle={v} onRemove={onRemove} onUpdateNotes={onUpdateNotes} inCareer={inCareer} />
                            ))}
                            {pendingGear.map(pg => {
                                const tpl = V.findVehicle(pg.templateKey) || {};
                                return (
                                    <div className="veh-row pending-new" key={pg.tempId}>
                                        <div className="veh-name">
                                            <span className="vn-name">{pg.name}</span>
                                            <span className="gear-pending-tag">pending</span>
                                        </div>
                                        <div className="veh-stat">{tpl.handling || '—'}</div>
                                        <div className="veh-stat">{tpl.speed || '—'}</div>
                                        <div className="veh-stat">{tpl.accel || '—'}</div>
                                        <div className="veh-stat">{tpl.body || '—'}</div>
                                        <div className="veh-stat">{tpl.armor || '—'}</div>
                                        <div className="veh-stat">{tpl.pilot || '—'}</div>
                                        <div className="veh-stat">{tpl.sensor || '—'}</div>
                                        <div className="veh-stat">{tpl.seats || '—'}</div>
                                        <div className="veh-cost mono" style={{ color: 'var(--accent)' }}>{(pg.nuyenCost || 0).toLocaleString()}¥</div>
                                        <button className="btn-row-remove" onClick={() => onUnstage(pg.tempId)} title="Discard pending">×</button>
                                    </div>
                                );
                            })}
                        </>
                    )}
                </div>
            </div>

            {pickerOpen && (
                <VehiclePickerModal
                    character={character}
                    onPick={onPick}
                    onClose={() => setPickerOpen(false)}
                />
            )}
            {customOpen && (
                <CustomVehicleDialog
                    onSubmit={onCustomSubmit}
                    onClose={() => setCustomOpen(false)}
                />
            )}
        </>
    );
};

/* Vehicle row */
window.VehicleRow = function VehicleRow({ vehicle, onRemove, onUpdateNotes, inCareer }) {
    return (
        <div className={`veh-row veh-${vehicle.category}`}>
            <div className="veh-name">
                <span className="vn-name">{vehicle.name}</span>
                <span className="vn-cat muted">{vehicle.category}</span>
            </div>
            <div className="veh-stat">{vehicle.handling}</div>
            <div className="veh-stat">{vehicle.speed}</div>
            <div className="veh-stat">{vehicle.accel}</div>
            <div className="veh-stat">{vehicle.body}</div>
            <div className="veh-stat">{vehicle.armor}</div>
            <div className="veh-stat">{vehicle.pilot}</div>
            <div className="veh-stat">{vehicle.sensor}</div>
            <div className="veh-stat">{vehicle.seats || '—'}</div>
            <div className="veh-cost mono">{(vehicle.nuyen || 0).toLocaleString()}¥</div>
            <button className="btn-row-remove" onClick={() => onRemove(vehicle.id)} title={inCareer ? "Use career log" : "Remove"}>×</button>
            <div className="veh-details">
                <span className="muted">{vehicle.description}</span>
                <span className="mono muted" style={{ marginLeft: 12 }}>{vehicle.source}</span>
                {vehicle.avail && (
                    <span className="mono muted" style={{ marginLeft: 12 }}>avail: {vehicle.avail}</span>
                )}
            </div>
            <div className="veh-notes">
                <TextInput
                    value={vehicle.notes || ''}
                    onChange={v => onUpdateNotes(vehicle.id, v)}
                    placeholder="Notes (plates, upgrades, nickname...)"
                    maxLength={200}
                    disabled={inCareer}
                />
            </div>
        </div>
    );
};

/* ============================================================
   DronesTab — owned drones + autosofts
   ============================================================ */
window.DronesTab = function DronesTab({ character, onChange }) {
    const C = SR5_CALC;
    const V = SR5_VEHICLES;
    const [pickerOpen, setPickerOpen] = useState(false);
    const [customOpen, setCustomOpen] = useState(false);
    const [autosoftTarget, setAutosoftTarget] = useState(null);

    const inCareer = C.isCareerMode(character);
    const pendingDrones = inCareer ? window.CareerGear.pendingOfKind(character, 'drone') : [];
    const pendingAutosofts = inCareer ? window.CareerGear.pendingOfKind(character, 'autosoft') : [];

    const drones = C.characterDrones(character);

    function onPick(tpl) {
        if (inCareer) {
            const cost = tpl.cost || 0;
            if (!window.CareerGear.canAfford(character, cost)) {
                alert(`Not enough nuyen: ${tpl.name} costs ${cost.toLocaleString()}¥.`);
                return;
            }
            onChange(C.stagePendingGear(character, {
                kind: 'drone',
                templateKey: tpl.key,
                name: tpl.name,
                nuyenCost: cost,
            }));
        } else {
            onChange(C.addDroneFromTemplate(character, tpl.key));
        }
        setPickerOpen(false);
    }
    function onCustomSubmit(payload) {
        onChange(C.addCustomDrone(character, payload));
        setCustomOpen(false);
    }
    function onRemove(id) {
        if (inCareer) { alert("Destroyed/sold? Log it in the career log."); return; }
        onChange(C.removeDrone(character, id));
    }
    function onUnstage(tempId) {
        onChange(C.unstagePendingGear(character, tempId));
    }
    function onAddAutosoft(payload) {
        if (inCareer) {
            const cost = payload.cost || 0;
            if (!window.CareerGear.canAfford(character, cost)) {
                alert(`Not enough nuyen: ${payload.name} costs ${cost.toLocaleString()}¥.`);
                return;
            }
            onChange(C.stagePendingGear(character, {
                kind: 'autosoft',
                name: payload.name,
                nuyenCost: cost,
                extras: { ...payload, parentDroneId: autosoftTarget },
            }));
        } else {
            onChange(C.addAutosoftToDrone(character, autosoftTarget, payload));
        }
        setAutosoftTarget(null);
    }
    function onRemoveAutosoft(droneId, autosoftId) {
        if (inCareer) { alert("Can't uninstall autosofts in career mode."); return; }
        onChange(C.removeAutosoftFromDrone(character, droneId, autosoftId));
    }

    const bySize = V.DRONE_SIZES.map(s => ({
        size: s,
        drones: drones.filter(d => d.droneSize === s.key),
    })).filter(g => g.drones.length > 0);

    return (
        <>
            <div className="card">
                <div className="card-header">
                    <h3 className="card-title">Owned drones</h3>
                    <div className="card-actions">
                        <button className="btn btn-primary" onClick={() => setPickerOpen(true)}>+ Browse Drones</button>
                        {!inCareer && (
                            <button className="btn btn-ghost" onClick={() => setCustomOpen(true)}>+ Custom</button>
                        )}
                    </div>
                </div>
                <div className="card-body" style={{ padding: 0 }}>
                    {drones.length === 0 && pendingDrones.length === 0 ? (
                        <div className="spell-empty">
                            No drones yet. Micro drones like the Fly-Spy are cheap scouts; the Doberman
                            and Roto-Drone are medium workhorses; the Steel Lynx is a restricted combat
                            drone. Buy autosofts per-drone — Clearsight, Maneuvering, Targeting, etc.
                        </div>
                    ) : (
                        <>
                            {bySize.map(({ size, drones: ds }) => (
                                <Fragment key={size.key}>
                                    <div className="drone-size-head">{size.label}</div>
                                    {ds.map(d => (
                                        <DroneRow
                                            key={d.id}
                                            drone={d}
                                            onRemove={onRemove}
                                            onAddAutosoft={() => setAutosoftTarget(d.id)}
                                            onRemoveAutosoft={onRemoveAutosoft}
                                            pendingAutosofts={pendingAutosofts.filter(a => a.extras?.parentDroneId === d.id)}
                                            onUnstageAutosoft={onUnstage}
                                            inCareer={inCareer}
                                        />
                                    ))}
                                </Fragment>
                            ))}
                            {pendingDrones.map(pg => {
                                const tpl = V.findDrone ? V.findDrone(pg.templateKey) : null;
                                return (
                                    <div className="drone-row pending-new" key={pg.tempId}>
                                        <div className="drone-head">
                                            <div className="dr-name">
                                                {pg.name}
                                                <span className="gear-pending-tag">pending</span>
                                            </div>
                                            <div className="dr-stats mono">
                                                {tpl && (
                                                    <>
                                                        <span>Hand {tpl.handling}</span>
                                                        <span>Spd {tpl.speed}</span>
                                                        <span>Body {tpl.body}</span>
                                                        <span>Arm {tpl.armor}</span>
                                                        <span>Pilot {tpl.pilot}</span>
                                                    </>
                                                )}
                                            </div>
                                            <div className="dr-cost mono" style={{ color: 'var(--accent)' }}>{(pg.nuyenCost || 0).toLocaleString()}¥</div>
                                            <button className="btn-row-remove" onClick={() => onUnstage(pg.tempId)} title="Discard pending">×</button>
                                        </div>
                                        <div className="dr-desc muted">(pending — autosofts can be added after commit)</div>
                                    </div>
                                );
                            })}
                        </>
                    )}
                </div>
            </div>

            {pickerOpen && (
                <DronePickerModal
                    character={character}
                    onPick={onPick}
                    onClose={() => setPickerOpen(false)}
                />
            )}
            {customOpen && (
                <CustomDroneDialog
                    onSubmit={onCustomSubmit}
                    onClose={() => setCustomOpen(false)}
                />
            )}
            {autosoftTarget && (
                <AutosoftPickerModal
                    droneName={drones.find(d => d.id === autosoftTarget)?.name || ''}
                    onSubmit={onAddAutosoft}
                    onClose={() => setAutosoftTarget(null)}
                />
            )}
        </>
    );
};

window.DroneRow = function DroneRow({ drone, onRemove, onAddAutosoft, onRemoveAutosoft, pendingAutosofts, onUnstageAutosoft, inCareer }) {
    const autosofts = drone.autosofts || [];
    const pending = pendingAutosofts || [];
    const autosoftCost = autosofts.reduce((s, a) => s + (a.cost || 0), 0);

    return (
        <div className="drone-row">
            <div className="drone-head">
                <div className="dr-name">{drone.name}</div>
                <div className="dr-stats mono">
                    <span>Hand {drone.handling}</span>
                    <span>Spd {drone.speed}</span>
                    <span>Acl {drone.accel}</span>
                    <span>Body {drone.body}</span>
                    <span>Arm {drone.armor}</span>
                    <span>Pilot {drone.pilot}</span>
                    <span>Sens {drone.sensor}</span>
                </div>
                <div className="dr-cost mono">
                    {((drone.nuyen || 0) + autosoftCost).toLocaleString()}¥
                    {autosofts.length > 0 && (
                        <span className="muted"> (drone {drone.nuyen.toLocaleString()} + softs {autosoftCost.toLocaleString()})</span>
                    )}
                </div>
                <button className="btn-row-remove" onClick={() => onRemove(drone.id)} title={inCareer ? "Use career log" : "Remove"}>×</button>
            </div>
            <div className="dr-desc">{drone.description}</div>

            <div className="dr-autosofts">
                <div className="dr-autosofts-head">
                    <span className="muted mono">Autosofts ({autosofts.length}{pending.length ? ` + ${pending.length} pending` : ''})</span>
                    <button className="btn btn-ghost btn-small" onClick={onAddAutosoft}>+ Add Autosoft</button>
                </div>
                {autosofts.length === 0 && pending.length === 0 ? (
                    <div className="muted dr-no-autosofts">No autosofts installed. This drone's Pilot will use its own rating for uncoached actions.</div>
                ) : (
                    <div className="dr-autosoft-list">
                        {autosofts.map(a => (
                            <div key={a.id} className="dr-autosoft-row">
                                <span className="dr-as-name">{a.name}</span>
                                <span className="mono dr-as-rating">R{a.rating}</span>
                                {a.weaponKey && <span className="dr-as-spec muted">[{a.weaponKey}]</span>}
                                {a.modelKey && <span className="dr-as-spec muted">[{a.modelKey}]</span>}
                                <span className="mono dr-as-cost">{(a.cost || 0).toLocaleString()}¥</span>
                                <button className="btn-row-remove" onClick={() => onRemoveAutosoft(drone.id, a.id)} title={inCareer ? "Can't uninstall in career" : "Remove"}>×</button>
                            </div>
                        ))}
                        {pending.map(pa => (
                            <div key={pa.tempId} className="dr-autosoft-row pending-new">
                                <span className="dr-as-name">
                                    {pa.name}
                                    <span className="gear-pending-tag">pending</span>
                                </span>
                                <span className="mono dr-as-rating">R{pa.extras?.rating || '?'}</span>
                                {pa.extras?.weaponKey && <span className="dr-as-spec muted">[{pa.extras.weaponKey}]</span>}
                                {pa.extras?.modelKey && <span className="dr-as-spec muted">[{pa.extras.modelKey}]</span>}
                                <span className="mono dr-as-cost" style={{ color: 'var(--accent)' }}>{(pa.nuyenCost || 0).toLocaleString()}¥</span>
                                <button className="btn-row-remove" onClick={() => onUnstageAutosoft(pa.tempId)} title="Discard pending">×</button>
                            </div>
                        ))}
                    </div>
                )}
            </div>
        </div>
    );
};

/* ============================================================
   RCCStatusTab — shows owned RCCs with their stats
   ============================================================ */
window.RCCStatusTab = function RCCStatusTab({ character, onChange }) {
    const C = SR5_CALC;
    const V = SR5_VEHICLES;
    const rccs = C.characterRCCs(character);
    const drones = C.characterDrones(character);

    if (rccs.length === 0) {
        return (
            <div className="card">
                <div className="card-body muted" style={{ padding: 24 }}>
                    No RCCs owned. Buy a Rigger Command Console in the <strong className="accent">Gear → Electronics</strong> tab.
                    {' '}Options: Hermes Electro (4,000¥, entry), Microdeck Trident (48,000¥, mid-tier),
                    {' '}Proteus Poseidon (190,000¥, pro).
                    <br /><br />
                    <span style={{ fontSize: 12 }}>
                        Without an RCC you can still remote-control drones via a commlink, but you lose the
                        noise reduction, shared autosofts, and the ability to jump directly into drones.
                    </span>
                </div>
            </div>
        );
    }

    return (
        <div className="card">
            <div className="card-header">
                <h3 className="card-title">Owned RCCs</h3>
            </div>
            <div className="card-body">
                {rccs.map(rcc => {
                    const stats = V.findRCC(rcc.key);
                    return (
                        <div key={rcc.id} className="rcc-card">
                            <div className="rcc-head">
                                <div className="rcc-name">{rcc.name}</div>
                                <div className="rcc-source muted mono">{rcc.source}</div>
                            </div>
                            {stats && (
                                <div className="rcc-grid">
                                    <div className="rcc-stat">
                                        <div className="rcc-lbl">Device Rating</div>
                                        <div className="rcc-val">{stats.deviceRating}</div>
                                    </div>
                                    <div className="rcc-stat">
                                        <div className="rcc-lbl">Data Processing</div>
                                        <div className="rcc-val">{stats.dataProcessing}</div>
                                    </div>
                                    <div className="rcc-stat">
                                        <div className="rcc-lbl">Firewall</div>
                                        <div className="rcc-val">{stats.firewall}</div>
                                    </div>
                                    <div className="rcc-stat">
                                        <div className="rcc-lbl">Noise −</div>
                                        <div className="rcc-val">{stats.deviceRating}</div>
                                    </div>
                                    <div className="rcc-stat">
                                        <div className="rcc-lbl">Autosoft slots</div>
                                        <div className="rcc-val">{stats.dataProcessing}</div>
                                    </div>
                                </div>
                            )}
                            <div className="rcc-hint muted">
                                Reduces area noise by Device Rating. Can share up to Data Processing autosofts
                                across all slaved drones simultaneously. Slaved drones use the RCC's Firewall
                                for defense against Matrix attacks.
                            </div>
                        </div>
                    );
                })}

                {drones.length > 0 && (
                    <div className="rcc-drones">
                        <div className="rcc-drones-head">You own {drones.length} drone{drones.length === 1 ? '' : 's'}</div>
                        <div className="muted" style={{ fontSize: 12 }}>
                            In play, slave drones to your RCC with a Simple Action. The RCC's Firewall will
                            then protect the whole drone PAN from Matrix attacks.
                        </div>
                    </div>
                )}
            </div>
        </div>
    );
};

/* ============================================================
   VehiclePickerModal — browse all 19 Core vehicles
   ============================================================ */
window.VehiclePickerModal = function VehiclePickerModal({ character, onPick, onClose }) {
    const V = SR5_VEHICLES;
    const C = SR5_CALC;

    return (
        <EntityPicker
            title="Browse Vehicles"
            items={V.VEHICLES}
            getItemKey={v => v.key}
            filters={V.VEHICLE_CATEGORIES.map(c => ({ key: c.key, label: c.label }))}
            filterBy={(v, query, activeFilter) => {
                if (activeFilter && v.category !== activeFilter) return false;
                if (query) {
                    const q = query.toLowerCase();
                    const blob = (v.name + ' ' + v.description + ' ' + v.category).toLowerCase();
                    if (!blob.includes(q)) return false;
                }
                return true;
            }}
            isBlocked={v => !C.availAllowedForCharacter(character, v.avail)}
            blockedReason={v => `Availability ${v.avail} exceeds creation cap of ${C.CREATION_AVAIL_CAP}`}
            itemRenderer={(v, { selected, blocked, onClick }) => (
                <div key={v.key}
                     className={`picker-item ${selected ? 'selected' : ''} ${blocked ? 'blocked' : ''}`}
                     onClick={onClick}
                     title={blocked ? `Availability ${v.avail} — over the creation cap` : undefined}>
                    <span className="pi-name">{v.name}</span>
                    <span className="pi-cost">{v.cost.toLocaleString()}¥</span>
                    <div className="pi-meta">
                        <span className="mono">{v.category}</span>
                        {' · H'}{v.handling}{' S'}{v.speed}{' B'}{v.body}{' A'}{v.armor}
                        {v.avail && <span className="muted"> · {v.avail}</span>}
                    </div>
                </div>
            )}
            renderDetails={(v) => (
                <>
                    <h3 className="picker-details-title">{v.name}</h3>
                    <div className="weapon-stat-grid">
                        <div className="ws"><span className="ws-label">Category</span><span className="ws-value">{v.category}</span></div>
                        <div className="ws"><span className="ws-label">Handling</span><span className="ws-value">{v.handling}</span></div>
                        <div className="ws"><span className="ws-label">Speed</span><span className="ws-value">{v.speed}</span></div>
                        <div className="ws"><span className="ws-label">Accel</span><span className="ws-value">{v.accel}</span></div>
                        <div className="ws"><span className="ws-label">Body</span><span className="ws-value">{v.body}</span></div>
                        <div className="ws"><span className="ws-label">Armor</span><span className="ws-value">{v.armor}</span></div>
                        <div className="ws"><span className="ws-label">Pilot</span><span className="ws-value">{v.pilot}</span></div>
                        <div className="ws"><span className="ws-label">Sensor</span><span className="ws-value">{v.sensor}</span></div>
                        <div className="ws"><span className="ws-label">Seats</span><span className="ws-value">{v.seats || '—'}</span></div>
                        <div className="ws"><span className="ws-label">Avail</span><span className="ws-value">{v.avail || '—'}</span></div>
                        <div className="ws"><span className="ws-label">Cost</span><span className="ws-value accent">{v.cost.toLocaleString()}¥</span></div>
                        <div className="ws"><span className="ws-label">Source</span><span className="ws-value mono">{v.source}</span></div>
                    </div>
                    <div className="picker-details-section">
                        <div className="picker-details-label">Description</div>
                        <div className="picker-details-text">{v.description}</div>
                    </div>
                </>
            )}
            onPick={onPick}
            onClose={onClose}
        />
    );
};

/* ============================================================
   DronePickerModal — browse all 11 Core drones
   ============================================================ */
window.DronePickerModal = function DronePickerModal({ character, onPick, onClose }) {
    const V = SR5_VEHICLES;
    const C = SR5_CALC;

    return (
        <EntityPicker
            title="Browse Drones"
            items={V.DRONES}
            getItemKey={d => d.key}
            filters={V.DRONE_SIZES.map(s => ({ key: s.key, label: s.label }))}
            filterBy={(d, query, activeFilter) => {
                if (activeFilter && d.droneSize !== activeFilter) return false;
                if (query) {
                    const q = query.toLowerCase();
                    const blob = (d.name + ' ' + d.description + ' ' + d.droneSize).toLowerCase();
                    if (!blob.includes(q)) return false;
                }
                return true;
            }}
            isBlocked={d => !C.availAllowedForCharacter(character, d.avail)}
            blockedReason={d => `Availability ${d.avail} exceeds creation cap of ${C.CREATION_AVAIL_CAP}`}
            itemRenderer={(d, { selected, blocked, onClick }) => (
                <div key={d.key}
                     className={`picker-item ${selected ? 'selected' : ''} ${blocked ? 'blocked' : ''}`}
                     onClick={onClick}
                     title={blocked ? `Availability ${d.avail} — over the creation cap` : undefined}>
                    <span className="pi-name">{d.name}</span>
                    <span className="pi-cost">{d.cost.toLocaleString()}¥</span>
                    <div className="pi-meta">
                        <span className="mono">{d.droneSize}</span>
                        {' · Pilot '}{d.pilot}{' · Sens '}{d.sensor}{' · Body '}{d.body}
                        {d.avail && <span className="muted"> · {d.avail}</span>}
                    </div>
                </div>
            )}
            renderDetails={(d) => (
                <>
                    <h3 className="picker-details-title">{d.name}</h3>
                    <div className="weapon-stat-grid">
                        <div className="ws"><span className="ws-label">Size</span><span className="ws-value">{d.droneSize}</span></div>
                        <div className="ws"><span className="ws-label">Handling</span><span className="ws-value">{d.handling}</span></div>
                        <div className="ws"><span className="ws-label">Speed</span><span className="ws-value">{d.speed}</span></div>
                        <div className="ws"><span className="ws-label">Accel</span><span className="ws-value">{d.accel}</span></div>
                        <div className="ws"><span className="ws-label">Body</span><span className="ws-value">{d.body}</span></div>
                        <div className="ws"><span className="ws-label">Armor</span><span className="ws-value">{d.armor}</span></div>
                        <div className="ws"><span className="ws-label">Pilot</span><span className="ws-value">{d.pilot}</span></div>
                        <div className="ws"><span className="ws-label">Sensor</span><span className="ws-value">{d.sensor}</span></div>
                        <div className="ws"><span className="ws-label">Avail</span><span className="ws-value">{d.avail || '—'}</span></div>
                        <div className="ws"><span className="ws-label">Cost</span><span className="ws-value accent">{d.cost.toLocaleString()}¥</span></div>
                        <div className="ws"><span className="ws-label">Source</span><span className="ws-value mono">{d.source}</span></div>
                    </div>
                    <div className="picker-details-section">
                        <div className="picker-details-label">Description</div>
                        <div className="picker-details-text">{d.description}</div>
                    </div>
                </>
            )}
            onPick={onPick}
            onClose={onClose}
        />
    );
};

/* ============================================================
   AutosoftPickerModal — add an autosoft to a drone
   ============================================================ */
window.AutosoftPickerModal = function AutosoftPickerModal({ droneName, onSubmit, onClose }) {
    const V = SR5_VEHICLES;

    const [key, setKey] = useState('clearsight');
    const [rating, setRating] = useState(3);
    const [weaponKey, setWeaponKey] = useState('');
    const [modelKey, setModelKey] = useState('');

    const tpl = V.findAutosoft(key);
    const needsWeapon = tpl?.perWeapon;
    const needsModel = tpl?.perModel;
    const cost = V.autosoftCost(rating);
    const avail = V.autosoftAvail(rating);

    const canSubmit = tpl && rating >= 1
        && (!needsWeapon || weaponKey.trim())
        && (!needsModel || modelKey.trim());

    const footer = (
        <div className="footer-actions" style={{ width: '100%', justifyContent: 'flex-end' }}>
            <button className="btn btn-ghost" onClick={onClose}>Cancel</button>
            <button className="btn btn-primary"
                    disabled={!canSubmit}
                    onClick={() => onSubmit({
                        key, rating,
                        weaponKey: needsWeapon ? weaponKey.trim() : null,
                        modelKey: needsModel ? modelKey.trim() : null,
                    })}>
                Add to {droneName}
            </button>
        </div>
    );

    return (
        <Modal title="Add Autosoft" onClose={onClose} footer={footer}>
            <div style={{ padding: '20px 24px', width: '100%', overflowY: 'auto' }}>
                <FormRow label="Autosoft type">
                    <div className="autosoft-type-grid">
                        {V.AUTOSOFTS.map(a => (
                            <div key={a.key}
                                 className={`autosoft-type-card ${key === a.key ? 'selected' : ''}`}
                                 onClick={() => setKey(a.key)}>
                                <div className="atc-name">{a.name}</div>
                                <div className="atc-desc">{a.description}</div>
                                {a.perWeapon && <div className="atc-tag mono">per-weapon</div>}
                                {a.perModel && <div className="atc-tag mono">per-model</div>}
                            </div>
                        ))}
                    </div>
                </FormRow>

                <div style={{ display: 'grid', gridTemplateColumns: '1fr 2fr', gap: 12 }}>
                    <FormRow label="Rating" hint="1-6">
                        <RatingStepper value={rating} min={1} max={6} onChange={setRating} />
                    </FormRow>
                    {needsWeapon && (
                        <FormRow label="Weapon" hint="the specific weapon this autosoft targets">
                            <TextInput value={weaponKey} onChange={setWeaponKey} placeholder="e.g. Ares Alpha, Colt M23" maxLength={40} />
                        </FormRow>
                    )}
                    {needsModel && (
                        <FormRow label="Drone model" hint="the specific drone model">
                            <TextInput value={modelKey} onChange={setModelKey} placeholder="e.g. Fly-Spy, Doberman" maxLength={40} />
                        </FormRow>
                    )}
                </div>

                <div className="autosoft-preview">
                    <div><strong>{tpl?.name}</strong> R{rating}</div>
                    <div className="mono muted">Cost: {cost.toLocaleString()}¥ · Avail: {avail}</div>
                    <div className="muted" style={{ fontSize: 11, marginTop: 6, lineHeight: 1.5 }}>
                        Per errata: autosoft cost = Rating × 500¥, availability = Rating × 2.
                        {needsWeapon && ' Weapon-targeting autosofts work only with the named weapon.'}
                        {needsModel && ' Model-specific autosofts work only on the named drone model.'}
                    </div>
                </div>
            </div>
        </Modal>
    );
};

/* ============================================================
   CustomVehicleDialog + CustomDroneDialog
   ============================================================ */
window.CustomVehicleDialog = function CustomVehicleDialog({ onSubmit, onClose }) {
    const V = SR5_VEHICLES;
    const [name, setName] = useState('');
    const [category, setCategory] = useState('car');
    const [handling, setHandling] = useState(3);
    const [speed, setSpeed] = useState(3);
    const [accel, setAccel] = useState(1);
    const [body, setBody] = useState(6);
    const [armor, setArmor] = useState(0);
    const [pilot, setPilot] = useState(1);
    const [sensor, setSensor] = useState(1);
    const [seats, setSeats] = useState(4);
    const [avail, setAvail] = useState('—');
    const [nuyen, setNuyen] = useState(0);
    const [description, setDescription] = useState('');

    const footer = (
        <div className="footer-actions" style={{ width: '100%', justifyContent: 'flex-end' }}>
            <button className="btn btn-ghost" onClick={onClose}>Cancel</button>
            <button className="btn btn-primary"
                    disabled={!name.trim()}
                    onClick={() => onSubmit({
                        name, category, handling, speed, accel, body, armor, pilot, sensor, seats,
                        avail, nuyen: parseInt(nuyen, 10) || 0, description,
                    })}>
                Add vehicle
            </button>
        </div>
    );

    return (
        <Modal title="Custom Vehicle" onClose={onClose} footer={footer}>
            <div style={{ padding: '20px 24px', width: '100%', overflowY: 'auto' }}>
                <FormRow label="Name">
                    <TextInput value={name} onChange={setName} placeholder="e.g. Rusty Bulldog" maxLength={60} />
                </FormRow>
                <FormRow label="Category">
                    <select className="input" value={category} onChange={e => setCategory(e.target.value)}>
                        {V.VEHICLE_CATEGORIES.map(c => (
                            <option key={c.key} value={c.key}>{c.label}</option>
                        ))}
                    </select>
                </FormRow>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8 }}>
                    <FormRow label="Handling"><RatingStepper value={handling} min={0} max={10} onChange={setHandling} /></FormRow>
                    <FormRow label="Speed"><RatingStepper value={speed} min={0} max={10} onChange={setSpeed} /></FormRow>
                    <FormRow label="Accel"><RatingStepper value={accel} min={0} max={10} onChange={setAccel} /></FormRow>
                    <FormRow label="Body"><RatingStepper value={body} min={1} max={24} onChange={setBody} /></FormRow>
                    <FormRow label="Armor"><RatingStepper value={armor} min={0} max={24} onChange={setArmor} /></FormRow>
                    <FormRow label="Pilot"><RatingStepper value={pilot} min={1} max={6} onChange={setPilot} /></FormRow>
                    <FormRow label="Sensor"><RatingStepper value={sensor} min={1} max={6} onChange={setSensor} /></FormRow>
                    <FormRow label="Seats"><RatingStepper value={seats} min={1} max={60} onChange={setSeats} /></FormRow>
                </div>
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
                    <FormRow label="Availability">
                        <TextInput value={avail} onChange={setAvail} maxLength={10} />
                    </FormRow>
                    <FormRow label="Nuyen">
                        <input type="number" className="input" min="0"
                               value={nuyen} onChange={e => setNuyen(e.target.value)} />
                    </FormRow>
                </div>
                <FormRow label="Description">
                    <TextArea value={description} onChange={setDescription} rows={2} placeholder="Notes, flavor, purpose..." />
                </FormRow>
            </div>
        </Modal>
    );
};

window.CustomDroneDialog = function CustomDroneDialog({ onSubmit, onClose }) {
    const V = SR5_VEHICLES;
    const [name, setName] = useState('');
    const [droneSize, setDroneSize] = useState('small');
    const [handling, setHandling] = useState(3);
    const [speed, setSpeed] = useState(3);
    const [accel, setAccel] = useState(1);
    const [body, setBody] = useState(2);
    const [armor, setArmor] = useState(0);
    const [pilot, setPilot] = useState(3);
    const [sensor, setSensor] = useState(2);
    const [avail, setAvail] = useState('—');
    const [nuyen, setNuyen] = useState(0);
    const [description, setDescription] = useState('');

    const footer = (
        <div className="footer-actions" style={{ width: '100%', justifyContent: 'flex-end' }}>
            <button className="btn btn-ghost" onClick={onClose}>Cancel</button>
            <button className="btn btn-primary"
                    disabled={!name.trim()}
                    onClick={() => onSubmit({
                        name, droneSize, handling, speed, accel, body, armor, pilot, sensor,
                        avail, nuyen: parseInt(nuyen, 10) || 0, description,
                    })}>
                Add drone
            </button>
        </div>
    );

    return (
        <Modal title="Custom Drone" onClose={onClose} footer={footer}>
            <div style={{ padding: '20px 24px', width: '100%', overflowY: 'auto' }}>
                <FormRow label="Name">
                    <TextInput value={name} onChange={setName} placeholder="e.g. Custom Scout Drone" maxLength={60} />
                </FormRow>
                <FormRow label="Size">
                    <select className="input" value={droneSize} onChange={e => setDroneSize(e.target.value)}>
                        {V.DRONE_SIZES.map(s => (
                            <option key={s.key} value={s.key}>{s.label}</option>
                        ))}
                    </select>
                </FormRow>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8 }}>
                    <FormRow label="Handling"><RatingStepper value={handling} min={0} max={10} onChange={setHandling} /></FormRow>
                    <FormRow label="Speed"><RatingStepper value={speed} min={0} max={10} onChange={setSpeed} /></FormRow>
                    <FormRow label="Accel"><RatingStepper value={accel} min={0} max={10} onChange={setAccel} /></FormRow>
                    <FormRow label="Body"><RatingStepper value={body} min={1} max={24} onChange={setBody} /></FormRow>
                    <FormRow label="Armor"><RatingStepper value={armor} min={0} max={24} onChange={setArmor} /></FormRow>
                    <FormRow label="Pilot"><RatingStepper value={pilot} min={1} max={6} onChange={setPilot} /></FormRow>
                    <FormRow label="Sensor"><RatingStepper value={sensor} min={1} max={6} onChange={setSensor} /></FormRow>
                </div>
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
                    <FormRow label="Availability">
                        <TextInput value={avail} onChange={setAvail} maxLength={10} />
                    </FormRow>
                    <FormRow label="Nuyen">
                        <input type="number" className="input" min="0"
                               value={nuyen} onChange={e => setNuyen(e.target.value)} />
                    </FormRow>
                </div>
                <FormRow label="Description">
                    <TextArea value={description} onChange={setDescription} rows={2} placeholder="Notes, flavor, purpose..." />
                </FormRow>
            </div>
        </Modal>
    );
};
