function stats = plot_compare_heatmaps(gridCom, gridOpt, z0, outPng)
%PLOT_COMPARE_HEATMAPS  Side-by-side COMSOL / OpticsFEM / difference heatmaps.

Zcom = gridCom.Z;
Zopt = gridOpt.Z;
valid = ~isnan(Zcom) & ~isnan(Zopt);
Zdiff = nan(size(Zcom));
Zdiff(valid) = Zopt(valid) - Zcom(valid);

cmin = min([Zcom(valid); Zopt(valid)]);
cmax = max([Zcom(valid); Zopt(valid)]);

fig = figure('Color', 'w', 'Position', [80 80 1280 420]);

subplot(1, 3, 1);
imagesc(gridCom.X(1, :), gridCom.Y(:, 1), Zcom);
set(gca, 'YDir', 'normal'); axis equal tight;
title(sprintf('COMSOL  |E|  (z=%.2f m)', z0));
xlabel('x (m)'); ylabel('y (m)');
colormap(gca, jet); colorbar; caxis([cmin cmax]);

subplot(1, 3, 2);
imagesc(gridOpt.X(1, :), gridOpt.Y(:, 1), Zopt);
set(gca, 'YDir', 'normal'); axis equal tight;
title(sprintf('OpticsFEM  |E|  (z=%.2f m)', z0));
xlabel('x (m)'); ylabel('y (m)');
colormap(gca, jet); colorbar; caxis([cmin cmax]);

subplot(1, 3, 3);
imagesc(gridCom.X(1, :), gridCom.Y(:, 1), Zdiff);
set(gca, 'YDir', 'normal'); axis equal tight;
title('Difference (OpticsFEM - COMSOL)');
xlabel('x (m)'); ylabel('y (m)');
colormap(gca, jet); colorbar;

sgtitle(sprintf('normE comparison on z = %.2f m plane', z0), 'FontWeight', 'bold');

if nargin >= 4 && ~isempty(outPng)
    outDir = fileparts(outPng);
    if ~isempty(outDir) && ~isfolder(outDir)
        mkdir(outDir);
    end
    exportgraphics(fig, outPng, 'Resolution', 180);
    fprintf('Saved figure: %s\n', outPng);
end

stats.maxAbsDiff = max(abs(Zdiff(valid)));
stats.relL2 = norm(Zdiff(valid)) / norm(Zcom(valid));
stats.comMin = min(Zcom(valid)); stats.comMax = max(Zcom(valid));
stats.optMin = min(Zopt(valid)); stats.optMax = max(Zopt(valid));
fprintf('COMSOL |E|: [%.4f, %.4f] V/m\n', stats.comMin, stats.comMax);
fprintf('OpticsFEM |E|: [%.4f, %.4f] V/m\n', stats.optMin, stats.optMax);
fprintf('max|diff|=%.4e, relL2=%.4e\n', stats.maxAbsDiff, stats.relL2);
end
