function rs = tdcs_random_slope_interaction(T, formula, term)
%TDCS_RANDOM_SLOPE_INTERACTION Honest LME test of a slope-interaction TERM.
%   RS = TDCS_RANDOM_SLOPE_INTERACTION(T, FORMULA, TERM) refits the linear mixed
%   model FORMULA (which must include a per-subject random SLOPE, e.g.
%   'success ~ day*tDCS + (day|subject)') on table T and returns the
%   Satterthwaite-DF marginal F-test of TERM (e.g. 'day:tDCS').
%
%   Why this is the honest test. The paper's model has only a random INTERCEPT,
%   so it assumes every animal shares one true slope and estimates the slope /
%   interaction with session-level precision -- Satterthwaite DF on that model
%   stays ~= residual DF and does NOT fix the pseudoreplication. Giving each
%   animal its OWN slope (a random slope) lets the between-animal slope variance
%   enter the standard error, and the Satterthwaite denominator DF then collapses
%   toward the number of animals -- matching the per-animal (cluster-honest)
%   test. RS fields: .ok (false if the richer model failed to fit), .F, .df1,
%   .df2 (Satterthwaite), .p.

rs = struct('ok', false, 'F', NaN, 'df1', NaN, 'df2', NaN, 'p', NaN);
w = warning('off', 'all'); cleanup = onCleanup(@() warning(w)); %#ok<NASGU>
try
    lme = fitlme(T, formula);
    A = anova(lme, 'DFMethod', 'satterthwaite');
    i = strcmp(A.Term, term);
    if any(i)
        rs = struct('ok', true, 'F', A.FStat(i), 'df1', A.DF1(i), ...
            'df2', A.DF2(i), 'p', A.pValue(i));
    end
catch
    % Random-slope model unidentifiable / non-convergent (common in short
    % windows or with very few animals): leave rs.ok = false.
end

end
