function write_gap_report(filename, summary, table1, table2)
                % WRITE_GAP_REPORT  Emit a text report matching your file’s format.
                %
                % Inputs
                %   filename : char/string, path to output .txt
                %   summary  : struct with fields (numeric):
                %       TopJawPitch, TopJawRoll, TopJawYaw, MeanTopJaw, ...
                %       BottomJawPitch, BottomJawRoll, BottomJawYaw, MeanBottomJaw, ...
                %       MeanGap, MeanGapSymmetry, BtmPole1ZVal, RefBlockGap
                %   table1   : Nx5 numeric matrix with columns [Pole, PtNum, X, Y, Z]
                %   table2   : Mx5 numeric matrix with columns [Pole, PtNum, X, Y, Z]
                %
                % Notes on formatting (matched to sample):
                % - Separator lines: 58 dashes
                % - Summary values: generally 4 decimals; BTM Pole #1,Z Val has 3
                % - Table columns: right-aligned with fixed widths and 5 decimals for X/Y/Z

                fid = fopen(filename,'w');
                assert(fid>0, 'Could not open %s for writing.', filename);
                cleaner = onCleanup(@() fclose(fid));

                sep = repmat('-',1,58);
                hdr = '   Pole   Pt. Num.    X Value       Y Value       Z Value';

                % ----- Summary Header -----
                fprintf(fid, '%s\n', sep);
                fprintf(fid, '        ----- Summary of Calculated Values -----\n');
                fprintf(fid, '%s\n', sep);
                fprintf(fid, '\n');

                % helper for aligned "Label = value" with equals signs lined up
                colW = 18; % width of label column to match alignment
                pf  = @(label,fmt,val) fprintf(fid, ['%-' num2str(colW) 's= ' fmt '\n'], label, val);

                % ----- Summary Lines (precisions chosen to match sample) -----
                pf('Top Jaw Pitch'    ,'%.4f', summary.TopJawPitch);
                pf('Top Jaw Roll'     ,'%.4f', summary.TopJawRoll);
                pf('Top Jaw Yaw'      ,'%.4f', summary.TopJawYaw);
                pf('Mean Top Jaw'     ,'%.4f', summary.MeanTopJaw);
                pf('Bottom Jaw Pitch' ,'%.4f', summary.BottomJawPitch);
                pf('Bottom Jaw Roll'  ,'%.4f', summary.BottomJawRoll);
                pf('Bottom Jaw Yaw'   ,'%.4f', summary.BottomJawYaw);
                pf('Mean Bottom Jaw'  ,'%.4f', summary.MeanBottomJaw);
                pf('Mean Gap'         ,'%.4f', summary.MeanGap);
                pf('Mean Gap Symmetry','%.4f', summary.MeanGapSymmetry);
                pf('BTM Pole #1,Z Val','%.3f', summary.BtmPole1ZVal);  % 3 decimals
                pf('Ref. Block Gap'   ,'%.4f', summary.RefBlockGap);

                % ----- First Table -----
                fprintf(fid, '%s\n', sep);
                fprintf(fid, '%s\n', hdr);
                fprintf(fid, '%s\n', sep);

                % Column format (right-aligned widths chosen to match visual spacing)
                %   Pole:   7, PtNum: 10, X: 15.5f, Y: 14.5f, Z: 14.5f
                rowfmt = '%7d%10d%15.5f%14.5f%14.5f\n';

                write_table(fid, table1, rowfmt);

                % ----- Second Table (same header repeated) -----
                fprintf(fid, '%s\n', sep);
                fprintf(fid, '%s\n', hdr);
                fprintf(fid, '%s\n', sep);

                write_table(fid, table2, rowfmt);
            end