var _useState_AP = React.useState;
var _useCallback_AP = React.useCallback;
var _useEffect_AP = React.useEffect;
var _useRef_AP = React.useRef;

/**
 * AnalysisPage — Two-phase page: Image Upload → AI Analysis Results.
 *
 * Engine selection via AIEngineAdapter.resolve() — reads AI_ENGINE flag value
 * and returns the active strategy (LocalCNNStrategy | HybridStrategy |
 * NyckelStrategy | CloudStrategy | NoneStrategy). No engine branching here.
 *
 * Phases: idle | loading_model | preview | analyzing | results | error
 *
 * Progressive disclosure for Hybrid and Local engines:
 *   1. Confidence ring + severity alert (immediate — Nyckel or Local CNN)
 *   2. Frequency spectrum bar         (progressive — enrichment pending)
 *   3. Heatmap panel                  (progressive — enrichment pending)
 *   4. Species panel                  (progressive — enrichment pending, SPECIES_LIST flag)
 *
 * Enrichment state machine: idle → pending → ready | failed
 *   pending : skeleton loaders shown in place of enrichment panels
 *   ready   : panels replace skeletons (scan record patched via updateScan)
 *   failed  : panels hidden, Nyckel verdict stands
 *
 * On successful analysis, saves scan record to ScanStore.
 * Hybrid enrichment patches the saved record via updateScan when complete.
 */
var AnalysisPage = function () {
    var navigate = ReactRouterDOM.useNavigate();
    var scanStore = useScanStore();

    var phaseState = _useState_AP('idle');
    var phase = phaseState[0]; var setPhase = phaseState[1];

    var imageState = _useState_AP(null);
    var imageData = imageState[0]; var setImageData = imageState[1];

    var resultState = _useState_AP(null);
    var result = resultState[0]; var setResult = resultState[1];

    var errorState = _useState_AP('');
    var errorMsg = errorState[0]; var setErrorMsg = errorState[1];

    var statusState = _useState_AP('');
    var statusMsg = statusState[0]; var setStatusMsg = statusState[1];

    var modelReadyState = _useState_AP(false);
    var modelReady = modelReadyState[0]; var setModelReady = modelReadyState[1];

    // Analysis state machine — prevents concurrent operations
    var analysisState = _useState_AP('idle'); // idle | running | completed | failed
    var analysisRunning = analysisState[0]; var setAnalysisRunning = analysisState[1];

    // Enrichment state machine for Hybrid mode progressive disclosure
    // idle → pending (Nyckel done, enrichment running) → ready | failed
    var enrichmentStateArr = _useState_AP('idle');
    var enrichmentState = enrichmentStateArr[0]; var setEnrichmentState = enrichmentStateArr[1];

    // Refs for cancellation and enrichment persistence
    var analysisRef = _useRef_AP(null);
    var analysisAbortRef = _useRef_AP(null);
    var savedScanIdRef = _useRef_AP(null);
    var previewImgRef = _useRef_AP(null);

    // Cleanup on unmount
    _useEffect_AP(function () {
        return function () {
            if (analysisAbortRef.current !== null) {
                analysisAbortRef.current = true;
            }
            savedScanIdRef.current  = null;
            previewImgRef.current   = null; // LR-04 FIX: release detached DOM node ref
        };
    }, []);

    // Read the active engine value once per render — drives all engine-aware UI copy
    var _aiEngine = useFeatureFlagValue('AI_ENGINE') || 'nyckel';
    // Convenience flag for UI copy — not used for engine dispatch (that's AIEngineAdapter's job)
    var useLocalCNN = (_aiEngine === 'local');
    // Hoisted at component level — hooks must not be called inside nested functions
    var speciesEnabled = useFeatureFlag('SPECIES_LIST');

    // ── Model readiness — poll until the active engine's models are ready ──────
    // local  : LocalCNNService must reach 'ready' state
    // hybrid : LocalCNNEnrichmentService must reach 'ready' (same models, lighter)
    // others : cloud APIs need no pre-load, mark ready immediately
    _useEffect_AP(function () {
        var cancelled = false;

        if (_aiEngine !== 'local' && _aiEngine !== 'hybrid') {
            setModelReady(true);
            return;
        }

        // MR-08 FIX: both 'local' and 'hybrid' share LocalCNNService model state —
        // LocalCNNEnrichmentService.isReady() delegates to LocalCNNService.getLoadState()
        // so reading it directly is correct and clearer for both engine values.
        var state = LocalCNNService.getLoadState();

        if (state === 'ready') {
            setModelReady(true);
            return;
        }
        if (state === 'failed') {
            console.warn('[AnalysisPage] Engine pre-load failed — proceeding with available fallback.');
            setModelReady(true);
            return;
        }
        if (state === 'idle') {
            setPhase('loading_model');
            setStatusMsg('Loading AI Vision engine…');
            var loadFn = (_aiEngine === 'hybrid')
                ? LocalCNNEnrichmentService.loadForEnrichment
                : LocalCNNService.load;
            loadFn(function (msg) { if (!cancelled) setStatusMsg(msg); })
                .then(function () {
                    if (cancelled) return;
                    setModelReady(true);
                    setPhase('idle');
                    setStatusMsg('');
                })
                ['catch'](function (err) {
                    if (cancelled) return;
                    console.warn('[AnalysisPage] On-demand load failed:', err.message);
                    setModelReady(true);
                    setPhase('idle');
                    setStatusMsg('');
                });
            return function () { cancelled = true; };
        }
        // 'loading' — boot pre-load still in progress, poll until done
        var pollInterval = setInterval(function () {
            var s = LocalCNNService.getLoadState();
            if (s === 'ready' || s === 'failed') {
                clearInterval(pollInterval);
                if (s === 'failed') {
                    console.warn('[AnalysisPage] Engine load failed (polled) — proceeding with fallback.');
                }
                setModelReady(true);
                setPhase('idle');
                setStatusMsg('');
            }
        }, 500);
        setPhase('loading_model');
        setStatusMsg('Finalising AI engine…');
        return function () { clearInterval(pollInterval); };
    }, [_aiEngine]);

    var handleImageReady = _useCallback_AP(function (data) {
        setImageData(data);
        setResult(null);
        setErrorMsg('');
        setStatusMsg('');
        setPhase('preview');
    }, []);

    // Shared scan save helper — avoids duplication across engine branches.
    // Captures the new scan id into savedScanIdRef so Hybrid enrichment
    // can patch the record via updateScan when the Local CNN pass completes.
    var _saveScan = function (res, thumbnail) {
        AnalyticsService.scanSaved({
            severity:     res.severity,
            has_location: false,
            has_property: false,
        });
        var record = scanStore.addScan({
            fileName:    imageData.file ? imageData.file.name : 'scan',
            thumbnail:   thumbnail || '',
            previewURL:  imageData.previewURL,
            percentage:  res.percentage,
            verdict:     res.verdict,
            severity:    res.severity,
            label:       res.label,
            insight:     res.insight,
            aiEngine:    res.aiEngine || null,
            rawScore:              res.rawScore              || null,
            freqSpectrum:          res.freqSpectrum          || null,
            saliencyLevel:         res.saliencyLevel         || null,
            saliencyPeakToMean:    res.saliencyPeakToMean    || null,
            isShortcut:            res.isShortcut            || false,
            heatmapDataURL:        res.heatmapDataURL        || null,
            speciesTop:            res.speciesTop            || null,
            speciesRanked:         res.speciesRanked         || [],
            speciesIsUncertain:    res.speciesIsUncertain    || false,
            speciesSummary:        res.speciesSummary        || '',
            darkMouldConsensus:    res.darkMouldConsensus    || false,
            patchContribution:     res.patchContribution     || null,
            textureIrregularity:   res.textureIrregularity   || null,
            textureIrregularityLevel: res.textureIrregularityLevel || null,
            interChannelDiff:      res.interChannelDiff      || null,
        });
        // Capture scan id for Hybrid enrichment patch
        savedScanIdRef.current = record ? record.id : null;
    };

    // _applyEnrichment — called when Hybrid enrichment resolves.
    // Patches the saved scan record and updates UI result state in one pass.
    // isAnalysisCancelled is passed in to guard against stale updates after reset.
    var _applyEnrichment = function (enrichedResult, isAnalysisCancelled) {
        if (isAnalysisCancelled()) {
            console.log('[AnalysisPage] Enrichment arrived after cancellation — discarding.');
            return;
        }
        // Update the persisted scan record with enrichment fields
        if (savedScanIdRef.current) {
            scanStore.updateScan(savedScanIdRef.current, {
                // HR-05 FIX: ensure aiEngine identity is persisted as 'hybrid'
                // so ScanDetails can correctly identify enriched scans after reload
                aiEngine:              'hybrid',
                freqSpectrum:          enrichedResult.freqSpectrum          || null,
                saliencyLevel:         enrichedResult.saliencyLevel         || null,
                saliencyPeakToMean:    enrichedResult.saliencyPeakToMean    || null,
                isShortcut:            enrichedResult.isShortcut            || false,
                heatmapDataURL:        enrichedResult.heatmapDataURL        || null,
                speciesTop:            enrichedResult.speciesTop            || null,
                speciesRanked:         enrichedResult.speciesRanked         || [],
                speciesIsUncertain:    enrichedResult.speciesIsUncertain    || false,
                speciesSummary:        enrichedResult.speciesSummary        || '',
            });
        }
        // Merge enrichment fields into the displayed result and reveal panels
        setResult(enrichedResult);
        setEnrichmentState('ready');
        console.info('[AnalysisPage] Hybrid enrichment applied.');
    };

        // HR-02 FIX: Map raw engine/network errors to plain-English user messages.
    // Called from the catch block so users never see API error codes or
    // TF.js internal strings.
    var _friendlyError = function (err) {
        var msg = (err && err.message) ? err.message.toLowerCase() : '';
        if (msg === 'offline'
            || msg.indexOf('failed to fetch') !== -1
            || msg.indexOf('networkerror') !== -1
            || msg.indexOf('network request failed') !== -1
            || msg.indexOf('load failed') !== -1) {
            return 'No internet connection. Please check your connection and try again.';
        }
        if (msg.indexOf('aborted') !== -1 || msg.indexOf('timeout') !== -1) {
            return 'The analysis took too long. Please try again.';
        }
        if (msg.indexOf('401') !== -1 || msg.indexOf('403') !== -1 || msg.indexOf('auth failed') !== -1) {
            return 'The analysis service is temporarily unavailable. Please try again later.';
        }
        if (msg.indexOf('image not ready') !== -1 || msg.indexOf('image element') !== -1) {
            return 'Please go back and select your photo again.';
        }
        if (msg.indexOf('not loaded') !== -1 || msg.indexOf('call load()') !== -1) {
            return 'The AI engine is still loading. Please wait a moment and try again.';
        }
        if (msg.indexOf('unrecognised api') !== -1) {
            return 'The analysis service returned an unexpected result. Please try again.';
        }
        return 'Something went wrong. Please try again. If the problem persists, try a different photo.';
    };

    var handleAnalyze = _useCallback_AP(function () {
        if (!imageData || !imageData.dataURL) return;
        if (analysisRunning === 'running') {
            console.warn('[AnalysisPage] Analysis already running, ignoring request');
            return;
        }

        var analysisId = Date.now() + Math.random();
        analysisRef.current = analysisId;
        analysisAbortRef.current = false;

        setAnalysisRunning('running');
        setEnrichmentState('idle');
        setPhase('analyzing');
        setStatusMsg('Analysing image…');
        setResult(null);
        setErrorMsg('');

        var strategy = AIEngineAdapter.resolve();

        // HR-01 FIX: Check connectivity before attempting any network-dependent engine.
        // Avoids 60-90s timeout on mobile when offline.
        if ((strategy.engineId === 'nyckel' || strategy.engineId === 'hybrid' || strategy.engineId === 'cloud_ai')
            && typeof navigator !== 'undefined' && navigator.onLine === false) {
            setErrorMsg('No internet connection. Please check your connection and try again.');
            setPhase('error');
            setAnalysisRunning('failed');
            return;
        }

        console.info('[AnalysisPage] Starting analysis — engine:', strategy.engineId, 'id:', analysisId);
        AnalyticsService.scanInitiated({ ai_engine: strategy.engineId, image_source: 'upload' });

        var isAnalysisCancelled = function () {
            return analysisAbortRef.current || analysisRef.current !== analysisId;
        };

        var imagePayload = {
            dataURL:    imageData.dataURL,
            previewURL: imageData.previewURL,
            file:       imageData.file || null,
            imgElement: previewImgRef.current || null
        };

        strategy.analyze(imagePayload, function (msg) {
            if (!isAnalysisCancelled()) setStatusMsg(msg);
        })
        .then(function (res) {
            if (isAnalysisCancelled()) return;
            if (strategy.engineId === 'hybrid') {
                res.enrichmentPending = true;
                res.hasEnrichment = false;
            }
            setResult(res);
            return ThumbnailService.generate(imageData.previewURL || imageData.dataURL)['catch'](function () { return ''; })
                .then(function (thumb) {
                    if (!isAnalysisCancelled()) _saveScan(res, thumb);
                })
                .then(function () {
                    if (isAnalysisCancelled()) return;
                    // MR-06 FIX: clear large original base64 — only previewURL needed
                    // for display from this point. dataURL can be 10-20MB for DSLR images.
                    setImageData(function (prev) {
                        if (!prev) return prev;
                        return { file: prev.file, previewURL: prev.previewURL, dataURL: null };
                    });
                    setStatusMsg('');
                    setPhase('results');
                    setAnalysisRunning('completed');
                    AnalyticsService.scanCompleted({
                        ai_engine:      strategy.engineId,
                        verdict:        res.verdict,
                        severity:       res.severity,
                        confidence_pct: res.percentage,
                        species:        res.speciesTop ? res.speciesTop.label : 'none',
                        is_mould:       res.percentage >= 50
                    });
                    if (strategy.engineId === 'hybrid' && res._enrichmentPromise) {
                        setEnrichmentState('pending');
                        setStatusMsg('Generating visual insights…');
                        res._enrichmentPromise
                            .then(function (enrichedResult) {
                                if (isAnalysisCancelled()) return;
                                setStatusMsg('');
                                if (enrichedResult && enrichedResult.hasEnrichment) {
                                    _applyEnrichment(enrichedResult, isAnalysisCancelled);
                                } else {
                                    setEnrichmentState('failed');
                                }
                            })
                            ['catch'](function (err) {
                                if (isAnalysisCancelled()) return;
                                setStatusMsg('');
                                setEnrichmentState('failed');
                                console.warn('[AnalysisPage] Hybrid enrichment failed:', err.message);
                            });
                    }
                });
        })
        ['catch'](function (err) {
            if (isAnalysisCancelled()) return;
            console.error('[AnalysisPage] Analysis failed (' + strategy.engineId + '):', err.message);
            AnalyticsService.scanError({
                ai_engine:     strategy.engineId,
                error_type:    'analysis_failure',
                error_message: err.message
            });
            // HR-02 FIX: map raw error to plain-English user message
            setErrorMsg(_friendlyError(err));
            setPhase('error');
            setAnalysisRunning('failed');
        });
    }, [imageData, scanStore, analysisRunning]);

    var handleReset = _useCallback_AP(function () {
        if (analysisRef.current) {
            analysisAbortRef.current = true;
            console.log('[AnalysisPage] Cancelling analysis on reset');
        }
        setPhase('idle');
        setImageData(null);
        setResult(null);
        setErrorMsg('');
        setStatusMsg('');
        setAnalysisRunning('idle');
        setEnrichmentState('idle');
        analysisRef.current     = null;
        analysisAbortRef.current = false;
        savedScanIdRef.current  = null;
        previewImgRef.current   = null; // LR-04 FIX: release detached DOM node ref
    }, []);

    var headerTitle = (phase === 'results') ? 'Analysis Results' : 'Mould Detect';

    var severityStyles = {
        critical: { bg: 'bg-warning-light', border: 'border-warning/20', text: 'text-warning', icon: 'emergency' },
        high:     { bg: 'bg-warning-light', border: 'border-warning/20', text: 'text-warning', icon: 'warning' },
        moderate: { bg: 'bg-[#FFF8E1]', border: 'border-[#d4a373]/20', text: 'text-[#d4a373]', icon: 'info' },
        low:      { bg: 'bg-[#E8F5E9]', border: 'border-primary/20', text: 'text-primary', icon: 'check_circle' },
    };

    // Engine badge shown in results
    var renderEngineBadge = function () {
        if (!result) return null;
        var isLocal = result.aiEngine === 'local_cnn';
        return (
            <div className={'inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[10px] font-black uppercase tracking-wider ' + (isLocal ? 'bg-primary/15 text-forest' : 'bg-forest/10 text-forest')}>
                <span className="material-symbols-outlined text-sm">{isLocal ? 'memory' : 'cloud'}</span>
                {isLocal ? 'Local AI · On-Device' : 'Nyckel API · Cloud'}
            </div>
        );
    };

    var renderResults = function () {
        var sev = severityStyles[result.severity] || severityStyles.low;
        // hasEnrichment: true for local_cnn always; true for hybrid once enrichment resolves
        var hasEnrichment = result.hasEnrichment || result.aiEngine === 'local_cnn';
        var enrichmentPending = enrichmentState === 'pending';

        // Skeleton loader — reused for each pending enrichment panel
        var renderEnrichmentSkeleton = function (icon, label) {
            return (
                <div className="bio-bg bio-bg-20 rounded-xl border border-stone-100/50 shadow-soft p-4 flex items-center gap-3">
                    <div className="relative w-8 h-8 shrink-0">
                        <div className="absolute inset-0 rounded-full border-2 border-primary/20"></div>
                        <div className="absolute inset-0 rounded-full border-2 border-transparent border-t-primary animate-spin"></div>
                        <div className="absolute inset-0 flex items-center justify-center">
                            <span className="material-symbols-outlined text-primary text-sm">{icon}</span>
                        </div>
                    </div>
                    <div>
                        <p className="text-[11px] font-black text-forest uppercase tracking-[0.12em]">{label}</p>
                        <p className="text-[11px] font-medium text-forest/60 mt-0.5">Generating visual insights…</p>
                    </div>
                </div>
            );
        };

        return (
            <div className="mt-4 space-y-4">
                {/* Scan image */}
                {imageData && imageData.previewURL && (
                    <div className="aspect-video w-full rounded-xl overflow-hidden shadow-soft border-4 border-surface">
                        <img className="w-full h-full object-cover" src={imageData.previewURL} alt="Analysed image" />
                    </div>
                )}

                {/* Verdict + confidence ring */}
                <div className="bg-background-light rounded-xl shadow-soft p-5 border border-stone-100/50">
                    <div className="text-center mb-3">
                        <h2 className="text-2xl font-extrabold text-forest">{result.verdict}</h2>
                        {result.label && (
                            <p className="text-forest font-bold text-sm mt-1">{result.label}</p>
                        )}
                    </div>
                    <div className="flex flex-col items-center">
                        <ConfidenceRing percentage={result.percentage} severity={result.severity} />
                    </div>

                    {/* Frequency spectrum — present when enrichment ready */}
                    {hasEnrichment && result.freqSpectrum && (
                        <FrequencySpectrumBar freqSpectrum={result.freqSpectrum} className="mt-4" />
                    )}
                    {/* Frequency spectrum skeleton — shown while enrichment is pending */}
                    {enrichmentPending && !result.freqSpectrum && (
                        <div className="mt-4">{renderEnrichmentSkeleton('graphic_eq', 'Frequency Spectrum')}</div>
                    )}

                    {/* Severity alert */}
                    <div className={sev.bg + ' rounded-xl mt-4 p-5 flex items-start gap-3 border ' + sev.border}>
                        <span className={'material-symbols-outlined ' + sev.text + ' mt-0.5'}>{sev.icon}</span>
                        <div className="flex-1">
                            <h3 className={'font-extrabold ' + sev.text + ' mb-1'}>{result.verdict}</h3>
                            <p className="text-sm font-medium text-forest leading-relaxed">{result.insight}</p>
                        </div>
                    </div>
                </div>

                {/* Heatmap panel — present when enrichment ready */}
                {hasEnrichment && result.heatmapDataURL && (
                    <LocalHeatmapPanel
                        heatmapDataURL={result.heatmapDataURL}
                        originalDataURL={imageData && imageData.previewURL}
                        isMould={result.percentage >= 50}
                        saliencyLevel={result.saliencyLevel}
                        isShortcut={result.isShortcut}
                        speciesLabel={result.speciesTop ? result.speciesTop.label : ''}
                    />
                )}
                {/* Heatmap skeleton — shown while enrichment is pending */}
                {enrichmentPending && !result.heatmapDataURL && (
                    renderEnrichmentSkeleton('visibility', 'AI Attention Heatmap')
                )}

                {/* Species panel — gated by SPECIES_LIST flag and enrichment */}
                {speciesEnabled && hasEnrichment && result.speciesTop && result.percentage >= 50 && (
                    <LocalSpeciesPanel
                        speciesTop={result.speciesTop}
                        speciesRanked={result.speciesRanked}
                        speciesSummary={result.speciesSummary}
                        isUncertain={result.speciesIsUncertain}
                    />
                )}
                {/* Species skeleton — shown while enrichment is pending and SPECIES_LIST enabled */}
                {speciesEnabled && enrichmentPending && !result.speciesTop && result.percentage >= 50 && (
                    renderEnrichmentSkeleton('biotech', 'Species Identification')
                )}

                <HealthRiskInfo />

                <FindSpecialistPanel context="analysis" severity={result.severity} />

                <button
                    onClick={function () { navigate('/location-details', { state: { fromScan: true } }); }}
                    className="w-full h-14 bg-primary text-white rounded-full font-extrabold text-lg shadow-clay flex items-center justify-center gap-2 btn-nature hover:brightness-110 transition-all"
                >
                    <span className="material-symbols-outlined">add_location</span>
                    Save Scan Details
                </button>
                <button
                    onClick={handleReset}
                    className="w-full h-12 bg-surface text-forest rounded-full font-bold text-sm border border-stone-100/50 shadow-soft flex items-center justify-center gap-2 btn-nature hover:bg-forest hover:text-white transition-all duration-300"
                >
                    <span className="material-symbols-outlined text-lg">add_a_photo</span>
                    Scan Another Image
                </button>

                <p className="text-[11px] text-forest text-center leading-relaxed">
                    AI-assisted visual analysis for decision-support only. Results should not replace professional inspection.
                </p>
            </div>
        );
    };

    return (
        <Layout>
            <main className="flex-1 overflow-y-auto overflow-x-hidden px-6 pb-36">
                <PageHeader
                    title={headerTitle}
                    showMenu={true}
                    titleClass="font-extrabold text-xl text-forest tracking-tight"
                />

                {/* Model loading state */}
                {phase === 'loading_model' && (
                    <div className="bg-background-light mt-4 rounded-xl shadow-soft p-5 border border-stone-100/50">
                        <div className="mt-8 flex flex-col items-center gap-5">
                            <div className="relative w-20 h-20">
                                <div className="absolute inset-0 rounded-full border-4 border-primary/20"></div>
                                <div className="absolute inset-0 rounded-full border-4 border-transparent border-t-primary animate-spin"></div>
                                <div className="absolute inset-0 flex items-center justify-center">
                                    <span className="material-symbols-outlined text-primary text-2xl">memory</span>
                                </div>
                            </div>
                            <div className="text-center">
                                <h2 className="text-base font-extrabold text-forest">Loading Local AI</h2>
                                <p className="text-sm font-medium text-forest mt-1">{statusMsg || 'Preparing on-device models…'}</p>
                                {/* <p className="text-[11px] font-medium text-forest mt-2">First load downloads MobileNet (~16MB) and caches it for future visits.</p> */}
                            </div>
                            <div className="flex items-center gap-1.5 px-3 py-1.5 rounded-full bg-primary/10">
                                <span className="material-symbols-outlined text-primary text-sm">lock</span>
                                <span className="text-[11px] font-bold text-primary">No data leaves your device</span>
                            </div>
                        </div>
                    </div>
                )}

                {phase === 'idle' && (
                    <div className="mt-4 space-y-5">
                        <div className="text-center">
                            <h2 className="text-xl font-extrabold text-forest">Upload a Photo</h2>
                            <p className="text-sm text-forest font-medium mt-1 leading-relaxed">
                                {useLocalCNN
                                    ? 'On-device AI analyses visual patterns — no data leaves your device.'
                                    : _aiEngine === 'hybrid'
                                        ? 'Nyckel AI detects mould instantly. Visual insights generated on-device.'
                                        : 'Our AI analyses visual patterns associated with mould and moisture damage.'}
                            </p>
                        </div>
                        {/* Engine indicator */}
                        <div className="flex justify-center">
                            <div className={'inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-[11px] font-bold ' + (useLocalCNN ? 'bg-primary/10 text-forest' : 'bg-forest/10 text-forest')}>
                                <span className="material-symbols-outlined text-sm">
                                    {useLocalCNN ? 'memory' : _aiEngine === 'hybrid' ? 'merge' : 'cloud'}
                                </span>
                                {useLocalCNN
                                    ? 'Local AI · On-Device · Private'
                                    : _aiEngine === 'hybrid'
                                        ? 'Hybrid AI · Nyckel + Visual Insights'
                                        : 'Nyckel API · Cloud Analysis'}
                            </div>
                        </div>
                        <ImageUpload onImageReady={handleImageReady} />
                        <p className="text-[11px] text-forest text-center leading-relaxed">
                            AI-assisted visual analysis for decision-support only. Results should not replace professional inspection.
                        </p>
                    </div>
                )}

                {phase === 'preview' && imageData && (
                    <div className="mt-4 space-y-5">
                        <div className="aspect-video w-full rounded-xl overflow-hidden shadow-soft border-4 border-surface">
                            <img
                                ref={previewImgRef}
                                className="w-full h-full object-cover"
                                src={imageData.previewURL}
                                alt="Upload preview"
                                crossOrigin="anonymous"
                            />
                        </div>
                        <div className="text-center">
                            <p className="text-sm font-extrabold text-forest">{imageData.file.name}</p>
                            <p className="text-xs font-semibold text-muted">{(imageData.file.size / 1024).toFixed(1)} KB</p>
                        </div>
                        <button
                            onClick={handleAnalyze}
                            disabled={!modelReady}
                            className="w-full h-14 bg-forest text-white rounded-full font-extrabold text-lg shadow-clay flex items-center justify-center gap-2 btn-nature hover:brightness-110 transition-all disabled:opacity-50 disabled:cursor-not-allowed"
                        >
                            <span className="material-symbols-outlined">biotech</span>
                            Check for Mould
                        </button>
                        <button
                            onClick={handleReset}
                            className="w-full h-12 bg-surface text-forest rounded-full font-bold text-sm border border-stone-100/50 shadow-soft flex items-center justify-center gap-2 btn-nature hover:bg-forest hover:text-white transition-all duration-300"
                        >
                            <span className="material-symbols-outlined text-lg">refresh</span>
                            Choose Different Image
                        </button>
                    </div>
                )}

                {phase === 'analyzing' && (
                    <div className="bg-background-light mt-4 rounded-xl shadow-soft p-5 border border-stone-100/50">
                        <div className="mt-12 flex flex-col items-center gap-6">
                            <div className="relative w-24 h-24">
                                <div className="absolute inset-0 rounded-full border-4 border-primary/20"></div>
                                <div className="absolute inset-0 rounded-full border-4 border-transparent border-t-primary animate-spin"></div>
                                <div className="absolute inset-0 flex items-center justify-center">
                                    <span className="material-symbols-outlined text-primary text-3xl">biotech</span>
                                </div>
                            </div>
                            <div className="text-center">
                                <h2 className="text-lg font-extrabold text-forest">Analysing Image</h2>
                                <p className="text-sm font-medium text-forest mt-1">{statusMsg || 'Examining your photo for mould indicators…'}</p>
                            </div>
                            {(useLocalCNN || _aiEngine === 'hybrid') && (
                                <div className="flex items-center gap-1.5 px-3 py-1.5 rounded-full bg-primary/10">
                                    <span className="material-symbols-outlined text-primary text-sm">lock</span>
                                    <span className="text-[11px] font-bold text-primary">
                                        {_aiEngine === 'hybrid' ? 'Visual insights processed on your device' : 'Processing on your device'}
                                    </span>
                                </div>
                            )}
                        </div>
                    </div>
                )}

                {phase === 'results' && result && renderResults()}

                {phase === 'error' && (
                    <div className="mt-8 space-y-5">
                        <div className="bg-warning-light rounded-xl p-5 flex items-start gap-3 border border-warning/20">
                            <span className="material-symbols-outlined text-warning mt-0.5">error</span>
                            <div className="flex-1">
                                <h3 className="font-extrabold text-warning mb-1">Analysis Failed</h3>
                                <p className="text-sm font-medium text-forest leading-relaxed">{errorMsg}</p>
                            </div>
                        </div>
                        <button
                            onClick={handleReset}
                            className="w-full h-14 bg-forest text-white rounded-full font-extrabold text-lg shadow-clay flex items-center justify-center gap-2 btn-nature hover:brightness-110 transition-all"
                        >
                            <span className="material-symbols-outlined">refresh</span>
                            Try Again
                        </button>
                    </div>
                )}

            </main>
        </Layout>
    );
};

window.AnalysisPage = AnalysisPage;
