_renderLhr(json, rootEl, saveGistCallback) {
    // Allow users to view the runnerResult
    if ('lhr' in json) {
      const runnerResult = /** @type {{lhr: LH.Result}} */ (/** @type {unknown} */ (json));
      json = runnerResult.lhr;
    }
    // Allow users to drop in PSI's json
    if ('lighthouseResult' in json) {
      const psiResp = /** @type {{lighthouseResult: LH.Result}} */ (/** @type {unknown} */ (json));
      json = psiResp.lighthouseResult;
    }

    // Install as global for easier debugging
    // @ts-expect-error
    window.__LIGHTHOUSE_JSON__ = json;
    // eslint-disable-next-line no-console
    console.log('window.__LIGHTHOUSE_JSON__', json);

    this._validateReportJson(json);

    // Redirect to old viewer if a v2 report. v3, v4, v5 handled by v5 viewer.
    if (json.lighthouseVersion.startsWith('2')) {
      this._loadInLegacyViewerVersion(json);
      return;
    }

    rootEl.classList.add('lh-root', 'lh-vars');
    const reportDom = new DOM(document, rootEl);
    const renderer = new ReportRenderer(reportDom);

    renderer.renderReport(json, rootEl, {
      occupyEntireViewport: true,
    });

    const features = new ViewerUIFeatures(reportDom, {
      saveGist: saveGistCallback,
      refresh: newLhr => {
        this._replaceReportHtml(newLhr);
      },
      getStandaloneReportHTML() {
        return ReportGenerator.generateReportHtml(json);
      },
    });
    features.initFeatures(json);
  }
@param {LH.Result} json
@param {HTMLElement} rootEl
@param {(json: LH.Result|LH.FlowResult) => void} [saveGistCallback]