Published
Edited
Mar 6, 2020
Insert cell
md`# Lighthouse Test`
Insert cell
md`
This is super hacky. You need to find each "RUN ME" (ctrl f), and run them for the last cell to work.

Report renderer code built with:

\`\`\`
npx terser -o out1.js -- \
lighthouse-core/report/html/renderer/util.js \
lighthouse-core/report/html/renderer/dom.js \
lighthouse-core/report/html/renderer/crc-details-renderer.js \
lighthouse-core/report/html/renderer/snippet-renderer.js \
lighthouse-core/report/html/renderer/logger.js
npx terser -o out2.js -- \
lighthouse-core/report/html/renderer/../../../lib/file-namer.js \
lighthouse-core/report/html/renderer/report-ui-features.js \
lighthouse-core/report/html/renderer/details-renderer.js \
lighthouse-core/report/html/renderer/category-renderer.js \
lighthouse-core/report/html/renderer/performance-category-renderer.js \
lighthouse-core/report/html/renderer/pwa-category-renderer.js \
lighthouse-core/report/html/renderer/report-renderer.js \
lighthouse-core/report/html/renderer/i18n.js
\`\`\`

`
Insert cell
module = undefined
Insert cell
{"use strict";const ELLIPSIS="…";const NBSP=" ";const PASS_THRESHOLD=.9;const SCREENSHOT_PREFIX="data:image/jpeg;base64,";const RATINGS={PASS:{label:"pass",minScore:PASS_THRESHOLD},AVERAGE:{label:"average",minScore:.5},FAIL:{label:"fail"},ERROR:{label:"error"}};const listOfTlds=["com","co","gov","edu","ac","org","go","gob","or","net","in","ne","nic","gouv","web","spb","blog","jus","kiev","mil","wi","qc","ca","bel","on"];class Util{static get PASS_THRESHOLD(){return PASS_THRESHOLD}static get MS_DISPLAY_VALUE(){return`%10d${NBSP}ms`}static prepareReportResult(result){const clone=JSON.parse(JSON.stringify(result));if(!clone.configSettings.locale){clone.configSettings.locale="en"}for(const audit of Object.values(clone.audits)){if(audit.scoreDisplayMode==="not_applicable"||audit.scoreDisplayMode==="not-applicable"){audit.scoreDisplayMode="notApplicable"}if(audit.details){if(audit.details.type===undefined||audit.details.type==="diagnostic"){audit.details.type="debugdata"}if(audit.details.type==="filmstrip"){for(const screenshot of audit.details.items){if(!screenshot.data.startsWith(SCREENSHOT_PREFIX)){screenshot.data=SCREENSHOT_PREFIX+screenshot.data}}}}}if(typeof clone.categories!=="object")throw new Error("No categories provided.");for(const category of Object.values(clone.categories)){category.auditRefs.forEach(auditRef=>{const result=clone.audits[auditRef.id];auditRef.result=result;if(clone.stackPacks){clone.stackPacks.forEach(pack=>{if(pack.descriptions[auditRef.id]){auditRef.stackPacks=auditRef.stackPacks||[];auditRef.stackPacks.push({title:pack.title,iconDataURL:pack.iconDataURL,description:pack.descriptions[auditRef.id]})}})}})}return clone}static showAsPassed(audit){switch(audit.scoreDisplayMode){case"manual":case"notApplicable":return true;case"error":case"informative":return false;case"numeric":case"binary":default:return Number(audit.score)>=RATINGS.PASS.minScore}}static calculateRating(score,scoreDisplayMode){if(scoreDisplayMode==="manual"||scoreDisplayMode==="notApplicable"){return RATINGS.PASS.label}else if(scoreDisplayMode==="error"){return RATINGS.ERROR.label}else if(score===null){return RATINGS.FAIL.label}let rating=RATINGS.FAIL.label;if(score>=RATINGS.PASS.minScore){rating=RATINGS.PASS.label}else if(score>=RATINGS.AVERAGE.minScore){rating=RATINGS.AVERAGE.label}return rating}static splitMarkdownCodeSpans(text){const segments=[];const parts=text.split(/`(.*?)`/g);for(let i=0;i<parts.length;i++){const text=parts[i];if(!text)continue;const isCode=i%2!==0;segments.push({isCode:isCode,text:text})}return segments}static splitMarkdownLink(text){const segments=[];const parts=text.split(/\[([^\]]+?)\]\((https?:\/\/.*?)\)/g);while(parts.length){const[preambleText,linkText,linkHref]=parts.splice(0,3);if(preambleText){segments.push({isLink:false,text:preambleText})}if(linkText&&linkHref){segments.push({isLink:true,text:linkText,linkHref:linkHref})}}return segments}static getURLDisplayName(parsedUrl,options){options=options||{numPathParts:undefined,preserveQuery:undefined,preserveHost:undefined};const numPathParts=options.numPathParts!==undefined?options.numPathParts:2;const preserveQuery=options.preserveQuery!==undefined?options.preserveQuery:true;const preserveHost=options.preserveHost||false;let name;if(parsedUrl.protocol==="about:"||parsedUrl.protocol==="data:"){name=parsedUrl.href}else{name=parsedUrl.pathname;const parts=name.split("/").filter(part=>part.length);if(numPathParts&&parts.length>numPathParts){name=ELLIPSIS+parts.slice(-1*numPathParts).join("/")}if(preserveHost){name=`${parsedUrl.host}/${name.replace(/^\//,"")}`}if(preserveQuery){name=`${name}${parsedUrl.search}`}}const MAX_LENGTH=64;name=name.replace(/([a-f0-9]{7})[a-f0-9]{13}[a-f0-9]*/g,`$1${ELLIPSIS}`);name=name.replace(/([a-zA-Z0-9-_]{9})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9-_]{10,}/g,`$1${ELLIPSIS}`);name=name.replace(/(\d{3})\d{6,}/g,`$1${ELLIPSIS}`);name=name.replace(/\u2026+/g,ELLIPSIS);if(name.length>MAX_LENGTH&&name.includes("?")){name=name.replace(/\?([^=]*)(=)?.*/,`?$1$2${ELLIPSIS}`);if(name.length>MAX_LENGTH){name=name.replace(/\?.*/,`?${ELLIPSIS}`)}}if(name.length>MAX_LENGTH){const dotIndex=name.lastIndexOf(".");if(dotIndex>=0){name=name.slice(0,MAX_LENGTH-1-(name.length-dotIndex))+`${ELLIPSIS}${name.slice(dotIndex)}`}else{name=name.slice(0,MAX_LENGTH-1)+ELLIPSIS}}return name}static parseURL(url){const parsedUrl=new URL(url);return{file:Util.getURLDisplayName(parsedUrl),hostname:parsedUrl.hostname,origin:parsedUrl.origin}}static createOrReturnURL(value){if(value instanceof URL){return value}return new URL(value)}static getTld(hostname){const tlds=hostname.split(".").slice(-2);if(!listOfTlds.includes(tlds[0])){return`.${tlds[tlds.length-1]}`}return`.${tlds.join(".")}`}static getRootDomain(url){const hostname=Util.createOrReturnURL(url).hostname;const tld=Util.getTld(hostname);const splitTld=tld.split(".");return hostname.split(".").slice(-splitTld.length).join(".")}static getEnvironmentDisplayValues(settings){const emulationDesc=Util.getEmulationDescriptions(settings);return[{name:Util.i18n.strings.runtimeSettingsDevice,description:emulationDesc.deviceEmulation},{name:Util.i18n.strings.runtimeSettingsNetworkThrottling,description:emulationDesc.networkThrottling},{name:Util.i18n.strings.runtimeSettingsCPUThrottling,description:emulationDesc.cpuThrottling}]}static getEmulationDescriptions(settings){let cpuThrottling;let networkThrottling;const throttling=settings.throttling;switch(settings.throttlingMethod){case"provided":cpuThrottling=Util.i18n.strings.throttlingProvided;networkThrottling=Util.i18n.strings.throttlingProvided;break;case"devtools":{const{cpuSlowdownMultiplier:cpuSlowdownMultiplier,requestLatencyMs:requestLatencyMs}=throttling;cpuThrottling=`${Util.i18n.formatNumber(cpuSlowdownMultiplier)}x slowdown (DevTools)`;networkThrottling=`${Util.i18n.formatNumber(requestLatencyMs)}${NBSP}ms HTTP RTT, `+`${Util.i18n.formatNumber(throttling.downloadThroughputKbps)}${NBSP}Kbps down, `+`${Util.i18n.formatNumber(throttling.uploadThroughputKbps)}${NBSP}Kbps up (DevTools)`;break}case"simulate":{const{cpuSlowdownMultiplier:cpuSlowdownMultiplier,rttMs:rttMs,throughputKbps:throughputKbps}=throttling;cpuThrottling=`${Util.i18n.formatNumber(cpuSlowdownMultiplier)}x slowdown (Simulated)`;networkThrottling=`${Util.i18n.formatNumber(rttMs)}${NBSP}ms TCP RTT, `+`${Util.i18n.formatNumber(throughputKbps)}${NBSP}Kbps throughput (Simulated)`;break}default:cpuThrottling=Util.i18n.strings.runtimeUnknown;networkThrottling=Util.i18n.strings.runtimeUnknown}let deviceEmulation=Util.i18n.strings.runtimeNoEmulation;if(settings.emulatedFormFactor==="mobile"){deviceEmulation=Util.i18n.strings.runtimeMobileEmulation}else if(settings.emulatedFormFactor==="desktop"){deviceEmulation=Util.i18n.strings.runtimeDesktopEmulation}return{deviceEmulation:deviceEmulation,cpuThrottling:cpuThrottling,networkThrottling:networkThrottling}}static filterRelevantLines(lines,lineMessages,surroundingLineCount){if(lineMessages.length===0){return lines.slice(0,surroundingLineCount*2+1)}const minGapSize=3;const lineNumbersToKeep=new Set;lineMessages=lineMessages.sort((a,b)=>(a.lineNumber||0)-(b.lineNumber||0));lineMessages.forEach(({lineNumber:lineNumber})=>{let firstSurroundingLineNumber=lineNumber-surroundingLineCount;let lastSurroundingLineNumber=lineNumber+surroundingLineCount;while(firstSurroundingLineNumber<1){firstSurroundingLineNumber++;lastSurroundingLineNumber++}if(lineNumbersToKeep.has(firstSurroundingLineNumber-minGapSize-1)){firstSurroundingLineNumber-=minGapSize}for(let i=firstSurroundingLineNumber;i<=lastSurroundingLineNumber;i++){const surroundingLineNumber=i;lineNumbersToKeep.add(surroundingLineNumber)}});return lines.filter(line=>lineNumbersToKeep.has(line.lineNumber))}static isPluginCategory(categoryId){return categoryId.startsWith("lighthouse-plugin-")}}Util.i18n=null;Util.UIStrings={varianceDisclaimer:"Values are estimated and may vary. The performance score is [based only on these metrics](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted).",opportunityResourceColumnLabel:"Opportunity",opportunitySavingsColumnLabel:"Estimated Savings",errorMissingAuditInfo:"Report error: no audit information",errorLabel:"Error!",warningHeader:"Warnings: ",auditGroupExpandTooltip:"Show audits",warningAuditsGroupTitle:"Passed audits but with warnings",passedAuditsGroupTitle:"Passed audits",notApplicableAuditsGroupTitle:"Not applicable",manualAuditsGroupTitle:"Additional items to manually check",toplevelWarningsMessage:"There were issues affecting this run of Lighthouse:",crcInitialNavigation:"Initial Navigation",crcLongestDurationLabel:"Maximum critical path latency:",snippetExpandButtonLabel:"Expand snippet",snippetCollapseButtonLabel:"Collapse snippet",lsPerformanceCategoryDescription:"[Lighthouse](https://developers.google.com/web/tools/lighthouse/) analysis of the current page on an emulated mobile network. Values are estimated and may vary.",labDataTitle:"Lab Data",thirdPartyResourcesLabel:"Show 3rd-party resources",dropdownPrintSummary:"Print Summary",dropdownPrintExpanded:"Print Expanded",dropdownCopyJSON:"Copy JSON",dropdownSaveHTML:"Save as HTML",dropdownSaveJSON:"Save as JSON",dropdownViewer:"Open in Viewer",dropdownSaveGist:"Save as Gist",dropdownDarkTheme:"Toggle Dark Theme",runtimeSettingsTitle:"Runtime Settings",runtimeSettingsUrl:"URL",runtimeSettingsFetchTime:"Fetch Time",runtimeSettingsDevice:"Device",runtimeSettingsNetworkThrottling:"Network throttling",runtimeSettingsCPUThrottling:"CPU throttling",runtimeSettingsChannel:"Channel",runtimeSettingsUA:"User agent (host)",runtimeSettingsUANetwork:"User agent (network)",runtimeSettingsBenchmark:"CPU/Memory Power",footerIssue:"File an issue",runtimeNoEmulation:"No emulation",runtimeMobileEmulation:"Emulated Moto G4",runtimeDesktopEmulation:"Emulated Desktop",runtimeUnknown:"Unknown",throttlingProvided:"Provided by environment"};if(typeof module!=="undefined"&&module.exports){module.exports=Util}else{self.Util=Util}"use strict";class DOM{constructor(document){this._document=document;this._lighthouseChannel="unknown"}createElement(name,className,attrs={}){const element=this._document.createElement(name);if(className){element.className=className}Object.keys(attrs).forEach(key=>{const value=attrs[key];if(typeof value!=="undefined"){element.setAttribute(key,value)}});return element}createFragment(){return this._document.createDocumentFragment()}createChildOf(parentElem,elementName,className,attrs){const element=this.createElement(elementName,className,attrs);parentElem.appendChild(element);return element}cloneTemplate(selector,context){const template=context.querySelector(selector);if(!template){throw new Error(`Template not found: template${selector}`)}const clone=this._document.importNode(template.content,true);if(template.hasAttribute("data-stamped")){this.findAll("style",clone).forEach(style=>style.remove())}template.setAttribute("data-stamped","true");return clone}resetTemplates(){this.findAll("template[data-stamped]",this._document).forEach(t=>{t.removeAttribute("data-stamped")})}convertMarkdownLinkSnippets(text){const element=this.createElement("span");for(const segment of Util.splitMarkdownLink(text)){if(!segment.isLink){element.appendChild(this._document.createTextNode(segment.text));continue}const url=new URL(segment.linkHref);const DOCS_ORIGINS=["https://developers.google.com","https://web.dev"];if(DOCS_ORIGINS.includes(url.origin)){url.searchParams.set("utm_source","lighthouse");url.searchParams.set("utm_medium",this._lighthouseChannel)}const a=this.createElement("a");a.rel="noopener";a.target="_blank";a.textContent=segment.text;a.href=url.href;element.appendChild(a)}return element}convertMarkdownCodeSnippets(markdownText){const element=this.createElement("span");for(const segment of Util.splitMarkdownCodeSpans(markdownText)){if(segment.isCode){const pre=this.createElement("code");pre.textContent=segment.text;element.appendChild(pre)}else{element.appendChild(this._document.createTextNode(segment.text))}}return element}setLighthouseChannel(lighthouseChannel){this._lighthouseChannel=lighthouseChannel}document(){return this._document}isDevTools(){return!!this._document.querySelector(".lh-devtools")}find(query,context){const result=context.querySelector(query);if(result===null){throw new Error(`query ${query} not found`)}return result}findAll(query,context){return Array.from(context.querySelectorAll(query))}}if(typeof module!=="undefined"&&module.exports){module.exports=DOM}else{self.DOM=DOM}"use strict";class CriticalRequestChainRenderer{static initTree(tree){let startTime=0;const rootNodes=Object.keys(tree);if(rootNodes.length>0){const node=tree[rootNodes[0]];startTime=node.request.startTime}return{tree:tree,startTime:startTime,transferSize:0}}static createSegment(parent,id,startTime,transferSize,treeMarkers,parentIsLastChild){const node=parent[id];const siblings=Object.keys(parent);const isLastChild=siblings.indexOf(id)===siblings.length-1;const hasChildren=!!node.children&&Object.keys(node.children).length>0;const newTreeMarkers=Array.isArray(treeMarkers)?treeMarkers.slice(0):[];if(typeof parentIsLastChild!=="undefined"){newTreeMarkers.push(!parentIsLastChild)}return{node:node,isLastChild:isLastChild,hasChildren:hasChildren,startTime:startTime,transferSize:transferSize+node.request.transferSize,treeMarkers:newTreeMarkers}}static createChainNode(dom,tmpl,segment,detailsRenderer){const chainsEl=dom.cloneTemplate("#tmpl-lh-crc__chains",tmpl);dom.find(".crc-node",chainsEl).setAttribute("title",segment.node.request.url);const treeMarkeEl=dom.find(".crc-node__tree-marker",chainsEl);segment.treeMarkers.forEach(separator=>{if(separator){treeMarkeEl.appendChild(dom.createElement("span","tree-marker vert"));treeMarkeEl.appendChild(dom.createElement("span","tree-marker"))}else{treeMarkeEl.appendChild(dom.createElement("span","tree-marker"));treeMarkeEl.appendChild(dom.createElement("span","tree-marker"))}});if(segment.isLastChild){treeMarkeEl.appendChild(dom.createElement("span","tree-marker up-right"));treeMarkeEl.appendChild(dom.createElement("span","tree-marker right"))}else{treeMarkeEl.appendChild(dom.createElement("span","tree-marker vert-right"));treeMarkeEl.appendChild(dom.createElement("span","tree-marker right"))}if(segment.hasChildren){treeMarkeEl.appendChild(dom.createElement("span","tree-marker horiz-down"))}else{treeMarkeEl.appendChild(dom.createElement("span","tree-marker right"))}const url=segment.node.request.url;const linkEl=detailsRenderer.renderTextURL(url);const treevalEl=dom.find(".crc-node__tree-value",chainsEl);treevalEl.appendChild(linkEl);if(!segment.hasChildren){const{startTime:startTime,endTime:endTime,transferSize:transferSize}=segment.node.request;const span=dom.createElement("span","crc-node__chain-duration");span.textContent=" - "+Util.i18n.formatMilliseconds((endTime-startTime)*1e3)+", ";const span2=dom.createElement("span","crc-node__chain-duration");span2.textContent=Util.i18n.formatBytesToKB(transferSize,.01);treevalEl.appendChild(span);treevalEl.appendChild(span2)}return chainsEl}static buildTree(dom,tmpl,segment,elem,details,detailsRenderer){elem.appendChild(CRCRenderer.createChainNode(dom,tmpl,segment,detailsRenderer));if(segment.node.children){for(const key of Object.keys(segment.node.children)){const childSegment=CRCRenderer.createSegment(segment.node.children,key,segment.startTime,segment.transferSize,segment.treeMarkers,segment.isLastChild);CRCRenderer.buildTree(dom,tmpl,childSegment,elem,details,detailsRenderer)}}}static render(dom,templateContext,details,detailsRenderer){const tmpl=dom.cloneTemplate("#tmpl-lh-crc",templateContext);const containerEl=dom.find(".lh-crc",tmpl);dom.find(".crc-initial-nav",tmpl).textContent=Util.i18n.strings.crcInitialNavigation;dom.find(".lh-crc__longest_duration_label",tmpl).textContent=Util.i18n.strings.crcLongestDurationLabel;dom.find(".lh-crc__longest_duration",tmpl).textContent=Util.i18n.formatMilliseconds(details.longestChain.duration);const root=CRCRenderer.initTree(details.chains);for(const key of Object.keys(root.tree)){const segment=CRCRenderer.createSegment(root.tree,key,root.startTime,root.transferSize);CRCRenderer.buildTree(dom,tmpl,segment,containerEl,details,detailsRenderer)}return dom.find(".lh-crc-container",tmpl)}}const CRCRenderer=CriticalRequestChainRenderer;if(typeof module!=="undefined"&&module.exports){module.exports=CriticalRequestChainRenderer}else{self.CriticalRequestChainRenderer=CriticalRequestChainRenderer}"use strict";const LineVisibility={ALWAYS:0,WHEN_COLLAPSED:1,WHEN_EXPANDED:2};const LineContentType={CONTENT_NORMAL:0,CONTENT_HIGHLIGHTED:1,PLACEHOLDER:2,MESSAGE:3};const classNamesByContentType={[LineContentType.CONTENT_NORMAL]:["lh-snippet__line--content"],[LineContentType.CONTENT_HIGHLIGHTED]:["lh-snippet__line--content","lh-snippet__line--content-highlighted"],[LineContentType.PLACEHOLDER]:["lh-snippet__line--placeholder"],[LineContentType.MESSAGE]:["lh-snippet__line--message"]};function getLineAndPreviousLine(lines,lineNumber){return{line:lines.find(l=>l.lineNumber===lineNumber),previousLine:lines.find(l=>l.lineNumber===lineNumber-1)}}function getMessagesForLineNumber(messages,lineNumber){return messages.filter(h=>h.lineNumber===lineNumber)}function getLinesWhenCollapsed(details){const SURROUNDING_LINES_TO_SHOW_WHEN_COLLAPSED=2;return Util.filterRelevantLines(details.lines,details.lineMessages,SURROUNDING_LINES_TO_SHOW_WHEN_COLLAPSED)}class SnippetRenderer{static renderHeader(dom,tmpl,details,detailsRenderer,toggleExpandedFn){const linesWhenCollapsed=getLinesWhenCollapsed(details);const canExpand=linesWhenCollapsed.length<details.lines.length;const header=dom.cloneTemplate("#tmpl-lh-snippet__header",tmpl);dom.find(".lh-snippet__title",header).textContent=details.title;const{snippetCollapseButtonLabel:snippetCollapseButtonLabel,snippetExpandButtonLabel:snippetExpandButtonLabel}=Util.i18n.strings;dom.find(".lh-snippet__btn-label-collapse",header).textContent=snippetCollapseButtonLabel;dom.find(".lh-snippet__btn-label-expand",header).textContent=snippetExpandButtonLabel;const toggleExpandButton=dom.find(".lh-snippet__toggle-expand",header);if(!canExpand){toggleExpandButton.remove()}else{toggleExpandButton.addEventListener("click",()=>toggleExpandedFn())}if(details.node&&dom.isDevTools()){const nodeContainer=dom.find(".lh-snippet__node",header);nodeContainer.appendChild(detailsRenderer.renderNode(details.node))}return header}static renderSnippetLine(dom,tmpl,{content:content,lineNumber:lineNumber,truncated:truncated,contentType:contentType,visibility:visibility}){const clonedTemplate=dom.cloneTemplate("#tmpl-lh-snippet__line",tmpl);const contentLine=dom.find(".lh-snippet__line",clonedTemplate);const{classList:classList}=contentLine;classNamesByContentType[contentType].forEach(typeClass=>classList.add(typeClass));if(visibility===LineVisibility.WHEN_COLLAPSED){classList.add("lh-snippet__show-if-collapsed")}else if(visibility===LineVisibility.WHEN_EXPANDED){classList.add("lh-snippet__show-if-expanded")}const lineContent=content+(truncated?"…":"");const lineContentEl=dom.find(".lh-snippet__line code",contentLine);if(contentType===LineContentType.MESSAGE){lineContentEl.appendChild(dom.convertMarkdownLinkSnippets(lineContent))}else{lineContentEl.textContent=lineContent}dom.find(".lh-snippet__line-number",contentLine).textContent=lineNumber.toString();return contentLine}static renderMessage(dom,tmpl,message){return SnippetRenderer.renderSnippetLine(dom,tmpl,{lineNumber:" ",content:message.message,contentType:LineContentType.MESSAGE})}static renderOmittedLinesPlaceholder(dom,tmpl,visibility){return SnippetRenderer.renderSnippetLine(dom,tmpl,{lineNumber:"…",content:"",visibility:visibility,contentType:LineContentType.PLACEHOLDER})}static renderSnippetContent(dom,tmpl,details){const template=dom.cloneTemplate("#tmpl-lh-snippet__content",tmpl);const snippetEl=dom.find(".lh-snippet__snippet-inner",template);details.generalMessages.forEach(m=>snippetEl.append(SnippetRenderer.renderMessage(dom,tmpl,m)));snippetEl.append(SnippetRenderer.renderSnippetLines(dom,tmpl,details));return template}static renderSnippetLines(dom,tmpl,details){const{lineMessages:lineMessages,generalMessages:generalMessages,lineCount:lineCount,lines:lines}=details;const linesWhenCollapsed=getLinesWhenCollapsed(details);const hasOnlyGeneralMessages=generalMessages.length>0&&lineMessages.length===0;const lineContainer=dom.createFragment();let hasPendingOmittedLinesPlaceholderForCollapsedState=false;for(let lineNumber=1;lineNumber<=lineCount;lineNumber++){const{line:line,previousLine:previousLine}=getLineAndPreviousLine(lines,lineNumber);const{line:lineWhenCollapsed,previousLine:previousLineWhenCollapsed}=getLineAndPreviousLine(linesWhenCollapsed,lineNumber);const showLineWhenCollapsed=!!lineWhenCollapsed;const showPreviousLineWhenCollapsed=!!previousLineWhenCollapsed;if(showPreviousLineWhenCollapsed&&!showLineWhenCollapsed){hasPendingOmittedLinesPlaceholderForCollapsedState=true}if(showLineWhenCollapsed&&hasPendingOmittedLinesPlaceholderForCollapsedState){lineContainer.append(SnippetRenderer.renderOmittedLinesPlaceholder(dom,tmpl,LineVisibility.WHEN_COLLAPSED));hasPendingOmittedLinesPlaceholderForCollapsedState=false}const isFirstOmittedLineWhenExpanded=!line&&!!previousLine;const isFirstLineOverallAndIsOmittedWhenExpanded=!line&&lineNumber===1;if(isFirstOmittedLineWhenExpanded||isFirstLineOverallAndIsOmittedWhenExpanded){const hasRenderedAllLinesVisibleWhenCollapsed=!linesWhenCollapsed.some(l=>l.lineNumber>lineNumber);const onlyShowWhenExpanded=hasRenderedAllLinesVisibleWhenCollapsed||lineNumber===1;lineContainer.append(SnippetRenderer.renderOmittedLinesPlaceholder(dom,tmpl,onlyShowWhenExpanded?LineVisibility.WHEN_EXPANDED:LineVisibility.ALWAYS));hasPendingOmittedLinesPlaceholderForCollapsedState=false}if(!line){continue}const messages=getMessagesForLineNumber(lineMessages,lineNumber);const highlightLine=messages.length>0||hasOnlyGeneralMessages;const contentLineDetails=Object.assign({},line,{contentType:highlightLine?LineContentType.CONTENT_HIGHLIGHTED:LineContentType.CONTENT_NORMAL,visibility:lineWhenCollapsed?LineVisibility.ALWAYS:LineVisibility.WHEN_EXPANDED});lineContainer.append(SnippetRenderer.renderSnippetLine(dom,tmpl,contentLineDetails));messages.forEach(message=>{lineContainer.append(SnippetRenderer.renderMessage(dom,tmpl,message))})}return lineContainer}static render(dom,templateContext,details,detailsRenderer){const tmpl=dom.cloneTemplate("#tmpl-lh-snippet",templateContext);const snippetEl=dom.find(".lh-snippet",tmpl);const header=SnippetRenderer.renderHeader(dom,tmpl,details,detailsRenderer,()=>snippetEl.classList.toggle("lh-snippet--expanded"));const content=SnippetRenderer.renderSnippetContent(dom,tmpl,details);snippetEl.append(header,content);return snippetEl}}if(typeof module!=="undefined"&&module.exports){module.exports=SnippetRenderer}else{self.SnippetRenderer=SnippetRenderer}"use strict";class Logger{constructor(element){this.el=element;this._id=undefined}log(msg,autoHide=true){this._id&&clearTimeout(this._id);this.el.textContent=msg;this.el.classList.add("show");if(autoHide){this._id=setTimeout(_=>{this.el.classList.remove("show")},7e3)}}warn(msg){this.log("Warning: "+msg)}error(msg){this.log(msg);setTimeout(_=>{throw new Error(msg)},0)}hide(){this._id&&clearTimeout(this._id);this.el.classList.remove("show")}}if(typeof module!=="undefined"&&module.exports){module.exports=Logger}}
Insert cell
Util = self.Util // RUN ME
Insert cell
CriticalRequestChainRenderer = self.CriticalRequestChainRenderer; // RUN ME
Insert cell
SnippetRenderer = self.SnippetRenderer // RUN ME
Insert cell
{"use strict";function getFilenamePrefix(lhr){const hostname=new URL(lhr.finalUrl).hostname;const date=lhr.fetchTime&&new Date(lhr.fetchTime)||new Date;const timeStr=date.toLocaleTimeString("en-US",{hour12:false});const dateParts=date.toLocaleDateString("en-US",{year:"numeric",month:"2-digit",day:"2-digit"}).split("/");dateParts.unshift(dateParts.pop());const dateStr=dateParts.join("-");const filenamePrefix=`${hostname}_${dateStr}_${timeStr}`;return filenamePrefix.replace(/[\/?<>\\:*|"]/g,"-")}if(typeof module!=="undefined"&&module.exports){module.exports={getFilenamePrefix:getFilenamePrefix}}"use strict";function getTableRows(tableEl){return Array.from(tableEl.tBodies[0].rows)}class ReportUIFeatures{constructor(dom){this.json;this._dom=dom;this._document=this._dom.document();this._templateContext=this._dom.document();this._dropDown=new DropDown(this._dom);this._copyAttempt=false;this.topbarEl;this.scoreScaleEl;this.stickyHeaderEl;this.highlightEl;this.onMediaQueryChange=this.onMediaQueryChange.bind(this);this.onCopy=this.onCopy.bind(this);this.onDropDownMenuClick=this.onDropDownMenuClick.bind(this);this.onKeyUp=this.onKeyUp.bind(this);this.collapseAllDetails=this.collapseAllDetails.bind(this);this.expandAllDetails=this.expandAllDetails.bind(this);this._toggleDarkTheme=this._toggleDarkTheme.bind(this);this._updateStickyHeaderOnScroll=this._updateStickyHeaderOnScroll.bind(this)}initFeatures(report){this.json=report;this._setupMediaQueryListeners();this._dropDown.setup(this.onDropDownMenuClick);this._setupThirdPartyFilter();this._setUpCollapseDetailsAfterPrinting();this._resetUIState();this._document.addEventListener("keyup",this.onKeyUp);this._document.addEventListener("copy",this.onCopy);const topbarLogo=this._dom.find(".lh-topbar__logo",this._document);topbarLogo.addEventListener("click",()=>this._toggleDarkTheme());let turnOffTheLights=false;if(!this._dom.isDevTools()&&window.matchMedia("(prefers-color-scheme: dark)").matches){turnOffTheLights=true}const scoresAll100=Object.values(report.categories).every(cat=>cat.score===1);const hasAllCoreCategories=Object.keys(report.categories).filter(id=>!Util.isPluginCategory(id)).length>=5;if(scoresAll100&&hasAllCoreCategories){turnOffTheLights=true;this._enableFireworks()}if(turnOffTheLights){this._toggleDarkTheme(true)}if(Object.keys(this.json.categories).length>=2){this._setupStickyHeaderElements();const containerEl=this._dom.find(".lh-container",this._document);const elToAddScrollListener=this._getScrollParent(containerEl);elToAddScrollListener.addEventListener("scroll",this._updateStickyHeaderOnScroll);if(this._dom.isDevTools()){const resizeObserver=new window.ResizeObserver(this._updateStickyHeaderOnScroll);resizeObserver.observe(containerEl)}else{window.addEventListener("resize",this._updateStickyHeaderOnScroll)}}const hasMetricError=report.categories.performance&&report.categories.performance.auditRefs.some(audit=>Boolean(audit.group==="metrics"&&report.audits[audit.id].errorMessage));if(hasMetricError){const toggleInputEl=this._dom.find(".lh-metrics-toggle__input",this._document);toggleInputEl.checked=true}for(const node of this._dom.findAll("[data-i18n]",this._dom.document())){const i18nAttr=node.getAttribute("data-i18n");node.textContent=Util.i18n.strings[i18nAttr]}}setTemplateContext(context){this._templateContext=context}_getScrollParent(element){const{overflowY:overflowY}=window.getComputedStyle(element);const isScrollable=overflowY!=="visible"&&overflowY!=="hidden";if(isScrollable){return element}if(element.parentElement){return this._getScrollParent(element.parentElement)}return document}_enableFireworks(){const scoresContainer=this._dom.find(".lh-scores-container",this._document);scoresContainer.classList.add("score100");scoresContainer.addEventListener("click",_=>{scoresContainer.classList.toggle("fireworks-paused")})}_fireEventOn(name,target=this._document,detail){const event=new CustomEvent(name,detail?{detail:detail}:undefined);target.dispatchEvent(event)}_setupMediaQueryListeners(){const mediaQuery=self.matchMedia("(max-width: 500px)");mediaQuery.addListener(this.onMediaQueryChange);this.onMediaQueryChange(mediaQuery)}onMediaQueryChange(mql){const root=this._dom.find(".lh-root",this._document);root.classList.toggle("lh-narrow",mql.matches)}_setupThirdPartyFilter(){const thirdPartyFilterAuditExclusions=["uses-rel-preconnect"];const thirdPartyFilterAuditHideByDefault=["legacy-javascript"];const tables=Array.from(this._document.querySelectorAll(".lh-table"));const tablesWithUrls=tables.filter(el=>el.querySelector("td.lh-table-column--url, td.lh-table-column--source-location")).filter(el=>{const containingAudit=el.closest(".lh-audit");if(!containingAudit)throw new Error(".lh-table not within audit");return!thirdPartyFilterAuditExclusions.includes(containingAudit.id)});tablesWithUrls.forEach((tableEl,index)=>{const rowEls=getTableRows(tableEl);const thirdPartyRows=this._getThirdPartyRows(rowEls,this.json.finalUrl);const filterTemplate=this._dom.cloneTemplate("#tmpl-lh-3p-filter",this._templateContext);const filterInput=this._dom.find("input",filterTemplate);const id=`lh-3p-filter-label--${index}`;filterInput.id=id;filterInput.addEventListener("change",e=>{if(e.target instanceof HTMLInputElement&&!e.target.checked){for(const row of thirdPartyRows.values()){row.remove()}}else{for(const[position,row]of thirdPartyRows.entries()){const childrenArr=getTableRows(tableEl);tableEl.tBodies[0].insertBefore(row,childrenArr[position])}}});this._dom.find("label",filterTemplate).setAttribute("for",id);this._dom.find(".lh-3p-filter-count",filterTemplate).textContent=`${thirdPartyRows.size}`;this._dom.find(".lh-3p-ui-string",filterTemplate).textContent=Util.i18n.strings.thirdPartyResourcesLabel;const allThirdParty=thirdPartyRows.size===rowEls.length;const allFirstParty=!thirdPartyRows.size;if(allThirdParty||allFirstParty){filterInput.disabled=true;filterInput.checked=allThirdParty}if(!tableEl.parentNode)return;tableEl.parentNode.insertBefore(filterTemplate,tableEl);const containingAudit=tableEl.closest(".lh-audit");if(!containingAudit)throw new Error(".lh-table not within audit");if(thirdPartyFilterAuditHideByDefault.includes(containingAudit.id)&&!allThirdParty){filterInput.click()}})}_getThirdPartyRows(rowEls,finalUrl){const thirdPartyRows=new Map;const finalUrlRootDomain=Util.getRootDomain(finalUrl);rowEls.forEach((rowEl,rowPosition)=>{const urlItem=rowEl.querySelector(".lh-text__url");if(!urlItem)return;const datasetUrl=urlItem.dataset.url;if(!datasetUrl)return;const isThirdParty=Util.getRootDomain(datasetUrl)!==finalUrlRootDomain;if(!isThirdParty)return;thirdPartyRows.set(Number(rowPosition),rowEl)});return thirdPartyRows}_getUrlItems(tableEl){return this._dom.findAll(".lh-text__url",tableEl)}_setupStickyHeaderElements(){this.topbarEl=this._dom.find(".lh-topbar",this._document);this.scoreScaleEl=this._dom.find(".lh-scorescale",this._document);this.stickyHeaderEl=this._dom.find(".lh-sticky-header",this._document);this.highlightEl=this._dom.createChildOf(this.stickyHeaderEl,"div","lh-highlighter")}onCopy(e){if(this._copyAttempt&&e.clipboardData){e.preventDefault();e.clipboardData.setData("text/plain",JSON.stringify(this.json,null,2));this._fireEventOn("lh-log",this._document,{cmd:"log",msg:"Report JSON copied to clipboard"})}this._copyAttempt=false}onCopyButtonClick(){this._fireEventOn("lh-analytics",this._document,{cmd:"send",fields:{hitType:"event",eventCategory:"report",eventAction:"copy"}});try{if(this._document.queryCommandSupported("copy")){this._copyAttempt=true;if(!this._document.execCommand("copy")){this._copyAttempt=false;this._fireEventOn("lh-log",this._document,{cmd:"warn",msg:"Your browser does not support copy to clipboard."})}}}catch(e){this._copyAttempt=false;this._fireEventOn("lh-log",this._document,{cmd:"log",msg:e.message})}}_resetUIState(){this._dropDown.close();this._dom.resetTemplates()}onDropDownMenuClick(e){e.preventDefault();const el=e.target;if(!el||!el.hasAttribute("data-action")){return}switch(el.getAttribute("data-action")){case"copy":this.onCopyButtonClick();break;case"print-summary":this.collapseAllDetails();this._print();break;case"print-expanded":this.expandAllDetails();this._print();break;case"save-json":{const jsonStr=JSON.stringify(this.json,null,2);this._saveFile(new Blob([jsonStr],{type:"application/json"}));break}case"save-html":{const htmlStr=this.getReportHtml();try{this._saveFile(new Blob([htmlStr],{type:"text/html"}))}catch(e){this._fireEventOn("lh-log",this._document,{cmd:"error",msg:"Could not export as HTML. "+e.message})}break}case"open-viewer":{const viewerPath="/lighthouse/viewer/";ReportUIFeatures.openTabAndSendJsonReport(this.json,viewerPath);break}case"save-gist":{this.saveAsGist();break}case"toggle-dark":{this._toggleDarkTheme();break}}this._dropDown.close()}_print(){self.print()}onKeyUp(e){if((e.ctrlKey||e.metaKey)&&e.keyCode===80){this._dropDown.close()}}static openTabAndSendJsonReport(reportJson,viewerPath){const VIEWER_ORIGIN="https://googlechrome.github.io";const json=reportJson;window.addEventListener("message",function msgHandler(messageEvent){if(messageEvent.origin!==VIEWER_ORIGIN){return}if(popup&&messageEvent.data.opened){popup.postMessage({lhresults:json},VIEWER_ORIGIN);window.removeEventListener("message",msgHandler)}});const fallbackFetchTime=json.generatedTime;const fetchTime=json.fetchTime||fallbackFetchTime;const windowName=`${json.lighthouseVersion}-${json.requestedUrl}-${fetchTime}`;const popup=window.open(`${VIEWER_ORIGIN}${viewerPath}`,windowName)}expandAllDetails(){const details=this._dom.findAll(".lh-categories details",this._document);details.map(detail=>detail.open=true)}collapseAllDetails(){const details=this._dom.findAll(".lh-categories details",this._document);details.map(detail=>detail.open=false)}_setUpCollapseDetailsAfterPrinting(){if("onbeforeprint"in self){self.addEventListener("afterprint",this.collapseAllDetails)}else{const win=self;win.matchMedia("print").addListener(mql=>{if(mql.matches){this.expandAllDetails()}else{this.collapseAllDetails()}})}}getReportHtml(){this._resetUIState();return this._document.documentElement.outerHTML}saveAsGist(){throw new Error("Cannot save as gist from base report")}_saveFile(blob){const filename=getFilenamePrefix({finalUrl:this.json.finalUrl,fetchTime:this.json.fetchTime});const ext=blob.type.match("json")?".json":".html";const href=URL.createObjectURL(blob);const a=this._dom.createElement("a");a.download=`${filename}${ext}`;a.href=href;this._document.body.appendChild(a);a.click();this._document.body.removeChild(a);setTimeout(_=>URL.revokeObjectURL(href),500)}_toggleDarkTheme(force){const el=this._dom.find(".lh-vars",this._document);if(typeof force==="undefined"){el.classList.toggle("dark")}else{el.classList.toggle("dark",force)}}_updateStickyHeaderOnScroll(){const topbarBottom=this.topbarEl.getBoundingClientRect().bottom;const scoreScaleTop=this.scoreScaleEl.getBoundingClientRect().top;const showStickyHeader=topbarBottom>=scoreScaleTop;const categoryEls=Array.from(this._document.querySelectorAll(".lh-category"));const categoriesAboveTheMiddle=categoryEls.filter(el=>el.getBoundingClientRect().top-window.innerHeight/2<0);const highlightIndex=categoriesAboveTheMiddle.length>0?categoriesAboveTheMiddle.length-1:0;const gaugeWrapperEls=this.stickyHeaderEl.querySelectorAll(".lh-gauge__wrapper");const gaugeToHighlight=gaugeWrapperEls[highlightIndex];const origin=gaugeWrapperEls[0].getBoundingClientRect().left;const offset=gaugeToHighlight.getBoundingClientRect().left-origin;this.highlightEl.style.transform=`translate(${offset}px)`;this.stickyHeaderEl.classList.toggle("lh-sticky-header--visible",showStickyHeader)}}class DropDown{constructor(dom){this._dom=dom;this._toggleEl;this._menuEl;this.onDocumentKeyDown=this.onDocumentKeyDown.bind(this);this.onToggleClick=this.onToggleClick.bind(this);this.onToggleKeydown=this.onToggleKeydown.bind(this);this.onMenuFocusOut=this.onMenuFocusOut.bind(this);this.onMenuKeydown=this.onMenuKeydown.bind(this);this._getNextMenuItem=this._getNextMenuItem.bind(this);this._getNextSelectableNode=this._getNextSelectableNode.bind(this);this._getPreviousMenuItem=this._getPreviousMenuItem.bind(this)}setup(menuClickHandler){this._toggleEl=this._dom.find(".lh-tools__button",this._dom.document());this._toggleEl.addEventListener("click",this.onToggleClick);this._toggleEl.addEventListener("keydown",this.onToggleKeydown);this._menuEl=this._dom.find(".lh-tools__dropdown",this._dom.document());this._menuEl.addEventListener("keydown",this.onMenuKeydown);this._menuEl.addEventListener("click",menuClickHandler)}close(){this._toggleEl.classList.remove("active");this._toggleEl.setAttribute("aria-expanded","false");if(this._menuEl.contains(this._dom.document().activeElement)){this._toggleEl.focus()}this._menuEl.removeEventListener("focusout",this.onMenuFocusOut);this._dom.document().removeEventListener("keydown",this.onDocumentKeyDown)}open(firstFocusElement){if(this._toggleEl.classList.contains("active")){firstFocusElement.focus()}else{this._menuEl.addEventListener("transitionend",()=>{firstFocusElement.focus()},{once:true})}this._toggleEl.classList.add("active");this._toggleEl.setAttribute("aria-expanded","true");this._menuEl.addEventListener("focusout",this.onMenuFocusOut);this._dom.document().addEventListener("keydown",this.onDocumentKeyDown)}onToggleClick(e){e.preventDefault();e.stopImmediatePropagation();if(this._toggleEl.classList.contains("active")){this.close()}else{this.open(this._getNextMenuItem())}}onToggleKeydown(e){switch(e.code){case"ArrowUp":e.preventDefault();this.open(this._getPreviousMenuItem());break;case"ArrowDown":case"Enter":case" ":e.preventDefault();this.open(this._getNextMenuItem());break;default:}}onMenuKeydown(e){const el=e.target;switch(e.code){case"ArrowUp":e.preventDefault();this._getPreviousMenuItem(el).focus();break;case"ArrowDown":e.preventDefault();this._getNextMenuItem(el).focus();break;case"Home":e.preventDefault();this._getNextMenuItem().focus();break;case"End":e.preventDefault();this._getPreviousMenuItem().focus();break;default:}}onDocumentKeyDown(e){if(e.keyCode===27){this.close()}}onMenuFocusOut(e){const focusEvent=e;const focusedEl=focusEvent.relatedTarget;if(!this._menuEl.contains(focusedEl)){this.close()}}_getNextSelectableNode(allNodes,startNode){const nodes=allNodes.filter(node=>{if(!(node instanceof HTMLElement)){return false}if(node.hasAttribute("disabled")){return false}if(window.getComputedStyle(node).display==="none"){return false}return true});let nextIndex=startNode?nodes.indexOf(startNode)+1:0;if(nextIndex>=nodes.length){nextIndex=0}return nodes[nextIndex]}_getNextMenuItem(startEl){const nodes=Array.from(this._menuEl.childNodes);return this._getNextSelectableNode(nodes,startEl)}_getPreviousMenuItem(startEl){const nodes=Array.from(this._menuEl.childNodes).reverse();return this._getNextSelectableNode(nodes,startEl)}}if(typeof module!=="undefined"&&module.exports){module.exports=ReportUIFeatures}else{self.ReportUIFeatures=ReportUIFeatures}"use strict";const URL_PREFIXES=["http://","https://","data:"];class DetailsRenderer{constructor(dom){this._dom=dom;this._templateContext}setTemplateContext(context){this._templateContext=context}render(details){switch(details.type){case"filmstrip":return this._renderFilmstrip(details);case"list":return this._renderList(details);case"table":return this._renderTable(details);case"criticalrequestchain":return CriticalRequestChainRenderer.render(this._dom,this._templateContext,details,this);case"opportunity":return this._renderTable(details);case"screenshot":case"debugdata":return null;default:{return this._renderUnknown(details.type,details)}}}_renderBytes(details){const value=Util.i18n.formatBytesToKB(details.value,details.granularity);return this._renderText(value)}_renderMilliseconds(details){let value=Util.i18n.formatMilliseconds(details.value,details.granularity);if(details.displayUnit==="duration"){value=Util.i18n.formatDuration(details.value)}return this._renderText(value)}renderTextURL(text){const url=text;let displayedPath;let displayedHost;let title;try{const parsed=Util.parseURL(url);displayedPath=parsed.file==="/"?parsed.origin:parsed.file;displayedHost=parsed.file==="/"?"":`(${parsed.hostname})`;title=url}catch(e){displayedPath=url}const element=this._dom.createElement("div","lh-text__url");element.appendChild(this._renderLink({text:displayedPath,url:url}));if(displayedHost){const hostElem=this._renderText(displayedHost);hostElem.classList.add("lh-text__url-host");element.appendChild(hostElem)}if(title){element.title=url;element.dataset.url=url}return element}_renderLink(details){const allowedProtocols=["https:","http:"];let url;try{url=new URL(details.url)}catch(_){}if(!url||!allowedProtocols.includes(url.protocol)){return this._renderText(details.text)}const a=this._dom.createElement("a");a.rel="noopener";a.target="_blank";a.textContent=details.text;a.href=url.href;return a}_renderText(text){const element=this._dom.createElement("div","lh-text");element.textContent=text;return element}_renderNumeric(text){const element=this._dom.createElement("div","lh-numeric");element.textContent=text;return element}_renderThumbnail(details){const element=this._dom.createElement("img","lh-thumbnail");const strValue=details;element.src=strValue;element.title=strValue;element.alt="";return element}_renderUnknown(type,value){console.error(`Unknown details type: ${type}`,value);const element=this._dom.createElement("details","lh-unknown");this._dom.createChildOf(element,"summary").textContent=`We don't know how to render audit details of type \`${type}\`. `+"The Lighthouse version that collected this data is likely newer than the Lighthouse "+"version of the report renderer. Expand for the raw JSON.";this._dom.createChildOf(element,"pre").textContent=JSON.stringify(value,null,2);return element}_renderTableValue(value,heading){if(typeof value==="undefined"||value===null){return null}if(typeof value==="object"){switch(value.type){case"code":{return this._renderCode(value.value)}case"link":{return this._renderLink(value)}case"node":{return this.renderNode(value)}case"source-location":{return this.renderSourceLocation(value)}case"url":{return this.renderTextURL(value.value)}default:{return this._renderUnknown(value.type,value)}}}switch(heading.valueType){case"bytes":{const numValue=Number(value);return this._renderBytes({value:numValue,granularity:heading.granularity})}case"code":{const strValue=String(value);return this._renderCode(strValue)}case"ms":{const msValue={value:Number(value),granularity:heading.granularity,displayUnit:heading.displayUnit};return this._renderMilliseconds(msValue)}case"numeric":{const strValue=String(value);return this._renderNumeric(strValue)}case"text":{const strValue=String(value);return this._renderText(strValue)}case"thumbnail":{const strValue=String(value);return this._renderThumbnail(strValue)}case"timespanMs":{const numValue=Number(value);return this._renderMilliseconds({value:numValue})}case"url":{const strValue=String(value);if(URL_PREFIXES.some(prefix=>strValue.startsWith(prefix))){return this.renderTextURL(strValue)}else{return this._renderCode(strValue)}}default:{return this._renderUnknown(heading.valueType,value)}}}_getCanonicalizedHeadingsFromTable(tableLike){if(tableLike.type==="opportunity"){return tableLike.headings}return tableLike.headings.map(heading=>this._getCanonicalizedHeading(heading))}_getCanonicalizedHeading(heading){let subRows;if(heading.subRows){subRows=this._getCanonicalizedHeading(heading.subRows);if(!subRows.key){console.warn("key should not be null")}subRows={...subRows,key:subRows.key||""}}return{key:heading.key,valueType:heading.itemType,subRows:subRows,label:heading.text,displayUnit:heading.displayUnit,granularity:heading.granularity}}_renderSubRows(values,heading){const subRowsElement=this._dom.createElement("div","lh-sub-rows");for(const childValue of values){const subRowElement=this._renderTableValue(childValue,heading);if(!subRowElement)continue;subRowElement.classList.add("lh-sub-row");subRowsElement.appendChild(subRowElement)}return subRowsElement}_renderTable(details){if(!details.items.length)return this._dom.createElement("span");const tableElem=this._dom.createElement("table","lh-table");const theadElem=this._dom.createChildOf(tableElem,"thead");const theadTrElem=this._dom.createChildOf(theadElem,"tr");const headings=this._getCanonicalizedHeadingsFromTable(details);for(const heading of headings){const valueType=heading.valueType||"text";const classes=`lh-table-column--${valueType}`;const labelEl=this._dom.createElement("div","lh-text");labelEl.textContent=heading.label;this._dom.createChildOf(theadTrElem,"th",classes).appendChild(labelEl)}const tbodyElem=this._dom.createChildOf(tableElem,"tbody");for(const row of details.items){const rowElem=this._dom.createChildOf(tbodyElem,"tr");for(const heading of headings){const valueFragment=this._dom.createFragment();if(heading.key===null&&!heading.subRows){console.warn("A header with a null `key` should define `subRows`.")}if(heading.key===null){const emptyElement=this._dom.createElement("div");emptyElement.innerHTML="&nbsp;";valueFragment.appendChild(emptyElement)}else{const value=row[heading.key];const valueElement=value!==undefined&&!Array.isArray(value)&&this._renderTableValue(value,heading);if(valueElement)valueFragment.appendChild(valueElement)}if(heading.subRows){const subRowsHeading={key:heading.subRows.key,valueType:heading.subRows.valueType||heading.valueType,granularity:heading.subRows.granularity||heading.granularity,displayUnit:heading.subRows.displayUnit||heading.displayUnit,label:""};const values=row[subRowsHeading.key];if(Array.isArray(values)){const subRowsElement=this._renderSubRows(values,subRowsHeading);valueFragment.appendChild(subRowsElement)}}if(valueFragment.childElementCount){const classes=`lh-table-column--${heading.valueType}`;this._dom.createChildOf(rowElem,"td",classes).appendChild(valueFragment)}else{this._dom.createChildOf(rowElem,"td","lh-table-column--empty")}}}return tableElem}_renderList(details){const listContainer=this._dom.createElement("div","lh-list");details.items.forEach(item=>{const snippetEl=SnippetRenderer.render(this._dom,this._templateContext,item,this);listContainer.appendChild(snippetEl)});return listContainer}renderNode(item){const element=this._dom.createElement("span","lh-node");if(item.nodeLabel){const nodeLabelEl=this._dom.createElement("div");nodeLabelEl.textContent=item.nodeLabel;element.appendChild(nodeLabelEl)}if(item.snippet){const snippetEl=this._dom.createElement("div");snippetEl.classList.add("lh-node__snippet");snippetEl.textContent=item.snippet;element.appendChild(snippetEl)}if(item.selector){element.title=item.selector}if(item.path)element.setAttribute("data-path",item.path);if(item.selector)element.setAttribute("data-selector",item.selector);if(item.snippet)element.setAttribute("data-snippet",item.snippet);return element}renderSourceLocation(item){if(!item.url){return null}const line=item.line+1;const column=item.column;let element;if(item.urlProvider==="network"){element=this.renderTextURL(item.url);this._dom.find("a",element).textContent+=`:${line}:${column}`}else{element=this._renderText(`${item.url}:${line}:${column} (from sourceURL)`)}element.classList.add("lh-source-location");element.setAttribute("data-source-url",item.url);element.setAttribute("data-source-line",String(item.line));element.setAttribute("data-source-column",String(item.column));return element}_renderFilmstrip(details){const filmstripEl=this._dom.createElement("div","lh-filmstrip");for(const thumbnail of details.items){const frameEl=this._dom.createChildOf(filmstripEl,"div","lh-filmstrip__frame");this._dom.createChildOf(frameEl,"img","lh-filmstrip__thumbnail",{src:thumbnail.data,alt:`Screenshot`})}return filmstripEl}_renderCode(text){const pre=this._dom.createElement("pre","lh-code");pre.textContent=text;return pre}}if(typeof module!=="undefined"&&module.exports){module.exports=DetailsRenderer}else{self.DetailsRenderer=DetailsRenderer}"use strict";class CategoryRenderer{constructor(dom,detailsRenderer){this.dom=dom;this.detailsRenderer=detailsRenderer;this.templateContext=this.dom.document();this.detailsRenderer.setTemplateContext(this.templateContext)}get _clumpTitles(){return{warning:Util.i18n.strings.warningAuditsGroupTitle,manual:Util.i18n.strings.manualAuditsGroupTitle,passed:Util.i18n.strings.passedAuditsGroupTitle,notApplicable:Util.i18n.strings.notApplicableAuditsGroupTitle}}renderAudit(audit){const tmpl=this.dom.cloneTemplate("#tmpl-lh-audit",this.templateContext);return this.populateAuditValues(audit,tmpl)}populateAuditValues(audit,tmpl){const strings=Util.i18n.strings;const auditEl=this.dom.find(".lh-audit",tmpl);auditEl.id=audit.result.id;const scoreDisplayMode=audit.result.scoreDisplayMode;if(audit.result.displayValue){this.dom.find(".lh-audit__display-text",auditEl).textContent=audit.result.displayValue}const titleEl=this.dom.find(".lh-audit__title",auditEl);titleEl.appendChild(this.dom.convertMarkdownCodeSnippets(audit.result.title));this.dom.find(".lh-audit__description",auditEl).appendChild(this.dom.convertMarkdownLinkSnippets(audit.result.description));if(audit.stackPacks){audit.stackPacks.forEach(pack=>{const packElm=this.dom.createElement("div");packElm.classList.add("lh-audit__stackpack");const packElmImg=this.dom.createElement("img");packElmImg.classList.add("lh-audit__stackpack__img");packElmImg.src=pack.iconDataURL;packElmImg.alt=pack.title;packElm.appendChild(packElmImg);packElm.appendChild(this.dom.convertMarkdownLinkSnippets(pack.description));this.dom.find(".lh-audit__stackpacks",auditEl).appendChild(packElm)})}const header=this.dom.find("details",auditEl);if(audit.result.details){const elem=this.detailsRenderer.render(audit.result.details);if(elem){elem.classList.add("lh-details");header.appendChild(elem)}}this.dom.find(".lh-chevron-container",auditEl).appendChild(this._createChevron());this._setRatingClass(auditEl,audit.result.score,scoreDisplayMode);if(audit.result.scoreDisplayMode==="error"){auditEl.classList.add(`lh-audit--error`);const textEl=this.dom.find(".lh-audit__display-text",auditEl);textEl.textContent=strings.errorLabel;textEl.classList.add("tooltip-boundary");const tooltip=this.dom.createChildOf(textEl,"div","tooltip tooltip--error");tooltip.textContent=audit.result.errorMessage||strings.errorMissingAuditInfo}else if(audit.result.explanation){const explEl=this.dom.createChildOf(titleEl,"div","lh-audit-explanation");explEl.textContent=audit.result.explanation}const warnings=audit.result.warnings;if(!warnings||warnings.length===0)return auditEl;const summaryEl=this.dom.find("summary",header);const warningsEl=this.dom.createChildOf(summaryEl,"div","lh-warnings");this.dom.createChildOf(warningsEl,"span").textContent=strings.warningHeader;if(warnings.length===1){warningsEl.appendChild(this.dom.document().createTextNode(warnings.join("")))}else{const warningsUl=this.dom.createChildOf(warningsEl,"ul");for(const warning of warnings){const item=this.dom.createChildOf(warningsUl,"li");item.textContent=warning}}return auditEl}_createChevron(){const chevronTmpl=this.dom.cloneTemplate("#tmpl-lh-chevron",this.templateContext);const chevronEl=this.dom.find(".lh-chevron",chevronTmpl);return chevronEl}_setRatingClass(element,score,scoreDisplayMode){const rating=Util.calculateRating(score,scoreDisplayMode);element.classList.add(`lh-audit--${scoreDisplayMode.toLowerCase()}`);if(scoreDisplayMode!=="informative"){element.classList.add(`lh-audit--${rating}`)}return element}renderCategoryHeader(category,groupDefinitions){const tmpl=this.dom.cloneTemplate("#tmpl-lh-category-header",this.templateContext);const gaugeContainerEl=this.dom.find(".lh-score__gauge",tmpl);const gaugeEl=this.renderScoreGauge(category,groupDefinitions);gaugeContainerEl.appendChild(gaugeEl);if(category.description){const descEl=this.dom.convertMarkdownLinkSnippets(category.description);this.dom.find(".lh-category-header__description",tmpl).appendChild(descEl)}return tmpl.firstElementChild}renderAuditGroup(group){const groupEl=this.dom.createElement("div","lh-audit-group");const auditGroupHeader=this.dom.createElement("div","lh-audit-group__header");this.dom.createChildOf(auditGroupHeader,"span","lh-audit-group__title").textContent=group.title;if(group.description){const descriptionEl=this.dom.convertMarkdownLinkSnippets(group.description);descriptionEl.classList.add("lh-audit-group__description");auditGroupHeader.appendChild(descriptionEl)}groupEl.appendChild(auditGroupHeader);return groupEl}_renderGroupedAudits(auditRefs,groupDefinitions){const grouped=new Map;const notAGroup="NotAGroup";grouped.set(notAGroup,[]);for(const auditRef of auditRefs){const groupId=auditRef.group||notAGroup;const groupAuditRefs=grouped.get(groupId)||[];groupAuditRefs.push(auditRef);grouped.set(groupId,groupAuditRefs)}const auditElements=[];for(const[groupId,groupAuditRefs]of grouped){if(groupId===notAGroup){for(const auditRef of groupAuditRefs){auditElements.push(this.renderAudit(auditRef))}continue}const groupDef=groupDefinitions[groupId];const auditGroupElem=this.renderAuditGroup(groupDef);for(const auditRef of groupAuditRefs){auditGroupElem.appendChild(this.renderAudit(auditRef))}auditGroupElem.classList.add(`lh-audit-group--${groupId}`);auditElements.push(auditGroupElem)}return auditElements}renderUnexpandableClump(auditRefs,groupDefinitions){const clumpElement=this.dom.createElement("div");const elements=this._renderGroupedAudits(auditRefs,groupDefinitions);elements.forEach(elem=>clumpElement.appendChild(elem));return clumpElement}renderClump(clumpId,{auditRefs:auditRefs,description:description}){const clumpTmpl=this.dom.cloneTemplate("#tmpl-lh-clump",this.templateContext);const clumpElement=this.dom.find(".lh-clump",clumpTmpl);if(clumpId==="warning"){clumpElement.setAttribute("open","")}const summaryInnerEl=this.dom.find(".lh-audit-group__summary",clumpElement);const chevronEl=summaryInnerEl.appendChild(this._createChevron());chevronEl.title=Util.i18n.strings.auditGroupExpandTooltip;const headerEl=this.dom.find(".lh-audit-group__header",clumpElement);const title=this._clumpTitles[clumpId];this.dom.find(".lh-audit-group__title",headerEl).textContent=title;if(description){const descriptionEl=this.dom.convertMarkdownLinkSnippets(description);descriptionEl.classList.add("lh-audit-group__description");headerEl.appendChild(descriptionEl)}const itemCountEl=this.dom.find(".lh-audit-group__itemcount",clumpElement);itemCountEl.textContent=`(${auditRefs.length})`;const auditElements=auditRefs.map(this.renderAudit.bind(this));clumpElement.append(...auditElements);clumpElement.classList.add(`lh-clump--${clumpId.toLowerCase()}`);return clumpElement}setTemplateContext(context){this.templateContext=context;this.detailsRenderer.setTemplateContext(context)}renderScoreGauge(category,groupDefinitions){const tmpl=this.dom.cloneTemplate("#tmpl-lh-gauge",this.templateContext);const wrapper=this.dom.find(".lh-gauge__wrapper",tmpl);wrapper.href=`#${category.id}`;wrapper.classList.add(`lh-gauge__wrapper--${Util.calculateRating(category.score)}`);if(Util.isPluginCategory(category.id)){wrapper.classList.add("lh-gauge__wrapper--plugin")}const numericScore=Number(category.score);const gauge=this.dom.find(".lh-gauge",tmpl);const gaugeArc=gauge.querySelector(".lh-gauge-arc");if(gaugeArc)this._setGaugeArc(gaugeArc,numericScore);const scoreOutOf100=Math.round(numericScore*100);const percentageEl=this.dom.find(".lh-gauge__percentage",tmpl);percentageEl.textContent=scoreOutOf100.toString();if(category.score===null){percentageEl.textContent="?";percentageEl.title=Util.i18n.strings.errorLabel}this.dom.find(".lh-gauge__label",tmpl).textContent=category.title;return tmpl}_setGaugeArc(arcElem,percent){const circumferencePx=2*Math.PI*Number(arcElem.getAttribute("r"));const strokeWidthPx=Number(arcElem.getAttribute("stroke-width"));const rotationalAdjustmentPercent=.25*strokeWidthPx/circumferencePx;arcElem.style.transform=`rotate(${-90+rotationalAdjustmentPercent*360}deg)`;let arcLengthPx=percent*circumferencePx-strokeWidthPx/2;if(percent===0)arcElem.style.opacity="0";if(percent===1)arcLengthPx=circumferencePx;arcElem.style.strokeDasharray=`${Math.max(arcLengthPx,0)} ${circumferencePx}`}_auditHasWarning(audit){return Boolean(audit.result.warnings&&audit.result.warnings.length)}_getClumpIdForAuditRef(auditRef){const scoreDisplayMode=auditRef.result.scoreDisplayMode;if(scoreDisplayMode==="manual"||scoreDisplayMode==="notApplicable"){return scoreDisplayMode}if(Util.showAsPassed(auditRef.result)){if(this._auditHasWarning(auditRef)){return"warning"}else{return"passed"}}else{return"failed"}}render(category,groupDefinitions={}){const element=this.dom.createElement("div","lh-category");this.createPermalinkSpan(element,category.id);element.appendChild(this.renderCategoryHeader(category,groupDefinitions));const clumps=new Map;clumps.set("failed",[]);clumps.set("warning",[]);clumps.set("manual",[]);clumps.set("passed",[]);clumps.set("notApplicable",[]);for(const auditRef of category.auditRefs){const clumpId=this._getClumpIdForAuditRef(auditRef);const clump=clumps.get(clumpId);clump.push(auditRef);clumps.set(clumpId,clump)}for(const[clumpId,auditRefs]of clumps){if(auditRefs.length===0)continue;if(clumpId==="failed"){const clumpElem=this.renderUnexpandableClump(auditRefs,groupDefinitions);clumpElem.classList.add(`lh-clump--failed`);element.appendChild(clumpElem);continue}const description=clumpId==="manual"?category.manualDescription:undefined;const clumpElem=this.renderClump(clumpId,{auditRefs:auditRefs,description:description});element.appendChild(clumpElem)}return element}createPermalinkSpan(element,id){const permalinkEl=this.dom.createChildOf(element,"span","lh-permalink");permalinkEl.id=id}}if(typeof module!=="undefined"&&module.exports){module.exports=CategoryRenderer}else{self.CategoryRenderer=CategoryRenderer}"use strict";class PerformanceCategoryRenderer extends CategoryRenderer{_renderMetric(audit){const tmpl=this.dom.cloneTemplate("#tmpl-lh-metric",this.templateContext);const element=this.dom.find(".lh-metric",tmpl);element.id=audit.result.id;const rating=Util.calculateRating(audit.result.score,audit.result.scoreDisplayMode);element.classList.add(`lh-metric--${rating}`);const titleEl=this.dom.find(".lh-metric__title",tmpl);titleEl.textContent=audit.result.title;const valueEl=this.dom.find(".lh-metric__value",tmpl);valueEl.textContent=audit.result.displayValue||"";const descriptionEl=this.dom.find(".lh-metric__description",tmpl);descriptionEl.appendChild(this.dom.convertMarkdownLinkSnippets(audit.result.description));if(audit.result.scoreDisplayMode==="error"){descriptionEl.textContent="";valueEl.textContent="Error!";const tooltip=this.dom.createChildOf(descriptionEl,"span");tooltip.textContent=audit.result.errorMessage||"Report error: no metric information"}return element}_renderOpportunity(audit,scale){const oppTmpl=this.dom.cloneTemplate("#tmpl-lh-opportunity",this.templateContext);const element=this.populateAuditValues(audit,oppTmpl);element.id=audit.result.id;if(!audit.result.details||audit.result.scoreDisplayMode==="error"){return element}const details=audit.result.details;if(details.type!=="opportunity"){return element}const displayEl=this.dom.find(".lh-audit__display-text",element);const sparklineWidthPct=`${details.overallSavingsMs/scale*100}%`;this.dom.find(".lh-sparkline__bar",element).style.width=sparklineWidthPct;displayEl.textContent=Util.i18n.formatSeconds(details.overallSavingsMs,.01);if(audit.result.displayValue){const displayValue=audit.result.displayValue;this.dom.find(".lh-load-opportunity__sparkline",element).title=displayValue;displayEl.title=displayValue}return element}_getWastedMs(audit){if(audit.result.details&&audit.result.details.type==="opportunity"){const details=audit.result.details;if(typeof details.overallSavingsMs!=="number"){throw new Error("non-opportunity details passed to _getWastedMs")}return details.overallSavingsMs}else{return Number.MIN_VALUE}}render(category,groups,environment){const strings=Util.i18n.strings;const element=this.dom.createElement("div","lh-category");if(environment==="PSI"){const gaugeEl=this.dom.createElement("div","lh-score__gauge");gaugeEl.appendChild(this.renderScoreGauge(category,groups));element.appendChild(gaugeEl)}else{this.createPermalinkSpan(element,category.id);element.appendChild(this.renderCategoryHeader(category,groups))}const metricAuditsEl=this.renderAuditGroup(groups.metrics);const toggleTmpl=this.dom.cloneTemplate("#tmpl-lh-metrics-toggle",this.templateContext);const _toggleEl=this.dom.find(".lh-metrics-toggle",toggleTmpl);metricAuditsEl.append(..._toggleEl.childNodes);const metricAudits=category.auditRefs.filter(audit=>audit.group==="metrics");const keyMetrics=metricAudits.filter(a=>a.weight>=3);const otherMetrics=metricAudits.filter(a=>a.weight<3);const metricsBoxesEl=this.dom.createChildOf(metricAuditsEl,"div","lh-columns");const metricsColumn1El=this.dom.createChildOf(metricsBoxesEl,"div","lh-column");const metricsColumn2El=this.dom.createChildOf(metricsBoxesEl,"div","lh-column");keyMetrics.forEach(item=>{metricsColumn1El.appendChild(this._renderMetric(item))});otherMetrics.forEach(item=>{metricsColumn2El.appendChild(this._renderMetric(item))});if(environment!=="PSI"){const estValuesEl=this.dom.createChildOf(metricAuditsEl,"div","lh-metrics__disclaimer");const disclaimerEl=this.dom.convertMarkdownLinkSnippets(strings.varianceDisclaimer);estValuesEl.appendChild(disclaimerEl)}metricAuditsEl.classList.add("lh-audit-group--metrics");element.appendChild(metricAuditsEl);const timelineEl=this.dom.createChildOf(element,"div","lh-filmstrip-container");const thumbnailAudit=category.auditRefs.find(audit=>audit.id==="screenshot-thumbnails");const thumbnailResult=thumbnailAudit&&thumbnailAudit.result;if(thumbnailResult&&thumbnailResult.details){timelineEl.id=thumbnailResult.id;const filmstripEl=this.detailsRenderer.render(thumbnailResult.details);filmstripEl&&timelineEl.appendChild(filmstripEl)}const budgetTableEls=[];["performance-budget","timing-budget"].forEach(id=>{const audit=category.auditRefs.find(audit=>audit.id===id);if(audit&&audit.result.details){const table=this.detailsRenderer.render(audit.result.details);if(table){table.id=id;table.classList.add("lh-audit");budgetTableEls.push(table)}}});if(budgetTableEls.length>0){const budgetsGroupEl=this.renderAuditGroup(groups.budgets);budgetTableEls.forEach(table=>budgetsGroupEl.appendChild(table));budgetsGroupEl.classList.add("lh-audit-group--budgets");element.appendChild(budgetsGroupEl)}const opportunityAudits=category.auditRefs.filter(audit=>audit.group==="load-opportunities"&&!Util.showAsPassed(audit.result)).sort((auditA,auditB)=>this._getWastedMs(auditB)-this._getWastedMs(auditA));if(opportunityAudits.length){const minimumScale=2e3;const wastedMsValues=opportunityAudits.map(audit=>this._getWastedMs(audit));const maxWaste=Math.max(...wastedMsValues);const scale=Math.max(Math.ceil(maxWaste/1e3)*1e3,minimumScale);const groupEl=this.renderAuditGroup(groups["load-opportunities"]);const tmpl=this.dom.cloneTemplate("#tmpl-lh-opportunity-header",this.templateContext);this.dom.find(".lh-load-opportunity__col--one",tmpl).textContent=strings.opportunityResourceColumnLabel;this.dom.find(".lh-load-opportunity__col--two",tmpl).textContent=strings.opportunitySavingsColumnLabel;const headerEl=this.dom.find(".lh-load-opportunity__header",tmpl);groupEl.appendChild(headerEl);opportunityAudits.forEach(item=>groupEl.appendChild(this._renderOpportunity(item,scale)));groupEl.classList.add("lh-audit-group--load-opportunities");element.appendChild(groupEl)}const diagnosticAudits=category.auditRefs.filter(audit=>audit.group==="diagnostics"&&!Util.showAsPassed(audit.result)).sort((a,b)=>{const scoreA=a.result.scoreDisplayMode==="informative"?100:Number(a.result.score);const scoreB=b.result.scoreDisplayMode==="informative"?100:Number(b.result.score);return scoreA-scoreB});if(diagnosticAudits.length){const groupEl=this.renderAuditGroup(groups["diagnostics"]);diagnosticAudits.forEach(item=>groupEl.appendChild(this.renderAudit(item)));groupEl.classList.add("lh-audit-group--diagnostics");element.appendChild(groupEl)}const passedAudits=category.auditRefs.filter(audit=>(audit.group==="load-opportunities"||audit.group==="diagnostics")&&Util.showAsPassed(audit.result));if(!passedAudits.length)return element;const clumpOpts={auditRefs:passedAudits,groupDefinitions:groups};const passedElem=this.renderClump("passed",clumpOpts);element.appendChild(passedElem);return element}}if(typeof module!=="undefined"&&module.exports){module.exports=PerformanceCategoryRenderer}else{self.PerformanceCategoryRenderer=PerformanceCategoryRenderer}"use strict";const getUniqueSuffix=(()=>{let svgSuffix=0;return function(){return svgSuffix++}})();class PwaCategoryRenderer extends CategoryRenderer{render(category,groupDefinitions={}){const categoryElem=this.dom.createElement("div","lh-category");this.createPermalinkSpan(categoryElem,category.id);categoryElem.appendChild(this.renderCategoryHeader(category,groupDefinitions));const auditRefs=category.auditRefs;const regularAuditRefs=auditRefs.filter(ref=>ref.result.scoreDisplayMode!=="manual");const auditsElem=this._renderAudits(regularAuditRefs,groupDefinitions);categoryElem.appendChild(auditsElem);const manualAuditRefs=auditRefs.filter(ref=>ref.result.scoreDisplayMode==="manual");const manualElem=this.renderClump("manual",{auditRefs:manualAuditRefs,description:category.manualDescription});categoryElem.appendChild(manualElem);return categoryElem}renderScoreGauge(category,groupDefinitions){if(category.score===null){return super.renderScoreGauge(category,groupDefinitions)}const tmpl=this.dom.cloneTemplate("#tmpl-lh-gauge--pwa",this.templateContext);const wrapper=this.dom.find(".lh-gauge--pwa__wrapper",tmpl);wrapper.href=`#${category.id}`;const svgRoot=tmpl.querySelector("svg");if(!svgRoot)throw new Error("no SVG element found in PWA score gauge template");PwaCategoryRenderer._makeSvgReferencesUnique(svgRoot);const allGroups=this._getGroupIds(category.auditRefs);const passingGroupIds=this._getPassingGroupIds(category.auditRefs);if(passingGroupIds.size===allGroups.size){wrapper.classList.add("lh-badged--all")}else{for(const passingGroupId of passingGroupIds){wrapper.classList.add(`lh-badged--${passingGroupId}`)}}this.dom.find(".lh-gauge__label",tmpl).textContent=category.title;wrapper.title=this._getGaugeTooltip(category.auditRefs,groupDefinitions);return tmpl}_getGroupIds(auditRefs){const groupIds=auditRefs.map(ref=>ref.group).filter(g=>!!g);return new Set(groupIds)}_getPassingGroupIds(auditRefs){const uniqueGroupIds=this._getGroupIds(auditRefs);for(const auditRef of auditRefs){if(!Util.showAsPassed(auditRef.result)&&auditRef.group){uniqueGroupIds.delete(auditRef.group)}}return uniqueGroupIds}_getGaugeTooltip(auditRefs,groupDefinitions){const groupIds=this._getGroupIds(auditRefs);const tips=[];for(const groupId of groupIds){const groupAuditRefs=auditRefs.filter(ref=>ref.group===groupId);const auditCount=groupAuditRefs.length;const passedCount=groupAuditRefs.filter(ref=>Util.showAsPassed(ref.result)).length;const title=groupDefinitions[groupId].title;tips.push(`${title}: ${passedCount}/${auditCount}`)}return tips.join(", ")}_renderAudits(auditRefs,groupDefinitions){const auditsElem=this.renderUnexpandableClump(auditRefs,groupDefinitions);const passsingGroupIds=this._getPassingGroupIds(auditRefs);for(const groupId of passsingGroupIds){const groupElem=this.dom.find(`.lh-audit-group--${groupId}`,auditsElem);groupElem.classList.add("lh-badged")}return auditsElem}static _makeSvgReferencesUnique(svgRoot){const defsEl=svgRoot.querySelector("defs");if(!defsEl)return;const idSuffix=getUniqueSuffix();const elementsToUpdate=defsEl.querySelectorAll("[id]");for(const el of elementsToUpdate){const oldId=el.id;const newId=`${oldId}-${idSuffix}`;el.id=newId;const useEls=svgRoot.querySelectorAll(`use[href="#${oldId}"]`);for(const useEl of useEls){useEl.setAttribute("href",`#${newId}`)}const fillEls=svgRoot.querySelectorAll(`[fill="url(#${oldId})"]`);for(const fillEl of fillEls){fillEl.setAttribute("fill",`url(#${newId})`)}}}}if(typeof module!=="undefined"&&module.exports){module.exports=PwaCategoryRenderer}else{self.PwaCategoryRenderer=PwaCategoryRenderer}"use strict";class ReportRenderer{constructor(dom){this._dom=dom;this._templateContext=this._dom.document()}renderReport(result,container){this._dom.setLighthouseChannel(result.configSettings.channel||"unknown");const report=Util.prepareReportResult(result);container.textContent="";container.appendChild(this._renderReport(report));return container}setTemplateContext(context){this._templateContext=context}_renderReportTopbar(report){const el=this._dom.cloneTemplate("#tmpl-lh-topbar",this._templateContext);const metadataUrl=this._dom.find(".lh-topbar__url",el);metadataUrl.href=metadataUrl.textContent=report.finalUrl;metadataUrl.title=report.finalUrl;return el}_renderReportHeader(){const el=this._dom.cloneTemplate("#tmpl-lh-heading",this._templateContext);const domFragment=this._dom.cloneTemplate("#tmpl-lh-scores-wrapper",this._templateContext);const placeholder=this._dom.find(".lh-scores-wrapper-placeholder",el);placeholder.parentNode.replaceChild(domFragment,placeholder);return el}_renderReportFooter(report){const footer=this._dom.cloneTemplate("#tmpl-lh-footer",this._templateContext);const env=this._dom.find(".lh-env__items",footer);env.id="runtime-settings";this._dom.find(".lh-env__title",footer).textContent=Util.i18n.strings.runtimeSettingsTitle;const envValues=Util.getEnvironmentDisplayValues(report.configSettings||{});[{name:Util.i18n.strings.runtimeSettingsUrl,description:report.finalUrl},{name:Util.i18n.strings.runtimeSettingsFetchTime,description:Util.i18n.formatDateTime(report.fetchTime)},...envValues,{name:Util.i18n.strings.runtimeSettingsChannel,description:report.configSettings.channel},{name:Util.i18n.strings.runtimeSettingsUA,description:report.userAgent},{name:Util.i18n.strings.runtimeSettingsUANetwork,description:report.environment&&report.environment.networkUserAgent},{name:Util.i18n.strings.runtimeSettingsBenchmark,description:report.environment&&report.environment.benchmarkIndex.toFixed(0)}].forEach(runtime=>{if(!runtime.description)return;const item=this._dom.cloneTemplate("#tmpl-lh-env__items",env);this._dom.find(".lh-env__name",item).textContent=runtime.name;this._dom.find(".lh-env__description",item).textContent=runtime.description;env.appendChild(item)});this._dom.find(".lh-footer__version_issue",footer).textContent=Util.i18n.strings.footerIssue;this._dom.find(".lh-footer__version",footer).textContent=report.lighthouseVersion;return footer}_renderReportWarnings(report){if(!report.runWarnings||report.runWarnings.length===0){return this._dom.createElement("div")}const container=this._dom.cloneTemplate("#tmpl-lh-warnings--toplevel",this._templateContext);const message=this._dom.find(".lh-warnings__msg",container);message.textContent=Util.i18n.strings.toplevelWarningsMessage;const warnings=this._dom.find("ul",container);for(const warningString of report.runWarnings){const warning=warnings.appendChild(this._dom.createElement("li"));warning.textContent=warningString}return container}_renderScoreGauges(report,categoryRenderer,specificCategoryRenderers){const defaultGauges=[];const customGauges=[];const pluginGauges=[];for(const category of Object.values(report.categories)){const renderer=specificCategoryRenderers[category.id]||categoryRenderer;const categoryGauge=renderer.renderScoreGauge(category,report.categoryGroups||{});if(Util.isPluginCategory(category.id)){pluginGauges.push(categoryGauge)}else if(renderer.renderScoreGauge===categoryRenderer.renderScoreGauge){defaultGauges.push(categoryGauge)}else{customGauges.push(categoryGauge)}}return[...defaultGauges,...customGauges,...pluginGauges]}_renderReport(report){const i18n=new I18n(report.configSettings.locale,{...Util.UIStrings,...report.i18n.rendererFormattedStrings});Util.i18n=i18n;const detailsRenderer=new DetailsRenderer(this._dom);const categoryRenderer=new CategoryRenderer(this._dom,detailsRenderer);categoryRenderer.setTemplateContext(this._templateContext);const specificCategoryRenderers={performance:new PerformanceCategoryRenderer(this._dom,detailsRenderer),pwa:new PwaCategoryRenderer(this._dom,detailsRenderer)};Object.values(specificCategoryRenderers).forEach(renderer=>{renderer.setTemplateContext(this._templateContext)});const headerContainer=this._dom.createElement("div");headerContainer.appendChild(this._renderReportHeader());const reportContainer=this._dom.createElement("div","lh-container");const reportSection=this._dom.createElement("div","lh-report");reportSection.appendChild(this._renderReportWarnings(report));let scoreHeader;const isSoloCategory=Object.keys(report.categories).length===1;if(!isSoloCategory){scoreHeader=this._dom.createElement("div","lh-scores-header")}else{headerContainer.classList.add("lh-header--solo-category")}if(scoreHeader){const scoreScale=this._dom.cloneTemplate("#tmpl-lh-scorescale",this._templateContext);const scoresContainer=this._dom.find(".lh-scores-container",headerContainer);scoreHeader.append(...this._renderScoreGauges(report,categoryRenderer,specificCategoryRenderers));scoresContainer.appendChild(scoreHeader);scoresContainer.appendChild(scoreScale);const stickyHeader=this._dom.createElement("div","lh-sticky-header");stickyHeader.append(...this._renderScoreGauges(report,categoryRenderer,specificCategoryRenderers));reportContainer.appendChild(stickyHeader)}const categories=reportSection.appendChild(this._dom.createElement("div","lh-categories"));for(const category of Object.values(report.categories)){const renderer=specificCategoryRenderers[category.id]||categoryRenderer;const wrapper=renderer.dom.createChildOf(categories,"div","lh-category-wrapper");wrapper.appendChild(renderer.render(category,report.categoryGroups))}const reportFragment=this._dom.createFragment();const topbarDocumentFragment=this._renderReportTopbar(report);reportFragment.appendChild(topbarDocumentFragment);reportFragment.appendChild(reportContainer);reportContainer.appendChild(headerContainer);reportContainer.appendChild(reportSection);reportSection.appendChild(this._renderReportFooter(report));return reportFragment}}if(typeof module!=="undefined"&&module.exports){module.exports=ReportRenderer}else{self.ReportRenderer=ReportRenderer}"use strict";const NBSP2=" ";class I18n{constructor(locale,strings){if(locale==="en-XA")locale="de";this._numberDateLocale=locale;this._numberFormatter=new Intl.NumberFormat(locale);this._strings=strings||{}}get strings(){return this._strings}formatNumber(number,granularity=.1){const coarseValue=Math.round(number/granularity)*granularity;return this._numberFormatter.format(coarseValue)}formatBytesToKB(size,granularity=.1){const kbs=this._numberFormatter.format(Math.round(size/1024/granularity)*granularity);return`${kbs}${NBSP2}KB`}formatMilliseconds(ms,granularity=10){const coarseTime=Math.round(ms/granularity)*granularity;return`${this._numberFormatter.format(coarseTime)}${NBSP2}ms`}formatSeconds(ms,granularity=.1){const coarseTime=Math.round(ms/1e3/granularity)*granularity;return`${this._numberFormatter.format(coarseTime)}${NBSP2}s`}formatDateTime(date){const options={month:"short",day:"numeric",year:"numeric",hour:"numeric",minute:"numeric",timeZoneName:"short"};let formatter=new Intl.DateTimeFormat(this._numberDateLocale,options);const tz=formatter.resolvedOptions().timeZone;if(!tz||tz.toLowerCase()==="etc/unknown"){options.timeZone="UTC";formatter=new Intl.DateTimeFormat(this._numberDateLocale,options)}return formatter.format(new Date(date))}formatDuration(timeInMilliseconds){let timeInSeconds=timeInMilliseconds/1e3;if(Math.round(timeInSeconds)===0){return"None"}const parts=[];const unitLabels={d:60*60*24,h:60*60,m:60,s:1};Object.keys(unitLabels).forEach(label=>{const unit=unitLabels[label];const numberOfUnits=Math.floor(timeInSeconds/unit);if(numberOfUnits>0){timeInSeconds-=numberOfUnits*unit;parts.push(`${numberOfUnits} ${label}`)}});return parts.join(" ")}}if(typeof module!=="undefined"&&module.exports){module.exports=I18n}else{self.I18n=I18n}}
Insert cell
Object.keys(self).sort()
Insert cell
{
self.lhr = {
"fetchTime": "2020-03-06T21:58:44.504Z",
"requestedUrl": "https://example.com/",
"finalUrl": "https://example.com/",
"lighthouseVersion": "5.6.0",
"environment": {
"networkUserAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3694.0 Mobile Safari/537.36 Chrome-Lighthouse",
"hostUserAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/79.0.3945.120 Safari/537.36",
"benchmarkIndex": 790
},
"userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/79.0.3945.120 Safari/537.36",
"runWarnings": [],
"runtimeError": null,
"audits": {
"canonical": {
"id": "canonical",
"title": "Document has a valid `rel=canonical`",
"description": "Canonical links suggest which URL to show in search results. [Learn more](https://web.dev/canonical).",
"score": null,
"scoreDisplayMode": "notApplicable",
"displayValue": "",
"explanation": "",
"errorMessage": "",
"details": null,
"warnings": null,
"numericValue": null
},
"document-title": {
"id": "document-title",
"title": "Document has a `<title>` element",
"description": "The title gives screen reader users an overview of the page, and search engine users rely on it heavily to determine if a page is relevant to their search. [Learn more](https://web.dev/document-title/).",
"score": 1,
"scoreDisplayMode": "binary",
"displayValue": "",
"explanation": "",
"errorMessage": "",
"details": {
"headings": [],
"items": [],
"type": "table"
},
"warnings": null,
"numericValue": null
},
"font-size": {
"id": "font-size",
"title": "Document uses legible font sizes",
"description": "Font sizes less than 12px are too small to be legible and require mobile visitors to “pinch to zoom” in order to read. Strive to have >60% of page text ≥12px. [Learn more](https://web.dev/font-size).",
"score": 1,
"scoreDisplayMode": "binary",
"displayValue": "100% legible text",
"explanation": "",
"errorMessage": "",
"details": {
"headings": [
{
"itemType": "url",
"key": "source",
"text": "Source"
},
{
"itemType": "code",
"key": "selector",
"text": "Selector"
},
{
"itemType": "text",
"key": "coverage",
"text": "% of Page Text"
},
{
"itemType": "text",
"key": "fontSize",
"text": "Font Size"
}
],
"items": [
{
"coverage": "100.00%",
"fontSize": "≥ 12px",
"source": "Legible text"
}
],
"type": "table"
},
"warnings": null,
"numericValue": null
},
"hreflang": {
"id": "hreflang",
"title": "Document has a valid `hreflang`",
"description": "hreflang links tell search engines what version of a page they should list in search results for a given language or region. [Learn more](https://web.dev/hreflang).",
"score": 1,
"scoreDisplayMode": "binary",
"displayValue": "",
"explanation": "",
"errorMessage": "",
"details": {
"headings": [],
"items": [],
"type": "table"
},
"warnings": null,
"numericValue": null
},
"http-status-code": {
"id": "http-status-code",
"title": "Page has successful HTTP status code",
"description": "Pages with unsuccessful HTTP status codes may not be indexed properly. [Learn more](https://web.dev/http-status-code).",
"score": 1,
"scoreDisplayMode": "binary",
"displayValue": "",
"explanation": "",
"errorMessage": "",
"details": null,
"warnings": null,
"numericValue": null
},
"image-alt": {
"id": "image-alt",
"title": "Image elements have `[alt]` attributes",
"description": "Informative elements should aim for short, descriptive alternate text. Decorative elements can be ignored with an empty alt attribute. [Learn more](https://web.dev/image-alt/).",
"score": null,
"scoreDisplayMode": "notApplicable",
"displayValue": "",
"explanation": "",
"errorMessage": "",
"details": null,
"warnings": null,
"numericValue": null
},
"is-crawlable": {
"id": "is-crawlable",
"title": "Page isn’t blocked from indexing",
"description": "Search engines are unable to include your pages in search results if they don't have permission to crawl them. [Learn more](https://web.dev/is-crawable).",
"score": 1,
"scoreDisplayMode": "binary",
"displayValue": "",
"explanation": "",
"errorMessage": "",
"details": {
"headings": [],
"items": [],
"type": "table"
},
"warnings": null,
"numericValue": null
},
"link-text": {
"id": "link-text",
"title": "Links have descriptive text",
"description": "Descriptive link text helps search engines understand your content. [Learn more](https://web.dev/link-text).",
"score": 1,
"scoreDisplayMode": "binary",
"displayValue": "",
"explanation": "",
"errorMessage": "",
"details": {
"headings": [],
"items": [],
"summary": {},
"type": "table"
},
"warnings": null,
"numericValue": null
},
"meta-description": {
"id": "meta-description",
"title": "Document does not have a meta description",
"description": "Meta descriptions may be included in search results to concisely summarize page content. [Learn more](https://web.dev/meta-description).",
"score": 0,
"scoreDisplayMode": "binary",
"displayValue": "",
"explanation": "",
"errorMessage": "",
"details": null,
"warnings": null,
"numericValue": null
},
"plugins": {
"id": "plugins",
"title": "Document avoids plugins",
"description": "Search engines can't index plugin content, and many devices restrict plugins or don't support them. [Learn more](https://web.dev/plugins).",
"score": 1,
"scoreDisplayMode": "binary",
"displayValue": "",
"explanation": "",
"errorMessage": "",
"details": {
"headings": [],
"items": [],
"type": "table"
},
"warnings": null,
"numericValue": null
},
"robots-txt": {
"id": "robots-txt",
"title": "robots.txt is valid",
"description": "If your robots.txt file is malformed, crawlers may not be able to understand how you want your website to be crawled or indexed. [Learn more](https://web.dev/robots-txt).",
"score": null,
"scoreDisplayMode": "notApplicable",
"displayValue": "",
"explanation": "",
"errorMessage": "",
"details": null,
"warnings": null,
"numericValue": null
},
"structured-data": {
"id": "structured-data",
"title": "Structured data is valid",
"description": "Run the [Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool/) and the [Structured Data Linter](http://linter.structured-data.org/) to validate structured data. [Learn more](https://web.dev/structured-data).",
"score": null,
"scoreDisplayMode": "manual",
"displayValue": "",
"explanation": "",
"errorMessage": "",
"details": null,
"warnings": null,
"numericValue": null
},
"tap-targets": {
"id": "tap-targets",
"title": "Tap targets are sized appropriately",
"description": "Interactive elements like buttons and links should be large enough (48x48px), and have enough space around them, to be easy enough to tap without overlapping onto other elements. [Learn more](https://web.dev/tap-targets).",
"score": 1,
"scoreDisplayMode": "binary",
"displayValue": "100% appropriately sized tap targets",
"explanation": "",
"errorMessage": "",
"details": {
"headings": [],
"items": [],
"type": "table"
},
"warnings": null,
"numericValue": null
},
"viewport": {
"id": "viewport",
"title": "Has a `<meta name=\"viewport\">` tag with `width` or `initial-scale`",
"description": "Add a `<meta name=\"viewport\">` tag to optimize your app for mobile screens. [Learn more](https://web.dev/viewport).",
"score": 1,
"scoreDisplayMode": "binary",
"displayValue": "",
"explanation": "",
"errorMessage": "",
"details": null,
"warnings": [],
"numericValue": null
}
},
"categories": {
"seo": {
"id": "seo",
"title": "SEO",
"description": "These checks ensure that your page is optimized for search engine results ranking. There are additional factors Lighthouse does not check that may affect your search ranking. [Learn more](https://support.google.com/webmasters/answer/35769).",
"score": 0.9,
"manualDescription": "Run these additional validators on your site to check additional SEO best practices.",
"auditRefs": [
{
"id": "viewport",
"weight": 1,
"group": "seo-mobile"
},
{
"id": "document-title",
"weight": 1,
"group": "seo-content"
},
{
"id": "meta-description",
"weight": 1,
"group": "seo-content"
},
{
"id": "http-status-code",
"weight": 1,
"group": "seo-crawl"
},
{
"id": "link-text",
"weight": 1,
"group": "seo-content"
},
{
"id": "is-crawlable",
"weight": 1,
"group": "seo-crawl"
},
{
"id": "robots-txt",
"weight": 0,
"group": "seo-crawl"
},
{
"id": "image-alt",
"weight": 0,
"group": "seo-content"
},
{
"id": "hreflang",
"weight": 1,
"group": "seo-content"
},
{
"id": "canonical",
"weight": 0,
"group": "seo-content"
},
{
"id": "font-size",
"weight": 1,
"group": "seo-mobile"
},
{
"id": "plugins",
"weight": 1,
"group": "seo-content"
},
{
"id": "tap-targets",
"weight": 1,
"group": "seo-mobile"
},
{
"id": "structured-data",
"weight": 0,
"group": ""
}
]
}
},
"categoryGroups": {
"a11y-aria": {
"title": "ARIA",
"description": "These are opportunities to improve the usage of ARIA in your application which may enhance the experience for users of assistive technology, like a screen reader."
},
"a11y-audio-video": {
"title": "Audio and video",
"description": "These are opportunities to provide alternative content for audio and video. This may improve the experience for users with hearing or vision impairments."
},
"a11y-best-practices": {
"title": "Best practices",
"description": "These items highlight common accessibility best practices."
},
"a11y-color-contrast": {
"title": "Contrast",
"description": "These are opportunities to improve the legibility of your content."
},
"a11y-language": {
"title": "Internationalization and localization",
"description": "These are opportunities to improve the interpretation of your content by users in different locales."
},
"a11y-names-labels": {
"title": "Names and labels",
"description": "These are opportunities to improve the semantics of the controls in your application. This may enhance the experience for users of assistive technology, like a screen reader."
},
"a11y-navigation": {
"title": "Navigation",
"description": "These are opportunities to improve keyboard navigation in your application."
},
"a11y-tables-lists": {
"title": "Tables and lists",
"description": "These are opportunities to to improve the experience of reading tabular or list data using assistive technology, like a screen reader."
},
"budgets": {
"title": "Budgets",
"description": "Performance budgets set standards for the performance of your site."
},
"diagnostics": {
"title": "Diagnostics",
"description": "More information about the performance of your application. These numbers don't [directly affect](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) the Performance score."
},
"load-opportunities": {
"title": "Opportunities",
"description": "These suggestions can help your page load faster. They don't [directly affect](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) the Performance score."
},
"metrics": {
"title": "Metrics",
"description": ""
},
"pwa-fast-reliable": {
"title": "Fast and reliable",
"description": ""
},
"pwa-installable": {
"title": "Installable",
"description": ""
},
"pwa-optimized": {
"title": "PWA Optimized",
"description": ""
},
"seo-content": {
"title": "Content Best Practices",
"description": "Format your HTML in a way that enables crawlers to better understand your app’s content."
},
"seo-crawl": {
"title": "Crawling and Indexing",
"description": "To appear in search results, crawlers need access to your app."
},
"seo-mobile": {
"title": "Mobile Friendly",
"description": "Make sure your pages are mobile friendly so users don’t have to pinch or zoom in order to read the content pages. [Learn more](https://developers.google.com/search/mobile-sites/)."
}
},
"configSettings": {
"emulatedFormFactor": "mobile",
"locale": "en-US",
"onlyCategories": [
"seo"
],
"channel": "lr"
},
"i18n": {
"rendererFormattedStrings": {
"varianceDisclaimer": "Values are estimated and may vary. The performance score is [based only on these metrics](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted).",
"opportunityResourceColumnLabel": "Opportunity",
"opportunitySavingsColumnLabel": "Estimated Savings",
"errorMissingAuditInfo": "Report error: no audit information",
"errorLabel": "Error!",
"warningHeader": "Warnings: ",
"auditGroupExpandTooltip": "Show audits",
"passedAuditsGroupTitle": "Passed audits",
"notApplicableAuditsGroupTitle": "Not applicable",
"manualAuditsGroupTitle": "Additional items to manually check",
"toplevelWarningsMessage": "There were issues affecting this run of Lighthouse:",
"scorescaleLabel": "",
"crcLongestDurationLabel": "Maximum critical path latency:",
"crcInitialNavigation": "Initial Navigation",
"lsPerformanceCategoryDescription": "[Lighthouse](https://developers.google.com/web/tools/lighthouse/) analysis of the current page on an emulated mobile network. Values are estimated and may vary.",
"labDataTitle": "Lab Data",
"warningAuditsGroupTitle": "Passed audits but with warnings",
"snippetExpandButtonLabel": "Expand snippet",
"snippetCollapseButtonLabel": "Collapse snippet",
"thirdPartyResourcesLabel": "Show 3rd-party resources"
}
},
"timing": {
"total": 1945.94,
"entries": [
{
"name": "lh:init:config",
"entryType": "measure",
"startTime": 413.7,
"duration": 170.6,
"gather": false
},
{
"name": "lh:config:requireGatherers",
"entryType": "measure",
"startTime": 417.5,
"duration": 10.18,
"gather": false
},
{
"name": "lh:config:requireAudits",
"entryType": "measure",
"startTime": 428.97,
"duration": 148.32,
"gather": false
},
{
"name": "lh:init:connect",
"entryType": "measure",
"startTime": 585.48,
"duration": 2.41,
"gather": false
},
{
"name": "lh:gather:loadBlank",
"entryType": "measure",
"startTime": 588,
"duration": 16.87,
"gather": false
},
{
"name": "lh:gather:getVersion",
"entryType": "measure",
"startTime": 605.11,
"duration": 2.79,
"gather": false
},
{
"name": "lh:gather:getBenchmarkIndex",
"entryType": "measure",
"startTime": 608.1,
"duration": 502.3,
"gather": false
},
{
"name": "lh:gather:setupDriver",
"entryType": "measure",
"startTime": 1110.65,
"duration": 14.03,
"gather": false
},
{
"name": "lh:gather:loadBlank",
"entryType": "measure",
"startTime": 1124.95,
"duration": 12.76,
"gather": false
},
{
"name": "lh:gather:setupPassNetwork",
"entryType": "measure",
"startTime": 1137.85,
"duration": 3.23,
"gather": false
},
{
"name": "lh:gather:beforePass",
"entryType": "measure",
"startTime": 1141.35,
"duration": 0.49,
"gather": false
},
{
"name": "lh:gather:beforePass:AnchorElements",
"entryType": "measure",
"startTime": 1141.39,
"duration": 0.07,
"gather": false
},
{
"name": "lh:gather:beforePass:LinkElements",
"entryType": "measure",
"startTime": 1141.51,
"duration": 0.03,
"gather": false
},
{
"name": "lh:gather:beforePass:MetaElements",
"entryType": "measure",
"startTime": 1141.55,
"duration": 0.02,
"gather": false
},
{
"name": "lh:gather:beforePass:FontSize",
"entryType": "measure",
"startTime": 1141.59,
"duration": 0.01,
"gather": false
},
{
"name": "lh:gather:beforePass:EmbeddedContent",
"entryType": "measure",
"startTime": 1141.64,
"duration": 0.04,
"gather": false
},
{
"name": "lh:gather:beforePass:RobotsTxt",
"entryType": "measure",
"startTime": 1141.71,
"duration": 0.01,
"gather": false
},
{
"name": "lh:gather:beforePass:TapTargets",
"entryType": "measure",
"startTime": 1141.77,
"duration": 0.01,
"gather": false
},
{
"name": "lh:gather:beforePass:Accessibility",
"entryType": "measure",
"startTime": 1141.81,
"duration": 0.01,
"gather": false
},
{
"name": "lh:gather:beginRecording",
"entryType": "measure",
"startTime": 1141.93,
"duration": 0.06,
"gather": false
},
{
"name": "lh:gather:loadPage-defaultPass",
"entryType": "measure",
"startTime": 1142.17,
"duration": 1125.83,
"gather": false
},
{
"name": "lh:gather:pass",
"entryType": "measure",
"startTime": 2268.27,
"duration": 0.22,
"gather": false
},
{
"name": "lh:gather:getDevtoolsLog",
"entryType": "measure",
"startTime": 2268.6,
"duration": 0.41,
"gather": false
},
{
"name": "lh:gather:afterPass",
"entryType": "measure",
"startTime": 2270.69,
"duration": 214.32,
"gather": false
},
{
"name": "lh:gather:afterPass:AnchorElements",
"entryType": "measure",
"startTime": 2279.07,
"duration": 8.09,
"gather": false
},
{
"name": "lh:gather:afterPass:LinkElements",
"entryType": "measure",
"startTime": 2287.28,
"duration": 4.77,
"gather": false
},
{
"name": "lh:gather:afterPass:MetaElements",
"entryType": "measure",
"startTime": 2292.11,
"duration": 3.93,
"gather": false
},
{
"name": "lh:gather:afterPass:FontSize",
"entryType": "measure",
"startTime": 2296.1,
"duration": 33.98,
"gather": false
},
{
"name": "lh:gather:afterPass:EmbeddedContent",
"entryType": "measure",
"startTime": 2330.24,
"duration": 4.87,
"gather": false
},
{
"name": "lh:gather:afterPass:RobotsTxt",
"entryType": "measure",
"startTime": 2335.19,
"duration": 26.36,
"gather": false
},
{
"name": "lh:gather:afterPass:TapTargets",
"entryType": "measure",
"startTime": 2361.61,
"duration": 7.14,
"gather": false
},
{
"name": "lh:gather:afterPass:Accessibility",
"entryType": "measure",
"startTime": 2368.81,
"duration": 116.17,
"gather": false
},
{
"name": "lh:gather:disconnect",
"entryType": "measure",
"startTime": 2508.55,
"duration": 0.3,
"gather": false
},
{
"name": "lh:runner:run",
"entryType": "measure",
"startTime": 584.64,
"duration": 1945.94,
"gather": false
},
{
"name": "lh:runner:auditing",
"entryType": "measure",
"startTime": 2509.21,
"duration": 20.67,
"gather": false
},
{
"name": "lh:audit:viewport",
"entryType": "measure",
"startTime": 2513.44,
"duration": 1.81,
"gather": false
},
{
"name": "lh:computed:ViewportMeta",
"entryType": "measure",
"startTime": 2513.84,
"duration": 0.89,
"gather": false
},
{
"name": "lh:audit:document-title",
"entryType": "measure",
"startTime": 2515.85,
"duration": 1.62,
"gather": false
},
{
"name": "lh:audit:image-alt",
"entryType": "measure",
"startTime": 2517.97,
"duration": 0.79,
"gather": false
},
{
"name": "lh:audit:meta-description",
"entryType": "measure",
"startTime": 2519.18,
"duration": 0.44,
"gather": false
},
{
"name": "lh:audit:http-status-code",
"entryType": "measure",
"startTime": 2520.02,
"duration": 0.91,
"gather": false
},
{
"name": "lh:computed:MainResource",
"entryType": "measure",
"startTime": 2520.24,
"duration": 0.39,
"gather": false
},
{
"name": "lh:computed:NetworkRecords",
"entryType": "measure",
"startTime": 2520.32,
"duration": 0.25,
"gather": false
},
{
"name": "lh:audit:font-size",
"entryType": "measure",
"startTime": 2521.29,
"duration": 0.74,
"gather": false
},
{
"name": "lh:audit:link-text",
"entryType": "measure",
"startTime": 2522.37,
"duration": 0.59,
"gather": false
},
{
"name": "lh:audit:is-crawlable",
"entryType": "measure",
"startTime": 2523.39,
"duration": 0.74,
"gather": false
},
{
"name": "lh:audit:robots-txt",
"entryType": "measure",
"startTime": 2524.45,
"duration": 0.45,
"gather": false
},
{
"name": "lh:audit:tap-targets",
"entryType": "measure",
"startTime": 2525.26,
"duration": 1.31,
"gather": false
},
{
"name": "lh:audit:hreflang",
"entryType": "measure",
"startTime": 2526.99,
"duration": 0.5,
"gather": false
},
{
"name": "lh:audit:plugins",
"entryType": "measure",
"startTime": 2527.8,
"duration": 0.47,
"gather": false
},
{
"name": "lh:audit:canonical",
"entryType": "measure",
"startTime": 2528.61,
"duration": 0.66,
"gather": false
},
{
"name": "lh:audit:structured-data",
"entryType": "measure",
"startTime": 2529.57,
"duration": 0.29,
"gather": false
},
{
"name": "lh:runner:generate",
"entryType": "measure",
"startTime": 2529.91,
"duration": 0.64,
"gather": false
}
]
},
"stackPacks": []
}
}
Insert cell
html`<!--
@license
Copyright 2018 Google Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS-IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<!-- Lighthouse run warnings -->
<template id="tmpl-lh-warnings--toplevel">
<div class="lh-warnings lh-warnings--toplevel">
<strong class="lh-warnings__msg"></strong>
<ul></ul>
</div>
</template>

<!-- Lighthouse score scale -->
<template id="tmpl-lh-scorescale">
<div class="lh-scorescale">
<span class="lh-scorescale-range lh-scorescale-range--fail">0&ndash;49</span>
<span class="lh-scorescale-range lh-scorescale-range--average">50&ndash;89</span>
<span class="lh-scorescale-range lh-scorescale-range--pass">90&ndash;100</span>
</div>
</template>

<!-- Toggle arrow chevron -->
<template id="tmpl-lh-chevron">
<svg class="lh-chevron" title="See audits" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 100">
<g class="lh-chevron__lines">
<path class="lh-chevron__line lh-chevron__line-left" d="M10 50h40"></path>
<path class="lh-chevron__line lh-chevron__line-right" d="M90 50H50"></path>
</g>
</svg>
</template>

<!-- Lighthouse category header -->
<template id="tmpl-lh-category-header">
<div class="lh-category-header">
<div class="lh-score__gauge" role="heading" aria-level="2"></div>
<div class="lh-category-header__description"></div>
</div>
</template>

<!-- Lighthouse clump -->
<template id="tmpl-lh-clump">
<!-- TODO: group classes shouldn't be reused for clumps. -->
<details class="lh-clump lh-audit-group">
<summary>
<div class="lh-audit-group__summary">
<div class="lh-audit-group__header">
<span class="lh-audit-group__title"></span>
<span class="lh-audit-group__itemcount"></span>
<!-- .lh-audit-group__description will be added here -->
<!-- .lh-metrics-toggle will be added here -->
</div>
<div class=""></div>
</div>
</summary>
</details>
</template>

<!-- Lighthouse metrics toggle -->
<template id="tmpl-lh-metrics-toggle">
<div class="lh-metrics-toggle">
<input class="lh-metrics-toggle__input" type="checkbox" id="toggle-metric-descriptions" aria-label="Toggle the display of metric descriptions">
<label class="lh-metrics-toggle__label" for="toggle-metric-descriptions">
<div class="lh-metrics-toggle__icon lh-metrics-toggle__icon--less" aria-hidden="true">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
<path class="lh-metrics-toggle__lines" d="M4 9h16v2H4zm0 4h10v2H4z" />
</svg>
</div>
<div class="lh-metrics-toggle__icon lh-metrics-toggle__icon--more" aria-hidden="true">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path class="lh-metrics-toggle__lines" d="M3 18h12v-2H3v2zM3 6v2h18V6H3zm0 7h18v-2H3v2z" />
</svg>
</div>
</label>
</div>
</template>

<!-- Lighthouse audit -->
<template id="tmpl-lh-audit">
<div class="lh-audit">
<details class="lh-expandable-details">
<summary>
<div class="lh-audit__header lh-expandable-details__summary">
<span class="lh-audit__score-icon"></span>
<span class="lh-audit__title-and-text">
<span class="lh-audit__title"></span>
<span class="lh-audit__display-text"></span>
</span>
<div class="lh-chevron-container"></div>
</div>
</summary>
<div class="lh-audit__description"></div>
<div class="lh-audit__stackpacks"></div>
</details>
</div>
</template>

<!-- Lighthouse perf metric -->
<template id="tmpl-lh-metric">
<div class="lh-metric">
<div class="lh-metric__innerwrap">
<span class="lh-metric__title"></span>
<div class="lh-metric__value"></div>
<div class="lh-metric__description"></div>
</div>
</div>
</template>

<!-- Lighthouse perf opportunity -->
<template id="tmpl-lh-opportunity">
<div class="lh-audit lh-audit--load-opportunity">
<details class="lh-expandable-details">
<summary>
<div class="lh-audit__header lh-expandable-details__summary">
<div class="lh-load-opportunity__cols">
<div class="lh-load-opportunity__col lh-load-opportunity__col--one">
<span class="lh-audit__score-icon"></span>
<div class="lh-audit__title"></div>
</div>
<div class="lh-load-opportunity__col lh-load-opportunity__col--two">
<div class="lh-load-opportunity__sparkline">
<div class="lh-sparkline"><div class="lh-sparkline__bar"></div></div>
</div>
<div class="lh-audit__display-text"></div>
<div class="lh-chevron-container" title="See resources"></div>
</div>
</div>
</div>
</summary>
<div class="lh-audit__description"></div>
<div class="lh-audit__stackpacks"></div>
</details>
</div>
</template>

<!-- Lighthouse perf opportunity header -->
<template id="tmpl-lh-opportunity-header">
<div class="lh-load-opportunity__header lh-load-opportunity__cols">
<div class="lh-load-opportunity__col lh-load-opportunity__col--one"></div>
<div class="lh-load-opportunity__col lh-load-opportunity__col--two"></div>
</div>
</template>

<!-- Lighthouse score container -->
<template id="tmpl-lh-scores-wrapper">
<style>
.lh-scores-container {
display: flex;
flex-direction: column;
padding: var(--scores-container-padding);
position: relative;
width: 100%;
}

.lh-sticky-header {
--gauge-circle-size: 36px;
--plugin-badge-size: 18px;
--plugin-icon-size: 75%;
--gauge-wrapper-width: 60px;
--gauge-percentage-font-size: 13px;
position: fixed;
left: 0;
right: 0;
top: var(--topbar-height);
font-weight: 700;
display: none;
justify-content: center;
background-color: var(--sticky-header-background-color);
border-bottom: 1px solid var(--color-gray-200);
padding-top: var(--score-container-padding);
padding-bottom: 4px;
z-index: 1;
pointer-events: none;
}

.lh-devtools .lh-sticky-header {
position: sticky;
}

.lh-sticky-header--visible {
display: grid;
grid-auto-flow: column;
pointer-events: auto;
}

/* Disable the gauge arc animation for the sticky header, so toggling display: none
does not play the animation. */
.lh-sticky-header .lh-gauge-arc {
animation: none;
}

.lh-sticky-header .lh-gauge__label {
display: none;
}

.lh-highlighter {
width: var(--gauge-wrapper-width);
height: 1px;
background-color: var(--highlighter-background-color);
/* Position at bottom of first gauge in sticky header. */
position: absolute;
grid-column: 1;
bottom: -1px;
}

.lh-gauge__wrapper:first-of-type {
contain: none;
}
</style>
<div class="lh-scores-wrapper">
<div class="lh-scores-container">
<div class="pyro">
<div class="before"></div>
<div class="after"></div>
</div>
</div>
</div>
</template>

<!-- Lighthouse topbar -->
<template id="tmpl-lh-topbar">
<style>
.lh-topbar {
position: sticky;
top: 0;
left: 0;
right: 0;
z-index: 1000;
display: flex;
align-items: center;
height: var(--topbar-height);
background-color: var(--topbar-background-color);
padding: var(--topbar-padding);
}

.lh-topbar__logo {
width: var(--topbar-logo-size);
height: var(--topbar-logo-size);
user-select: none;
flex: none;
}
.lh-topbar__logo .shape {
fill: var(--report-text-color);
}

.lh-topbar__url {
margin: var(--topbar-padding);
text-decoration: none;
color: var(--report-text-color);
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}

.lh-tools {
margin-left: auto;
will-change: transform;
}
.lh-tools__button {
width: var(--tools-icon-size);
height: var(--tools-icon-size);
cursor: pointer;
margin-right: 5px;
/* This is actually a button element, but we want to style it like a transparent div. */
display: flex;
background: none;
color: inherit;
border: none;
padding: 0;
font: inherit;
outline: inherit;
}
.lh-tools__button svg {
fill: var(--tools-icon-color);
}
.dark .lh-tools__button svg {
filter: invert(1);
}
.lh-tools__button.active + .lh-tools__dropdown {
opacity: 1;
clip: rect(-1px, 187px, 242px, -3px);
visibility: visible;
}
.lh-tools__dropdown {
position: absolute;
background-color: var(--report-background-color);
border: 1px solid var(--report-border-color);
border-radius: 3px;
padding: calc(var(--default-padding) / 2) 0;
cursor: pointer;
top: 36px;
right: 0;
box-shadow: 1px 1px 3px #ccc;
min-width: 125px;
clip: rect(0, 164px, 0, 0);
visibility: hidden;
opacity: 0;
transition: all 200ms cubic-bezier(0,0,0.2,1);
}
.lh-tools__dropdown a {
display: block;
color: currentColor;
text-decoration: none;
white-space: nowrap;
padding: 0 12px;
line-height: 2;
}
.lh-tools__dropdown a:hover,
.lh-tools__dropdown a:focus {
background-color: var(--color-gray-200);
outline: none;
}
.lh-tools__dropdown .report-icon {
cursor: pointer;
background-repeat: no-repeat;
background-position: 8px 50%;
background-size: 18px;
background-color: transparent;
text-indent: 18px;
}
.dark .report-icon {
color: var(--color-gray-900);
filter: invert(1);
}
.dark .lh-tools__dropdown a:hover,
.dark .lh-tools__dropdown a:focus {
background-color: #BDBDBD;
}
/* copy icon needs slight adjustments to look great */
.lh-tools__dropdown .report-icon--copy {
background-size: 16px;
background-position: 9px 50%;
}
/* save-as-gist option hidden in report */
.lh-tools__dropdown .lh-tools--gist {
display: none;
}

@media screen and (max-width: 964px) {
.lh-tools__dropdown {
right: 0;
left: initial;
}
}
@media print {
.lh-topbar {
position: static;
margin-left: 0;
}

.lh-tools__dropdown {
display: none;
}
}
</style>

<div class="lh-topbar">
<!-- Lighthouse logo. -->
<svg class="lh-topbar__logo" viewBox="0 0 24 24">
<defs>
<linearGradient x1="57.456%" y1="13.086%" x2="18.259%" y2="72.322%" id="lh-topbar__logo--a">
<stop stop-color="#262626" stop-opacity=".1" offset="0%"/>
<stop stop-color="#262626" stop-opacity="0" offset="100%"/>
</linearGradient>
<linearGradient x1="100%" y1="50%" x2="0%" y2="50%" id="lh-topbar__logo--b">
<stop stop-color="#262626" stop-opacity=".1" offset="0%"/>
<stop stop-color="#262626" stop-opacity="0" offset="100%"/>
</linearGradient>
<linearGradient x1="58.764%" y1="65.756%" x2="36.939%" y2="50.14%" id="lh-topbar__logo--c">
<stop stop-color="#262626" stop-opacity=".1" offset="0%"/>
<stop stop-color="#262626" stop-opacity="0" offset="100%"/>
</linearGradient>
<linearGradient x1="41.635%" y1="20.358%" x2="72.863%" y2="85.424%" id="lh-topbar__logo--d">
<stop stop-color="#FFF" stop-opacity=".1" offset="0%"/>
<stop stop-color="#FFF" stop-opacity="0" offset="100%"/>
</linearGradient>
</defs>
<g fill="none" fill-rule="evenodd">
<path d="M12 3l4.125 2.625v3.75H18v2.25h-1.688l1.5 9.375H6.188l1.5-9.375H6v-2.25h1.875V5.648L12 3zm2.201 9.938L9.54 14.633 9 18.028l5.625-2.062-.424-3.028zM12.005 5.67l-1.88 1.207v2.498h3.75V6.86l-1.87-1.19z" fill="#F44B21"/>
<path fill="#FFF" d="M14.201 12.938L9.54 14.633 9 18.028l5.625-2.062z"/>
<path d="M6 18c-2.042 0-3.95-.01-5.813 0l1.5-9.375h4.326L6 18z" fill="url(#lh-topbar__logo--a)" fill-rule="nonzero" transform="translate(6 3)"/>
<path fill="#FFF176" fill-rule="nonzero" d="M13.875 9.375v-2.56l-1.87-1.19-1.88 1.207v2.543z"/>
<path fill="url(#lh-topbar__logo--b)" fill-rule="nonzero" d="M0 6.375h6v2.25H0z" transform="translate(6 3)"/>
<path fill="url(#lh-topbar__logo--c)" fill-rule="nonzero" d="M6 6.375H1.875v-3.75L6 0z" transform="translate(6 3)"/>
<path fill="url(#lh-topbar__logo--d)" fill-rule="nonzero" d="M6 0l4.125 2.625v3.75H12v2.25h-1.688l1.5 9.375H.188l1.5-9.375H0v-2.25h1.875V2.648z" transform="translate(6 3)"/>
</g>
</svg>

<a href="" class="lh-topbar__url" target="_blank" rel="noopener"></a>

<div class="lh-tools">
<button id="lh-tools-button" class="report-icon report-icon--share lh-tools__button" title="Tools menu" aria-label="Toggle report tools menu" aria-haspopup="menu" aria-expanded="false" aria-controls="lh-tools-dropdown">
<svg width="100%" height="100%" viewBox="0 0 24 24">
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>
</svg>
</button>
<div id="lh-tools-dropdown" role="menu" class="lh-tools__dropdown" aria-labelledby="lh-tools-button">
<!-- TODO(i18n): localize tools dropdown -->
<a role="menuitem" tabindex="-1" href="#" class="report-icon report-icon--print" data-i18n="dropdownPrintSummary" data-action="print-summary"></a>
<a role="menuitem" tabindex="-1" href="#" class="report-icon report-icon--print" data-i18n="dropdownPrintExpanded" data-action="print-expanded"></a>
<a role="menuitem" tabindex="-1" href="#" class="report-icon report-icon--copy" data-i18n="dropdownCopyJSON" data-action="copy"></a>
<a role="menuitem" tabindex="-1" href="#" class="report-icon report-icon--download" data-i18n="dropdownSaveHTML" data-action="save-html"></a>
<a role="menuitem" tabindex="-1" href="#" class="report-icon report-icon--download" data-i18n="dropdownSaveJSON" data-action="save-json"></a>
<a role="menuitem" tabindex="-1" href="#" class="report-icon report-icon--open lh-tools--viewer" data-i18n="dropdownViewer" data-action="open-viewer"></a>
<a role="menuitem" tabindex="-1" href="#" class="report-icon report-icon--open lh-tools--gist" data-i18n="dropdownSaveGist" data-action="save-gist"></a>
<a role="menuitem" tabindex="-1" href="#" class="report-icon report-icon--dark" data-i18n="dropdownDarkTheme" data-action="toggle-dark"></a>
</div>
</div>
</div>
</template>

<!-- Lighthouse header -->
<template id="tmpl-lh-heading">
<style>
/* CSS Fireworks. Originally by Eddie Lin
https://codepen.io/paulirish/pen/yEVMbP
*/
.pyro {
display: none;
z-index: 1;
pointer-events: none;
}
.score100 .pyro {
display: block;
}
.score100 .lh-lighthouse stop:first-child {
stop-color: hsla(200, 12%, 95%, 0);
}
.score100 .lh-lighthouse stop:last-child {
stop-color: hsla(65, 81%, 76%, 1);
}

.pyro > .before, .pyro > .after {
position: absolute;
width: 5px;
height: 5px;
border-radius: 2.5px;
box-shadow: 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff, 0 0 #fff;
animation: 1s bang ease-out infinite backwards, 1s gravity ease-in infinite backwards, 5s position linear infinite backwards;
animation-delay: 1s, 1s, 1s;
}

.pyro > .after {
animation-delay: 2.25s, 2.25s, 2.25s;
animation-duration: 1.25s, 1.25s, 6.25s;
}
.fireworks-paused .pyro > div {
animation-play-state: paused;
}

@keyframes bang {
to {
box-shadow: -70px -115.67px #47ebbc, -28px -99.67px #eb47a4, 58px -31.67px #7eeb47, 13px -141.67px #eb47c5, -19px 6.33px #7347eb, -2px -74.67px #ebd247, 24px -151.67px #eb47e0, 57px -138.67px #b4eb47, -51px -104.67px #479eeb, 62px 8.33px #ebcf47, -93px 0.33px #d547eb, -16px -118.67px #47bfeb, 53px -84.67px #47eb83, 66px -57.67px #eb47bf, -93px -65.67px #91eb47, 30px -13.67px #86eb47, -2px -59.67px #83eb47, -44px 1.33px #eb47eb, 61px -58.67px #47eb73, 5px -22.67px #47e8eb, -66px -28.67px #ebe247, 42px -123.67px #eb5547, -75px 26.33px #7beb47, 15px -52.67px #a147eb, 36px -51.67px #eb8347, -38px -12.67px #eb5547, -46px -59.67px #47eb81, 78px -114.67px #eb47ba, 15px -156.67px #eb47bf, -36px 1.33px #eb4783, -72px -86.67px #eba147, 31px -46.67px #ebe247, -68px 29.33px #47e2eb, -55px 19.33px #ebe047, -56px 27.33px #4776eb, -13px -91.67px #eb5547, -47px -138.67px #47ebc7, -18px -96.67px #eb47ac, 11px -88.67px #4783eb, -67px -28.67px #47baeb, 53px 10.33px #ba47eb, 11px 19.33px #5247eb, -5px -11.67px #eb4791, -68px -4.67px #47eba7, 95px -37.67px #eb478b, -67px -162.67px #eb5d47, -54px -120.67px #eb6847, 49px -12.67px #ebe047, 88px 8.33px #47ebda, 97px 33.33px #eb8147, 6px -71.67px #ebbc47;
}
}
@keyframes gravity {
to {
transform: translateY(80px);
opacity: 0;
}
}
@keyframes position {
0%, 19.9% {
margin-top: 4%;
margin-left: 47%;
}
20%, 39.9% {
margin-top: 7%;
margin-left: 30%;
}
40%, 59.9% {
margin-top: 6%;
margin-left: 70%;
}
60%, 79.9% {
margin-top: 3%;
margin-left: 20%;
}
80%, 99.9% {
margin-top: 3%;
margin-left: 80%;
}
}
</style>

<div class="lh-header-container">
<div class="lh-scores-wrapper-placeholder"></div>
</div>
</template>


<!-- Lighthouse footer -->
<template id="tmpl-lh-footer">
<style>
.lh-footer {
padding: var(--footer-padding-vertical) calc(var(--default-padding) * 2);
max-width: var(--report-width);
margin: 0 auto;
}
.lh-footer .lh-generated {
text-align: center;
}
.lh-env__title {
font-size: var(--env-item-font-size-big);
line-height: var(--env-item-line-height-big);
text-align: center;
padding: var(--score-container-padding);
}
.lh-env {
padding: var(--default-padding) 0;
}
.lh-env__items {
padding-left: 16px;
margin: 0 0 var(--audits-margin-bottom);
padding: 0;
}
.lh-env__items .lh-env__item:nth-child(2n) {
background-color: var(--env-item-background-color);
}
.lh-env__item {
display: flex;
padding: var(--env-item-padding);
position: relative;
}
span.lh-env__name {
font-weight: bold;
min-width: var(--env-name-min-width);
flex: 0.5;
padding: 0 8px;
}
span.lh-env__description {
text-align: left;
flex: 1;
}
</style>
<footer class="lh-footer">
<!-- TODO(i18n): localize runtime settings -->
<div class="lh-env">
<div class="lh-env__title">Runtime Settings</div>
<ul class="lh-env__items">
<template id="tmpl-lh-env__items">
<li class="lh-env__item">
<span class="lh-env__name"></span>
<span class="lh-env__description"></span>
</li>
</template>
</ul>
</div>

<div class="lh-generated">
<!-- TODO(i18n): use ICU replacement to replace version w/o concatenation. -->
Generated by <b>Lighthouse</b> <span class="lh-footer__version"></span> |
<a href="https://github.com/GoogleChrome/Lighthouse/issues" target="_blank" rel="noopener" class="lh-footer__version_issue">File an issue</a>
</div>
</footer>
</template>

<!-- Lighthouse score gauge -->
<template id="tmpl-lh-gauge">
<a href="#" class="lh-gauge__wrapper">
<!-- Wrapper exists for the ::before plugin icon. Cannot create pseudo-elements on svgs. -->
<div class="lh-gauge__svg-wrapper">
<svg viewBox="0 0 120 120" class="lh-gauge">
<circle class="lh-gauge-base" r="56" cx="60" cy="60" stroke-width="8"></circle>
<circle class="lh-gauge-arc" r="56" cx="60" cy="60" stroke-width="8"></circle>
</svg>
</div>
<div class="lh-gauge__percentage"></div>
<!-- TODO: should likely be an h2 -->
<div class="lh-gauge__label"></div>
</a>
</template>


<!-- Lighthouse PWA badge gauge -->
<template id="tmpl-lh-gauge--pwa">
<style>
.lh-gauge--pwa .lh-gauge--pwa__component {
display: none;
}
.lh-gauge--pwa__wrapper:not(.lh-badged--all) .lh-gauge--pwa__logo > path {
/* Gray logo unless everything is passing. */
fill: #B0B0B0;
}

.lh-gauge--pwa__disc {
fill: var(--color-gray-200);
}

.lh-gauge--pwa__logo--primary-color {
fill: #304FFE;
}

.lh-gauge--pwa__logo--secondary-color {
fill: #3D3D3D;
}
.dark .lh-gauge--pwa__logo--secondary-color {
fill: #D8B6B6;
}

/* No passing groups. */
.lh-gauge--pwa__wrapper:not([class*='lh-badged--']) .lh-gauge--pwa__na-line {
display: inline;
}
/* Just optimized. Same n/a line as no passing groups. */
.lh-gauge--pwa__wrapper.lh-badged--pwa-optimized:not(.lh-badged--pwa-installable):not(.lh-badged--pwa-fast-reliable) .lh-gauge--pwa__na-line {
display: inline;
}

/* Just fast and reliable. */
.lh-gauge--pwa__wrapper.lh-badged--pwa-fast-reliable:not(.lh-badged--pwa-installable) .lh-gauge--pwa__fast-reliable-badge {
display: inline;
}

/* Just installable. */
.lh-gauge--pwa__wrapper.lh-badged--pwa-installable:not(.lh-badged--pwa-fast-reliable) .lh-gauge--pwa__installable-badge {
display: inline;
}

/* Fast and reliable and installable. */
.lh-gauge--pwa__wrapper.lh-badged--pwa-fast-reliable.lh-badged--pwa-installable .lh-gauge--pwa__fast-reliable-installable-badges {
display: inline;
}

/* All passing groups. */
.lh-gauge--pwa__wrapper.lh-badged--all .lh-gauge--pwa__check-circle {
display: inline;
}
</style>

<a href="#" class="lh-gauge__wrapper lh-gauge--pwa__wrapper">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60" class="lh-gauge lh-gauge--pwa">
<defs>
<linearGradient id="lh-gauge--pwa__check-circle__gradient" x1="50%" y1="0%" x2="50%" y2="100%">
<stop stop-color="#00C852" offset="0%"></stop>
<stop stop-color="#009688" offset="100%"></stop>
</linearGradient>
<linearGradient id="lh-gauge--pwa__installable__shadow-gradient" x1="76.056%" x2="24.111%" y1="82.995%" y2="24.735%">
<stop stop-color="#A5D6A7" offset="0%"></stop>
<stop stop-color="#80CBC4" offset="100%"></stop>
</linearGradient>
<linearGradient id="lh-gauge--pwa__fast-reliable__shadow-gradient" x1="76.056%" y1="82.995%" x2="25.678%" y2="26.493%">
<stop stop-color="#64B5F6" offset="0%"></stop>
<stop stop-color="#2979FF" offset="100%"></stop>
</linearGradient>

<g id="lh-gauge--pwa__fast-reliable-badge">
<circle fill="#FFFFFF" cx="10" cy="10" r="10"></circle>
<path fill="#304FFE" d="M10 3.58l5.25 2.34v3.5c0 3.23-2.24 6.26-5.25 7-3.01-.74-5.25-3.77-5.25-7v-3.5L10 3.58zm-.47 10.74l2.76-4.83.03-.07c.04-.08 0-.24-.22-.24h-1.64l.47-3.26h-.47l-2.7 4.77c-.02.01.05-.1-.04.05-.09.16-.1.31.18.31h1.63l-.47 3.27h.47z"/>
</g>
<g id="lh-gauge--pwa__installable-badge">
<circle fill="#FFFFFF" cx="10" cy="10" r="10"></circle>
<path fill="#009688" d="M10 4.167A5.835 5.835 0 0 0 4.167 10 5.835 5.835 0 0 0 10 15.833 5.835 5.835 0 0 0 15.833 10 5.835 5.835 0 0 0 10 4.167zm2.917 6.416h-2.334v2.334H9.417v-2.334H7.083V9.417h2.334V7.083h1.166v2.334h2.334v1.166z"/>
</g>
</defs>

<g stroke="none" fill-rule="nonzero">
<!-- Background and PWA logo (color by default) -->
<circle class="lh-gauge--pwa__disc" cx="30" cy="30" r="30"></circle>
<g class="lh-gauge--pwa__logo">
<path class="lh-gauge--pwa__logo--secondary-color" d="M35.66 19.39l.7-1.75h2L37.4 15 38.6 12l3.4 9h-2.51l-.58-1.61z"/>
<path class="lh-gauge--pwa__logo--primary-color" d="M33.52 21l3.65-9h-2.42l-2.5 5.82L30.5 12h-1.86l-1.9 5.82-1.35-2.65-1.21 3.72L25.4 21h2.38l1.72-5.2 1.64 5.2z"/>
<path class="lh-gauge--pwa__logo--secondary-color" fill-rule="nonzero" d="M20.3 17.91h1.48c.45 0 .85-.05 1.2-.15l.39-1.18 1.07-3.3a2.64 2.64 0 0 0-.28-.37c-.55-.6-1.36-.91-2.42-.91H18v9h2.3V17.9zm1.96-3.84c.22.22.33.5.33.87 0 .36-.1.65-.29.87-.2.23-.59.35-1.15.35h-.86v-2.41h.87c.52 0 .89.1 1.1.32z"/>
</g>

<!-- No badges. -->
<rect class="lh-gauge--pwa__component lh-gauge--pwa__na-line" fill="#FFFFFF" x="20" y="32" width="20" height="4" rx="2"></rect>

<!-- Just fast and reliable. -->
<g class="lh-gauge--pwa__component lh-gauge--pwa__fast-reliable-badge" transform="translate(20, 29)">
<path fill="url(#lh-gauge--pwa__fast-reliable__shadow-gradient)" d="M33.63 19.49A30 30 0 0 1 16.2 30.36L3 17.14 17.14 3l16.49 16.49z"/>
<use href="#lh-gauge--pwa__fast-reliable-badge" />
</g>

<!-- Just installable. -->
<g class="lh-gauge--pwa__component lh-gauge--pwa__installable-badge" transform="translate(20, 29)">
<path fill="url(#lh-gauge--pwa__installable__shadow-gradient)" d="M33.629 19.487c-4.272 5.453-10.391 9.39-17.415 10.869L3 17.142 17.142 3 33.63 19.487z"/>
<use href="#lh-gauge--pwa__installable-badge" />
</g>

<!-- Fast and reliable and installable. -->
<g class="lh-gauge--pwa__component lh-gauge--pwa__fast-reliable-installable-badges">
<g transform="translate(8, 29)"> <!-- fast and reliable -->
<path fill="url(#lh-gauge--pwa__fast-reliable__shadow-gradient)" d="M16.321 30.463L3 17.143 17.142 3l22.365 22.365A29.864 29.864 0 0 1 22 31c-1.942 0-3.84-.184-5.679-.537z"/>
<use href="#lh-gauge--pwa__fast-reliable-badge" />
</g>
<g transform="translate(32, 29)"> <!-- installable -->
<path fill="url(#lh-gauge--pwa__installable__shadow-gradient)" d="M25.982 11.84a30.107 30.107 0 0 1-13.08 15.203L3 17.143 17.142 3l8.84 8.84z"/>
<use href="#lh-gauge--pwa__installable-badge" />
</g>
</g>

<!-- Full PWA. -->
<g class="lh-gauge--pwa__component lh-gauge--pwa__check-circle" transform="translate(18, 28)">
<circle fill="#FFFFFF" cx="12" cy="12" r="12"></circle>
<path fill="url(#lh-gauge--pwa__check-circle__gradient)" d="M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"></path>
</g>
</g>
</svg>

<div class="lh-gauge__label"></div>
</a>
</template>

<!-- Lighthouse crtiical request chains component -->
<template id="tmpl-lh-crc">
<div class="lh-crc-container">
<style>
.lh-crc .tree-marker {
width: 12px;
height: 26px;
display: block;
float: left;
background-position: top left;
}
.lh-crc .horiz-down {
background: url('data:image/svg+xml;utf8,<svg width="16" height="26" viewBox="0 0 16 26" xmlns="http://www.w3.org/2000/svg"><g fill="%23D8D8D8" fill-rule="evenodd"><path d="M16 12v2H-2v-2z"/><path d="M9 12v14H7V12z"/></g></svg>');
}
.lh-crc .right {
background: url('data:image/svg+xml;utf8,<svg width="16" height="26" viewBox="0 0 16 26" xmlns="http://www.w3.org/2000/svg"><path d="M16 12v2H0v-2z" fill="%23D8D8D8" fill-rule="evenodd"/></svg>');
}
.lh-crc .up-right {
background: url('data:image/svg+xml;utf8,<svg width="16" height="26" viewBox="0 0 16 26" xmlns="http://www.w3.org/2000/svg"><path d="M7 0h2v14H7zm2 12h7v2H9z" fill="%23D8D8D8" fill-rule="evenodd"/></svg>');
}
.lh-crc .vert-right {
background: url('data:image/svg+xml;utf8,<svg width="16" height="26" viewBox="0 0 16 26" xmlns="http://www.w3.org/2000/svg"><path d="M7 0h2v27H7zm2 12h7v2H9z" fill="%23D8D8D8" fill-rule="evenodd"/></svg>');
}
.lh-crc .vert {
background: url('data:image/svg+xml;utf8,<svg width="16" height="26" viewBox="0 0 16 26" xmlns="http://www.w3.org/2000/svg"><path d="M7 0h2v26H7z" fill="%23D8D8D8" fill-rule="evenodd"/></svg>');
}
.lh-crc .crc-tree {
font-size: 14px;
width: 100%;
overflow-x: auto;
}
.lh-crc .crc-node {
height: 26px;
line-height: 26px;
white-space: nowrap;
}
.lh-crc .crc-node__tree-value {
margin-left: 10px;
}
.lh-crc .crc-node__tree-value div {
display: inline;
}
.lh-crc .crc-node__chain-duration {
font-weight: 700;
}
.lh-crc .crc-initial-nav {
color: #595959;
font-style: italic;
}
.lh-crc__summary-value {
margin-bottom: 10px;
}
</style>
<div>
<div class="lh-crc__summary-value">
<span class="lh-crc__longest_duration_label"></span> <b class="lh-crc__longest_duration"></b>
</div>
</div>
<div class="lh-crc">
<div class="crc-initial-nav"></div>
<!-- stamp for each chain -->
<template id="tmpl-lh-crc__chains">
<div class="crc-node">
<span class="crc-node__tree-marker">

</span>
<span class="crc-node__tree-value">

</span>
</div>
</template>
</div>
</div>
</template>

<template id="tmpl-lh-3p-filter">
<style>
.lh-3p-filter {
background-color: var(--table-higlight-background-color);
color: var(--color-gray-600);
float: right;
padding: 6px;
}
.lh-3p-filter-label, .lh-3p-filter-input {
vertical-align: middle;
user-select: none;
}
.lh-3p-filter-input:disabled + .lh-3p-ui-string {
text-decoration: line-through;
}
</style>
<div class="lh-3p-filter">
<label class="lh-3p-filter-label">
<input type="checkbox" class="lh-3p-filter-input" checked />
<span class="lh-3p-ui-string">Show 3rd party resources</span> (<span class="lh-3p-filter-count"></span>)
</label>
</div>
</template>

<!-- Lighthouse snippet component -->
<template id="tmpl-lh-snippet">
<div class="lh-snippet">
<style>
:root {
--snippet-highlight-light: #fbf1f2;
--snippet-highlight-dark: #ffd6d8;
}

.lh-snippet__header {
position: relative;
overflow: hidden;
padding: 10px;
border-bottom: none;
color: var(--snippet-color);
background-color: var(--snippet-background-color);
border: 1px solid var(--report-border-color-secondary);
}
.lh-snippet__title {
font-weight: bold;
float: left;
}
.lh-snippet__node {
float: left;
margin-left: 4px;
}
.lh-snippet__toggle-expand {
padding: 1px 7px;
margin-top: -1px;
margin-right: -7px;
float: right;
background: transparent;
border: none;
cursor: pointer;
font-size: 14px;
color: #0c50c7;
}

.lh-snippet__snippet {
overflow: auto;
border: 1px solid var(--report-border-color-secondary);
}
/* Container needed so that all children grow to the width of the scroll container */
.lh-snippet__snippet-inner {
display: inline-block;
min-width: 100%;
}

.lh-snippet:not(.lh-snippet--expanded) .lh-snippet__show-if-expanded {
display: none;
}
.lh-snippet.lh-snippet--expanded .lh-snippet__show-if-collapsed {
display: none;
}

.lh-snippet__line {
background: white;
white-space: pre;
display: flex;
}
.lh-snippet__line:not(.lh-snippet__line--message):first-child {
padding-top: 4px;
}
.lh-snippet__line:not(.lh-snippet__line--message):last-child {
padding-bottom: 4px;
}
.lh-snippet__line--content-highlighted {
background: var(--snippet-highlight-dark);
}
.lh-snippet__line--message {
background: var(--snippet-highlight-light);
}
.lh-snippet__line--message .lh-snippet__line-number {
padding-top: 10px;
padding-bottom: 10px;
}
.lh-snippet__line--message code {
padding: 10px;
padding-left: 5px;
color: var(--color-fail);
font-family: var(--report-font-family);
}
.lh-snippet__line--message code {
white-space: normal;
}
.lh-snippet__line-icon {
padding-top: 10px;
display: none;
}
.lh-snippet__line--message .lh-snippet__line-icon {
display: block;
}
.lh-snippet__line-icon:before {
content: "";
display: inline-block;
vertical-align: middle;
margin-right: 4px;
width: var(--score-icon-size);
height: var(--score-icon-size);
background-image: var(--fail-icon-url);
}
.lh-snippet__line-number {
flex-shrink: 0;
width: 40px;
text-align: right;
font-family: monospace;
padding-right: 5px;
margin-right: 5px;
color: var(--color-gray-600);
user-select: none;
}
</style>
<template id="tmpl-lh-snippet__header">
<div class="lh-snippet__header">
<div class="lh-snippet__title"></div>
<div class="lh-snippet__node"></div>
<button class="lh-snippet__toggle-expand">
<span class="lh-snippet__btn-label-collapse lh-snippet__show-if-expanded"></span>
<span class="lh-snippet__btn-label-expand lh-snippet__show-if-collapsed"></span>
</button>
</div>
</template>
<template id="tmpl-lh-snippet__content">
<div class="lh-snippet__snippet">
<div class="lh-snippet__snippet-inner"></div>
</div>
</template>
<template id="tmpl-lh-snippet__line">
<div class="lh-snippet__line">
<div class="lh-snippet__line-number"></div>
<div class="lh-snippet__line-icon"></div>
<code></code>
</div>
</template>
</div>
</template>
`
Insert cell
html`<style>

/**
* @license
* Copyright 2017 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/*
Naming convention:

If a variable is used for a specific component: --{component}-{property name}-{modifier}

Both {component} and {property name} should be kebab-case. If the target is the entire page,
use 'report' for the component. The property name should not be abbreviated. Use the
property name the variable is intended for - if it's used for multiple, a common descriptor
is fine (ex: 'size' for a variable applied to 'width' and 'height'). If a variable is shared
across multiple components, either create more variables or just drop the "{component}-"
part of the name. Append any modifiers at the end (ex: 'big', 'dark').

For colors: --color-{hue}-{intensity}

{intensity} is the Material Design tag - 700, A700, etc.
*/
.lh-vars {
/* Palette using Material Design Colors
* https://www.materialui.co/colors */
--color-amber-50: #FFF8E1;
--color-blue-200: #90CAF9;
--color-blue-900: #0D47A1;
--color-blue-A700: #2962FF;
--color-cyan-500: #00BCD4;
--color-gray-100: #F5F5F5;
--color-gray-200: #E0E0E0;
--color-gray-400: #BDBDBD;
--color-gray-50: #FAFAFA;
--color-gray-500: #9E9E9E;
--color-gray-600: #757575;
--color-gray-700: #616161;
--color-gray-800: #424242;
--color-gray-900: #212121;
--color-gray: #000000;
--color-green-700: #018642;
--color-green: #0CCE6B;
--color-orange-700: #D04900;
--color-orange: #FFA400;
--color-red-700: #EB0F00;
--color-red: #FF4E42;
--color-teal-600: #00897B;
--color-white: #FFFFFF;

/* Context-specific colors */
--color-average-secondary: var(--color-orange-700);
--color-average: var(--color-orange);
--color-fail-secondary: var(--color-red-700);
--color-fail: var(--color-red);
--color-informative: var(--color-blue-900);
--color-pass-secondary: var(--color-green-700);
--color-pass: var(--color-green);
--color-hover: var(--color-gray-50);

/* Component variables */
--audit-description-padding-left: calc(var(--score-icon-size) + var(--score-icon-margin-left) + var(--score-icon-margin-right));
--audit-explanation-line-height: 16px;
--audit-group-margin-bottom: 40px;
--audit-group-padding-vertical: 8px;
--audit-margin-horizontal: 5px;
--audit-padding-vertical: 8px;
--category-header-font-size: 20px;
--category-padding: 40px;
--chevron-line-stroke: var(--color-gray-600);
--chevron-size: 12px;
--default-padding: 12px;
--env-item-background-color: var(--color-gray-100);
--env-item-font-size: 28px;
--env-item-line-height: 36px;
--env-item-padding: 10px 0px;
--env-name-min-width: 220px;
--footer-padding-vertical: 16px;
--gauge-circle-size-big: 112px;
--gauge-circle-size: 80px;
--gauge-label-font-size-big: 28px;
--gauge-label-font-size: 20px;
--gauge-label-line-height-big: 36px;
--gauge-label-line-height: 26px;
--gauge-percentage-font-size-big: 38px;
--gauge-percentage-font-size: 28px;
--gauge-wrapper-width: 148px;
--header-line-height: 24px;
--highlighter-background-color: var(--report-text-color);
--icon-square-size: calc(var(--score-icon-size) * 0.88);
--image-preview-size: 48px;
--metric-toggle-lines-fill: #7F7F7F;
--metrics-toggle-background-color: var(--color-gray-200);
--plugin-badge-background-color: var(--color-white);
--plugin-badge-size-big: calc(var(--gauge-circle-size-big) / 2.7);
--plugin-badge-size: calc(var(--gauge-circle-size) / 2.7);
--plugin-icon-size: 65%;
--pwa-icon-margin: 0 6px 0 -2px;
--pwa-icon-size: var(--topbar-logo-size);
--report-background-color: #fff;
--report-border-color-secondary: #ebebeb;
--report-font-family-monospace: 'Roboto Mono', 'Menlo', 'dejavu sans mono', 'Consolas', 'Lucida Console', monospace;
--report-font-family: Roboto, Helvetica, Arial, sans-serif;
--report-font-size: 16px;
--report-line-height: 24px;
--report-min-width: 400px;
--report-text-color-secondary: var(--color-gray-800);
--report-text-color: var(--color-gray-900);
--report-width: calc(60 * var(--report-font-size));
--score-container-padding: 8px;
--score-icon-background-size: 24px;
--score-icon-margin-left: 4px;
--score-icon-margin-right: 12px;
--score-icon-margin: 0 var(--score-icon-margin-right) 0 var(--score-icon-margin-left);
--score-icon-size: 12px;
--scores-container-padding: 20px 0 20px 0;
--scorescale-height: 6px;
--scorescale-width: 18px;
--section-padding-vertical: 12px;
--snippet-background-color: var(--color-gray-50);
--snippet-color: var(--color-gray-800);
--sparkline-height: 5px;
--stackpack-padding-horizontal: 10px;
--sticky-header-background-color: var(--report-background-color);
--table-higlight-background-color: hsla(0, 0%, 75%, 0.1);
--tools-icon-color: var(--color-gray-600);
--tools-icon-size: var(--score-icon-background-size);
--topbar-background-color: var(--color-gray-100);
--topbar-height: 32px;
--topbar-logo-size: 24px;
--topbar-padding: 0 8px;
--toplevel-warning-padding: 22px;

/* SVGs */
--plugin-icon-url-dark: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23FFFFFF"><path d="M0 0h24v24H0z" fill="none"/><path d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"/></svg>');
--plugin-icon-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="%23757575"><path d="M0 0h24v24H0z" fill="none"/><path d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"/></svg>');

--pass-icon-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><title>check</title><path fill="%23178239" d="M24 4C12.95 4 4 12.95 4 24c0 11.04 8.95 20 20 20 11.04 0 20-8.96 20-20 0-11.05-8.96-20-20-20zm-4 30L10 24l2.83-2.83L20 28.34l15.17-15.17L38 16 20 34z"/></svg>');
--average-icon-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><title>info</title><path fill="%23E67700" d="M24 4C12.95 4 4 12.95 4 24s8.95 20 20 20 20-8.95 20-20S35.05 4 24 4zm2 30h-4V22h4v12zm0-16h-4v-4h4v4z"/></svg>');
--fail-icon-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><title>warn</title><path fill="%23C7221F" d="M2 42h44L24 4 2 42zm24-6h-4v-4h4v4zm0-8h-4v-8h4v8z"/></svg>');

--pwa-fast-reliable-gray-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="nonzero"><circle fill="%23DAE0E3" cx="12" cy="12" r="12"/><path d="M12.3 4l6.3 2.8V11c0 3.88-2.69 7.52-6.3 8.4C8.69 18.52 6 14.89 6 11V6.8L12.3 4zm-.56 12.88l3.3-5.79.04-.08c.05-.1.01-.29-.26-.29h-1.96l.56-3.92h-.56L9.6 12.52c0 .03.07-.12-.03.07-.11.2-.12.37.2.37h1.97l-.56 3.92h.56z" fill="%23FFF"/></g></svg>');
--pwa-installable-gray-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="nonzero"><circle fill="%23DAE0E3" cx="12" cy="12" r="12"/><path d="M12 5a7 7 0 1 0 0 14 7 7 0 0 0 0-14zm3.5 7.7h-2.8v2.8h-1.4v-2.8H8.5v-1.4h2.8V8.5h1.4v2.8h2.8v1.4z" fill="%23FFF"/></g></svg>');
--pwa-optimized-gray-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><rect fill="%23DAE0E3" width="24" height="24" rx="12"/><path fill="%23FFF" d="M12 15.07l3.6 2.18-.95-4.1 3.18-2.76-4.2-.36L12 6.17l-1.64 3.86-4.2.36 3.2 2.76-.96 4.1z"/><path d="M5 5h14v14H5z"/></g></svg>');

--pwa-fast-reliable-gray-url-dark: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="nonzero"><circle fill="%23424242" cx="12" cy="12" r="12"/><path d="M12.3 4l6.3 2.8V11c0 3.88-2.69 7.52-6.3 8.4C8.69 18.52 6 14.89 6 11V6.8L12.3 4zm-.56 12.88l3.3-5.79.04-.08c.05-.1.01-.29-.26-.29h-1.96l.56-3.92h-.56L9.6 12.52c0 .03.07-.12-.03.07-.11.2-.12.37.2.37h1.97l-.56 3.92h.56z" fill="%23FFF"/></g></svg>');
--pwa-installable-gray-url-dark: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="nonzero"><circle fill="%23424242" cx="12" cy="12" r="12"/><path d="M12 5a7 7 0 1 0 0 14 7 7 0 0 0 0-14zm3.5 7.7h-2.8v2.8h-1.4v-2.8H8.5v-1.4h2.8V8.5h1.4v2.8h2.8v1.4z" fill="%23FFF"/></g></svg>');
--pwa-optimized-gray-url-dark: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><rect fill="%23424242" width="24" height="24" rx="12"/><path fill="%23FFF" d="M12 15.07l3.6 2.18-.95-4.1 3.18-2.76-4.2-.36L12 6.17l-1.64 3.86-4.2.36 3.2 2.76-.96 4.1z"/><path d="M5 5h14v14H5z"/></g></svg>');

--pwa-fast-reliable-color-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero" fill="none"><circle fill="%230CCE6B" cx="12" cy="12" r="12"/><path d="M12 4.3l6.3 2.8v4.2c0 3.88-2.69 7.52-6.3 8.4-3.61-.88-6.3-4.51-6.3-8.4V7.1L12 4.3zm-.56 12.88l3.3-5.79.04-.08c.05-.1.01-.29-.26-.29h-1.96l.56-3.92h-.56L9.3 12.82c0 .03.07-.12-.03.07-.11.2-.12.37.2.37h1.97l-.56 3.92h.56z" fill="%23FFF"/></g></svg>');
--pwa-installable-color-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero" fill="none"><circle fill="%230CCE6B" cx="12" cy="12" r="12"/><path d="M12 5a7 7 0 1 0 0 14 7 7 0 0 0 0-14zm3.5 7.7h-2.8v2.8h-1.4v-2.8H8.5v-1.4h2.8V8.5h1.4v2.8h2.8v1.4z" fill="%23FFF"/></g></svg>');
--pwa-optimized-color-url: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><rect fill="%230CCE6B" width="24" height="24" rx="12"/><path d="M5 5h14v14H5z"/><path fill="%23FFF" d="M12 15.07l3.6 2.18-.95-4.1 3.18-2.76-4.2-.36L12 6.17l-1.64 3.86-4.2.36 3.2 2.76-.96 4.1z"/></g></svg>');
}

@media not print {
.lh-vars.dark {
/* Pallete */
--color-gray-200: var(--color-gray-800);
--color-gray-400: var(--color-gray-600);
--color-gray-700: var(--color-gray-400);
--color-gray-50: #757575;
--color-gray-600: var(--color-gray-500);
--color-green-700: var(--color-green);
--color-orange-700: var(--color-orange);
--color-red-700: var(--color-red);
--color-teal-600: var(--color-cyan-500);

/* Context-specific colors */
--color-hover: rgba(0, 0, 0, 0.2);
--color-informative: var(--color-blue-200);

/* Component variables */
--env-item-background-color: var(--color-gray);
--plugin-badge-background-color: var(--color-gray-800);
--report-background-color: var(--color-gray-900);
--report-border-color-secondary: var(--color-gray-200);
--report-text-color-secondary: var(--color-gray-400);
--report-text-color: var(--color-gray-100);
--topbar-background-color: var(--color-gray);

/* SVGs */
--plugin-icon-url: var(--plugin-icon-url-dark);
--pwa-fast-reliable-gray-url: var(--pwa-fast-reliable-gray-url-dark);
--pwa-installable-gray-url: var(--pwa-installable-gray-url-dark);
--pwa-optimized-gray-url: var(--pwa-optimized-gray-url-dark);
}
}

@media only screen and (max-width: 480px) {
.lh-vars {
--audit-group-margin-bottom: 20px;
--category-padding: 24px;
--env-name-min-width: 120px;
--gauge-circle-size-big: 96px;
--gauge-circle-size: 72px;
--gauge-label-font-size-big: 22px;
--gauge-label-font-size: 14px;
--gauge-label-line-height-big: 26px;
--gauge-label-line-height: 20px;
--gauge-percentage-font-size-big: 34px;
--gauge-percentage-font-size: 26px;
--gauge-wrapper-width: 112px;
--header-padding: 16px 0 16px 0;
--image-preview-size: 24px;
--plugin-icon-size: 75%;
--pwa-icon-margin: 0 7px 0 -3px;
--report-font-size: 14px;
--report-line-height: 20px;
--score-icon-margin-left: 2px;
--score-icon-size: 10px;
--topbar-height: 28px;
--topbar-logo-size: 20px;
}

/* Not enough space to adequately show the relative savings bars. */
.lh-sparkline {
display: none;
}
}

.lh-vars.lh-devtools {
--audit-explanation-line-height: 14px;
--audit-group-margin-bottom: 20px;
--audit-group-padding-vertical: 12px;
--audit-padding-vertical: 4px;
--category-header-font-size: 16px;
--category-padding: 12px;
--default-padding: 12px;
--env-name-min-width: 120px;
--footer-padding-vertical: 8px;
--gauge-circle-size-big: 72px;
--gauge-circle-size: 64px;
--gauge-label-font-size-big: 22px;
--gauge-label-font-size: 14px;
--gauge-label-line-height-big: 26px;
--gauge-label-line-height: 20px;
--gauge-percentage-font-size-big: 34px;
--gauge-percentage-font-size: 26px;
--gauge-wrapper-width: 97px;
--header-line-height: 20px;
--header-padding: 16px 0 16px 0;
--plugin-icon-size: 75%;
--pwa-icon-margin: 0 7px 0 -3px;
--report-font-family-monospace: 'Menlo', 'dejavu sans mono', 'Consolas', 'Lucida Console', monospace;
--report-font-family: '.SFNSDisplay-Regular', 'Helvetica Neue', 'Lucida Grande', sans-serif;
--report-font-size: 12px;
--report-line-height: 20px;
--score-icon-margin-left: 2px;
--score-icon-size: 10px;
--section-padding-vertical: 8px;
}

.lh-devtools.lh-root {
height: 100%;
}
.lh-devtools.lh-root img {
/* Override devtools default 'min-width: 0' so svg without size in a flexbox isn't collapsed. */
min-width: auto;
}
.lh-devtools .lh-container {
overflow-y: scroll;
height: calc(100% - var(--topbar-height));
}
@media print {
.lh-devtools .lh-container {
overflow: unset;
}
}
.lh-devtools .lh-sticky-header {
top: 0;
}

@keyframes fadeIn {
0% { opacity: 0;}
100% { opacity: 0.6;}
}

.lh-root *, .lh-root *::before, .lh-root *::after {
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
}

.lh-root {
font-family: var(--report-font-family);
font-size: var(--report-font-size);
margin: 0;
line-height: var(--report-line-height);
background: var(--report-background-color);
scroll-behavior: smooth;
color: var(--report-text-color);
}

.lh-root :focus {
outline: -webkit-focus-ring-color auto 3px;
}
.lh-root summary:focus {
outline: none;
box-shadow: 0 0 0 1px hsl(217, 89%, 61%);
}

.lh-root [hidden] {
display: none !important;
}

.lh-root pre {
margin: 0;
}

.lh-root details > summary {
cursor: pointer;
}

.lh-container {
word-break: break-word;
}

.lh-audit-group a,
.lh-category-header__description a,
.lh-audit__description a,
.lh-footer a,
.lh-table-column--link a {
color: var(--color-informative);
}

.lh-audit__description, .lh-audit__stackpack {
--inner-audit-padding-right: var(--stackpack-padding-horizontal);
padding-left: var(--audit-description-padding-left);
padding-right: var(--inner-audit-padding-right);
padding-top: 8px;
padding-bottom: 8px;
}

.lh-details {
font-size: var(--report-font-size);
margin-top: var(--default-padding);
margin-bottom: var(--default-padding);
margin-left: var(--audit-description-padding-left);
/* whatever the .lh-details side margins are */
width: 100%;
}

.lh-details.flex .lh-code {
max-width: 70%;
}

.lh-audit__stackpack {
display: flex;
align-items: center;
}

.lh-audit__stackpack__img {
max-width: 50px;
margin-right: var(--default-padding)
}

/* Report header */

.report-icon {
opacity: 0.7;
}
.report-icon:hover {
opacity: 1;
}
.report-icon[disabled] {
opacity: 0.3;
pointer-events: none;
}

.report-icon--print {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"/><path fill="none" d="M0 0h24v24H0z"/></svg>');
}
.report-icon--copy {
background-image: url('data:image/svg+xml;utf8,<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>');
}
.report-icon--open {
background-image: url('data:image/svg+xml;utf8,<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h4v-2H5V8h14v10h-4v2h4c1.1 0 2-.9 2-2V6c0-1.1-.89-2-2-2zm-7 6l-4 4h3v6h2v-6h3l-4-4z"/></svg>');
}
.report-icon--download {
background-image: url('data:image/svg+xml;utf8,<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/><path d="M0 0h24v24H0z" fill="none"/></svg>');
}
.report-icon--dark {
background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 100 125"><path d="M50 23.587c-16.27 0-22.799 12.574-22.799 21.417 0 12.917 10.117 22.451 12.436 32.471h20.726c2.32-10.02 12.436-19.554 12.436-32.471 0-8.843-6.528-21.417-22.799-21.417zM39.637 87.161c0 3.001 1.18 4.181 4.181 4.181h.426l.41 1.231C45.278 94.449 46.042 95 48.019 95h3.963c1.978 0 2.74-.551 3.365-2.427l.409-1.231h.427c3.002 0 4.18-1.18 4.18-4.181V80.91H39.637v6.251zM50 18.265c1.26 0 2.072-.814 2.072-2.073v-9.12C52.072 5.813 51.26 5 50 5c-1.259 0-2.072.813-2.072 2.073v9.12c0 1.259.813 2.072 2.072 2.072zM68.313 23.727c.994.774 2.135.634 2.91-.357l5.614-7.187c.776-.992.636-2.135-.356-2.909-.992-.776-2.135-.636-2.91.357l-5.613 7.186c-.778.993-.636 2.135.355 2.91zM91.157 36.373c-.306-1.222-1.291-1.815-2.513-1.51l-8.85 2.207c-1.222.305-1.814 1.29-1.51 2.512.305 1.223 1.291 1.814 2.513 1.51l8.849-2.206c1.223-.305 1.816-1.291 1.511-2.513zM86.757 60.48l-8.331-3.709c-1.15-.512-2.225-.099-2.736 1.052-.512 1.151-.1 2.224 1.051 2.737l8.33 3.707c1.15.514 2.225.101 2.736-1.05.513-1.149.1-2.223-1.05-2.737zM28.779 23.37c.775.992 1.917 1.131 2.909.357.992-.776 1.132-1.917.357-2.91l-5.615-7.186c-.775-.992-1.917-1.132-2.909-.357s-1.131 1.917-.356 2.909l5.614 7.187zM21.715 39.583c.305-1.223-.288-2.208-1.51-2.513l-8.849-2.207c-1.222-.303-2.208.289-2.513 1.511-.303 1.222.288 2.207 1.511 2.512l8.848 2.206c1.222.304 2.208-.287 2.513-1.509zM21.575 56.771l-8.331 3.711c-1.151.511-1.563 1.586-1.05 2.735.511 1.151 1.586 1.563 2.736 1.052l8.331-3.711c1.151-.511 1.563-1.586 1.05-2.735-.512-1.15-1.585-1.562-2.736-1.052z"/></svg>');
}

/* Node */
.lh-node__snippet {
font-family: var(--report-font-family-monospace);
color: var(--color-teal-600);
font-size: 12px;
line-height: 1.5em;
}

/* Score */

.lh-audit__score-icon {
width: var(--score-icon-size);
height: var(--score-icon-size);
margin: var(--score-icon-margin);
}

.lh-audit--pass .lh-audit__display-text {
color: var(--color-pass-secondary);
}
.lh-audit--pass .lh-audit__score-icon {
border-radius: 100%;
background: var(--color-pass);
}

.lh-audit--average .lh-audit__display-text {
color: var(--color-average-secondary);
}
.lh-audit--average .lh-audit__score-icon {
background: var(--color-average);
width: var(--icon-square-size);
height: var(--icon-square-size);
}

.lh-audit--fail .lh-audit__display-text {
color: var(--color-fail-secondary);
}
.lh-audit--fail .lh-audit__score-icon,
.lh-audit--error .lh-audit__score-icon {
border-left: calc(var(--score-icon-size) / 2) solid transparent;
border-right: calc(var(--score-icon-size) / 2) solid transparent;
border-bottom: var(--score-icon-size) solid var(--color-fail);
}

.lh-audit--manual .lh-audit__display-text,
.lh-audit--notapplicable .lh-audit__display-text {
color: var(--color-gray-600);
}
.lh-audit--manual .lh-audit__score-icon,
.lh-audit--notapplicable .lh-audit__score-icon {
border-radius: 100%;
background: var(--color-gray-400);
}

.lh-audit--informative .lh-audit__display-text {
color: var(--color-gray-600);
}

.lh-audit--informative .lh-audit__score-icon {
border: none;
border-radius: 100%;
background: var(--color-gray-400);
}

.lh-audit__description,
.lh-audit__stackpack {
color: var(--report-text-color-secondary);
}
.lh-category-header__description {
font-size: var(--report-font-size);
text-align: center;
margin: 0px auto;
max-width: 400px;
}


.lh-audit__display-text,
.lh-load-opportunity__sparkline,
.lh-chevron-container {
margin: 0 var(--audit-margin-horizontal);
}
.lh-chevron-container {
margin-right: 0;
}

.lh-audit__title-and-text {
flex: 1;
}

/* Prepend display text with em dash separator. But not in Opportunities. */
.lh-audit__display-text:not(:empty):before {
content: '—';
margin-right: var(--audit-margin-horizontal);
}
.lh-audit-group.lh-audit-group--load-opportunities .lh-audit__display-text:not(:empty):before {
display: none;
}

/* Expandable Details (Audit Groups, Audits) */
.lh-audit__header {
display: flex;
align-items: center;
font-weight: 500;
padding: var(--audit-padding-vertical) 0;
}

.lh-audit--load-opportunity .lh-audit__header {
display: block;
}

.lh-audit__header:hover {
background-color: var(--color-hover);
}

/* Hide the expandable arrow icon, three ways: via the CSS Counter Styles spec, for webkit/blink browsers, hiding the polyfilled icon */
/* https://github.com/javan/details-element-polyfill/blob/master/src/details-element-polyfill/polyfill.sass */
.lh-audit-group > summary,
.lh-expandable-details > summary {
list-style-type: none;
}
.lh-audit-group > summary::-webkit-details-marker,
.lh-expandable-details > summary::-webkit-details-marker {
display: none;
}
.lh-audit-group > summary:before,
.lh-expandable-details > summary:before {
display: none;
}


/* Perf Metric */

.lh-columns {
display: flex;
width: 100%;
}
@media screen and (max-width: 640px) {
.lh-columns {
flex-wrap: wrap;

}
}

.lh-column {
flex: 1;
}
.lh-column:first-of-type {
margin-right: 24px;
}

@media screen and (max-width: 800px) {
.lh-column:first-of-type {
margin-right: 8px;
}
}
@media screen and (max-width: 640px) {
.lh-column {
flex-basis: 100%;
}
.lh-column:first-of-type {
margin-right: 0px;
}
.lh-column:first-of-type .lh-metric:last-of-type {
border-bottom: 0;
}
}


.lh-metric {
border-bottom: 1px solid var(--report-border-color-secondary);
}
.lh-metric:first-of-type {
border-top: 1px solid var(--report-border-color-secondary);
}

.lh-metric__innerwrap {
display: grid;
grid-template-columns: var(--audit-description-padding-left) 10fr 3fr;
align-items: center;
padding: 10px 0;
}

.lh-metric__details {
order: -1;
}

.lh-metric__title {
flex: 1;
font-weight: 500;
}

.lh-metrics__disclaimer {
color: var(--color-gray-600);
margin: var(--section-padding-vertical) 0;
}
.lh-metrics__disclaimer a {
color: var(--color-gray-700);
}

.lh-metric__description {
display: none;
grid-column-start: 2;
grid-column-end: 3;
color: var(--report-text-color-secondary);
}

.lh-metric__value {
white-space: nowrap; /* No wrapping between metric value and the icon */
font-weight: 500;
justify-self: end;
}

/* No-JS toggle switch */
.lh-metrics-toggle__input:checked ~ .lh-columns .lh-metric__description {
display: block;
}

.lh-metrics-toggle__input {
cursor: pointer;
opacity: 0;
position: absolute;
right: 0;
width: 74px;
height: 28px;
top: -3px;
}
.lh-metrics-toggle__label {
display: flex;
background-color: #eee;
border-radius: 20px;
overflow: hidden;
position: absolute;
right: 0;
top: -3px;
pointer-events: none;
}
.lh-metrics-toggle__input:focus + label {
outline: -webkit-focus-ring-color auto 3px;
}
.lh-metrics-toggle__icon {
display: flex;
align-items: center;
justify-content: center;
padding: 2px 5px;
width: 50%;
height: 28px;
}
.lh-metrics-toggle__input:not(:checked) + label .lh-metrics-toggle__icon--less,
.lh-metrics-toggle__input:checked + label .lh-metrics-toggle__icon--more {
background-color: var(--color-blue-A700);
--metric-toggle-lines-fill: var(--color-white);
}
.lh-metrics-toggle__lines {
fill: var(--metric-toggle-lines-fill);
}

.lh-metrics-toggle__label {
background-color: var(--metrics-toggle-background-color);
}

.lh-metrics-toggle__label .lh-metrics-toggle__icon--less {
padding-left: 8px;
}
.lh-metrics-toggle__label .lh-metrics-toggle__icon--more {
padding-right: 8px;
}

/* Pushes the metric description toggle button to the right. */
.lh-audit-group--metrics .lh-audit-group__header {
display: flex;
}
.lh-audit-group--metrics .lh-audit-group__header span.lh-audit-group__title {
flex: 1;
}

.lh-metric .lh-metric__innerwrap::before {
content: '';
width: var(--score-icon-size);
height: var(--score-icon-size);
display: inline-block;
margin: var(--score-icon-margin);
}

.lh-metric--pass .lh-metric__value {
color: var(--color-pass-secondary);
}
.lh-metric--pass .lh-metric__innerwrap::before {
border-radius: 100%;
background: var(--color-pass);
}

.lh-metric--average .lh-metric__value {
color: var(--color-average-secondary);
}
.lh-metric--average .lh-metric__innerwrap::before {
background: var(--color-average);
width: var(--icon-square-size);
height: var(--icon-square-size);
}

.lh-metric--fail .lh-metric__value {
color: var(--color-fail-secondary);
}
.lh-metric--fail .lh-metric__innerwrap::before,
.lh-metric--error .lh-metric__innerwrap::before {
border-left: calc(var(--score-icon-size) / 2) solid transparent;
border-right: calc(var(--score-icon-size) / 2) solid transparent;
border-bottom: var(--score-icon-size) solid var(--color-fail);
}

.lh-metric--error .lh-metric__value,
.lh-metric--error .lh-metric__description {
color: var(--color-fail-secondary);
}

/* Perf load opportunity */

.lh-load-opportunity__cols {
display: flex;
align-items: flex-start;
}

.lh-load-opportunity__header .lh-load-opportunity__col {
color: var(--color-gray-600);
display: unset;
line-height: calc(2.3 * var(--report-font-size));
}

.lh-load-opportunity__col {
display: flex;
}

.lh-load-opportunity__col--one {
flex: 5;
align-items: center;
margin-right: 2px;
}
.lh-load-opportunity__col--two {
flex: 4;
text-align: right;
}

.lh-audit--load-opportunity .lh-audit__display-text {
text-align: right;
flex: 0 0 calc(3 * var(--report-font-size));
}


/* Sparkline */

.lh-load-opportunity__sparkline {
flex: 1;
margin-top: calc((var(--report-line-height) - var(--sparkline-height)) / 2);
}

.lh-sparkline {
height: var(--sparkline-height);
width: 100%;
}

.lh-sparkline__bar {
height: 100%;
float: right;
}

.lh-audit--pass .lh-sparkline__bar {
background: var(--color-pass);
}

.lh-audit--average .lh-sparkline__bar {
background: var(--color-average);
}

.lh-audit--fail .lh-sparkline__bar {
background: var(--color-fail);
}



/* Filmstrip */

.lh-filmstrip-container {
/* smaller gap between metrics and filmstrip */
margin: -8px auto 0 auto;
}

.lh-filmstrip {
display: flex;
flex-direction: row;
justify-content: space-between;
padding-bottom: var(--default-padding);
}

.lh-filmstrip__frame {
text-align: right;
position: relative;
}

.lh-filmstrip__thumbnail {
border: 1px solid var(--report-border-color-secondary);
max-height: 100px;
max-width: 60px;
}

@media screen and (max-width: 750px) {
.lh-filmstrip {
flex-wrap: wrap;
}
.lh-filmstrip__frame {
width: 20%;
margin-bottom: 5px;
}
.lh-filmstrip__thumbnail {
display: block;
margin: auto;
}
}

/* Audit */

.lh-audit {
border-bottom: 1px solid var(--report-border-color-secondary);
}

/* Apply border-top to just the first audit. */
.lh-audit {
border-top: 1px solid var(--report-border-color-secondary);
}
.lh-audit ~ .lh-audit {
border-top: none;
}


.lh-audit--error .lh-audit__display-text {
color: var(--color-fail);
}

/* Audit Group */

.lh-audit-group {
margin-bottom: var(--audit-group-margin-bottom);
position: relative;
}

.lh-audit-group__header::before {
/* By default, groups don't get an icon */
content: none;
width: var(--pwa-icon-size);
height: var(--pwa-icon-size);
margin: var(--pwa-icon-margin);
display: inline-block;
vertical-align: middle;
}

/* Style the "over budget" columns red. */
.lh-audit-group--budgets #performance-budget tbody tr td:nth-child(4),
.lh-audit-group--budgets #performance-budget tbody tr td:nth-child(5),
.lh-audit-group--budgets #timing-budget tbody tr td:nth-child(3) {
color: var(--color-red-700);
}

/* Align the "over budget request count" text to be close to the "over budget bytes" column. */
.lh-audit-group--budgets .lh-table tbody tr td:nth-child(4){
text-align: right;
}

.lh-audit-group--budgets .lh-table {
width: 100%;
margin: 16px 0px 16px 0px;
}

.lh-audit-group--pwa-fast-reliable .lh-audit-group__header::before {
content: '';
background-image: var(--pwa-fast-reliable-gray-url);
}
.lh-audit-group--pwa-installable .lh-audit-group__header::before {
content: '';
background-image: var(--pwa-installable-gray-url);
}
.lh-audit-group--pwa-optimized .lh-audit-group__header::before {
content: '';
background-image: var(--pwa-optimized-gray-url);
}
.lh-audit-group--pwa-fast-reliable.lh-badged .lh-audit-group__header::before {
background-image: var(--pwa-fast-reliable-color-url);
}
.lh-audit-group--pwa-installable.lh-badged .lh-audit-group__header::before {
background-image: var(--pwa-installable-color-url);
}
.lh-audit-group--pwa-optimized.lh-badged .lh-audit-group__header::before {
background-image: var(--pwa-optimized-color-url);
}

.lh-audit-group--metrics .lh-audit-group__summary {
margin-top: 0;
margin-bottom: 0;
}

.lh-audit-group__summary {
display: flex;
justify-content: space-between;
margin-top: calc(var(--category-padding) * 1.5);
margin-bottom: var(--category-padding);
}

.lh-audit-group__itemcount {
color: var(--color-gray-600);
font-weight: bold;
}
.lh-audit-group__header .lh-chevron {
margin-top: calc((var(--report-line-height) - 5px) / 2);
}

.lh-audit-group__header {
font-size: var(--report-font-size);
margin: 0 0 var(--audit-group-padding-vertical);
/* When the header takes 100% width, the chevron becomes small. */
max-width: calc(100% - var(--chevron-size));
}
/* max-width makes the metric toggle not flush. metrics doesn't have a chevron so unset. */
.lh-audit-group--metrics .lh-audit-group__header {
max-width: unset;
}

.lh-audit-group__header span.lh-audit-group__title {
font-weight: bold;
}

.lh-audit-group__header span.lh-audit-group__itemcount {
font-weight: bold;
color: var(--color-gray-600);
}

.lh-audit-group__header span.lh-audit-group__description {
font-weight: 500;
color: var(--color-gray-600);
}
.lh-audit-group__header span.lh-audit-group__description::before {
content: '—';
margin: 0px var(--audit-margin-horizontal);
}

.lh-clump > .lh-audit-group__header,
.lh-audit-group--diagnostics .lh-audit-group__header,
.lh-audit-group--load-opportunities .lh-audit-group__header,
.lh-audit-group--metrics .lh-audit-group__header,
.lh-audit-group--pwa-fast-reliable .lh-audit-group__header,
.lh-audit-group--pwa-installable .lh-audit-group__header,
.lh-audit-group--pwa-optimized .lh-audit-group__header {
margin-top: var(--audit-group-padding-vertical);
}

.lh-audit-explanation {
margin: var(--audit-padding-vertical) 0 calc(var(--audit-padding-vertical) / 2) var(--audit-margin-horizontal);
line-height: var(--audit-explanation-line-height);
display: inline-block;
}

.lh-audit--fail .lh-audit-explanation {
color: var(--color-fail);
}

/* Report */
.lh-list > div:not(:last-child) {
padding-bottom: 20px;
}

.lh-header-container {
display: block;
margin: 0 auto;
position: relative;
word-wrap: break-word;
}

.lh-report {
min-width: var(--report-min-width);
}

.lh-exception {
font-size: large;
}

.lh-code {
white-space: normal;
margin-top: 0;
font-size: 85%;
}

.lh-warnings {
--item-margin: calc(var(--report-line-height) / 6);
color: var(--color-average);
margin: var(--audit-padding-vertical) 0;
padding: calc(var(--audit-padding-vertical) / 2) calc(var(--audit-description-padding-left));
}
.lh-warnings span {
font-weight: bold;
}

.lh-warnings--toplevel {
--item-margin: calc(var(--header-line-height) / 4);
color: var(--report-text-color-secondary);
margin-left: auto;
margin-right: auto;
max-width: calc(var(--report-width) - var(--category-padding) * 2);
background-color: var(--color-amber-50);
padding: var(--toplevel-warning-padding);
}

.lh-warnings ul {
padding-left: calc(var(--category-padding) * 2);
margin: 0;
}
.lh-warnings li {
margin: var(--item-margin) 0;
}
.lh-warnings li:last-of-type {
margin-bottom: 0;
}

.lh-scores-header {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.lh-scores-header__solo {
padding: 0;
border: 0;
}

/* Gauge */

.lh-gauge__wrapper--pass {
color: var(--color-pass);
fill: var(--color-pass);
stroke: var(--color-pass);
}

.lh-gauge__wrapper--average {
color: var(--color-average);
fill: var(--color-average);
stroke: var(--color-average);
}

.lh-gauge__wrapper--fail {
color: var(--color-fail);
fill: var(--color-fail);
stroke: var(--color-fail);
}

.lh-gauge {
stroke-linecap: round;
width: var(--gauge-circle-size);
height: var(--gauge-circle-size);
}

.lh-category .lh-gauge {
--gauge-circle-size: var(--gauge-circle-size-big);
}

.lh-gauge-base {
opacity: 0.1;
stroke: var(--circle-background);
}

.lh-gauge-arc {
fill: none;
stroke: var(--circle-color);
transform-origin: 50% 50%;
animation: load-gauge var(--transition-length) ease forwards;
animation-delay: 250ms;
}

.lh-gauge__svg-wrapper {
position: relative;
height: var(--gauge-circle-size);
}
.lh-category .lh-gauge__svg-wrapper {
--gauge-circle-size: var(--gauge-circle-size-big);
}

/* The plugin badge overlay */
.lh-gauge__wrapper--plugin .lh-gauge__svg-wrapper::before {
width: var(--plugin-badge-size);
height: var(--plugin-badge-size);
background-color: var(--plugin-badge-background-color);
background-image: var(--plugin-icon-url);
background-repeat: no-repeat;
background-size: var(--plugin-icon-size);
background-position: 58% 50%;
content: "";
position: absolute;
right: -6px;
bottom: 0px;
display: block;
z-index: 100;
box-shadow: 0 0 4px rgba(0,0,0,.2);
border-radius: 25%;
}
.lh-category .lh-gauge__wrapper--plugin .lh-gauge__svg-wrapper::before {
width: var(--plugin-badge-size-big);
height: var(--plugin-badge-size-big);
}

@keyframes load-gauge {
from { stroke-dasharray: 0 352; }
}

.lh-gauge__percentage {
width: 100%;
height: var(--gauge-circle-size);
position: absolute;
font-family: var(--report-font-family-monospace);
font-size: calc(var(--gauge-circle-size) * 0.34 + 1.3px);
line-height: 0;
text-align: center;
top: calc(var(--score-container-padding) + var(--gauge-circle-size) / 2);
}

.lh-category .lh-gauge__percentage {
--gauge-circle-size: var(--gauge-circle-size-big);
--gauge-percentage-font-size: var(--gauge-percentage-font-size-big);
}

.lh-gauge__wrapper {
position: relative;
display: flex;
align-items: center;
flex-direction: column;
text-decoration: none;
padding: var(--score-container-padding);

--transition-length: 1s;

/* Contain the layout style paint & layers during animation*/
contain: content;
will-change: opacity; /* Only using for layer promotion */
}

.lh-gauge__label {
font-size: var(--gauge-label-font-size);
line-height: var(--gauge-label-line-height);
margin-top: 10px;
text-align: center;
color: var(--report-text-color);
}

/* TODO(#8185) use more BEM (.lh-gauge__label--big) instead of relying on descendant selector */
.lh-category .lh-gauge__label {
--gauge-label-font-size: var(--gauge-label-font-size-big);
--gauge-label-line-height: var(--gauge-label-line-height-big);
margin-top: 14px;
}


.lh-scores-header .lh-gauge__wrapper,
.lh-scores-header .lh-gauge--pwa__wrapper,
.lh-sticky-header .lh-gauge__wrapper,
.lh-sticky-header .lh-gauge--pwa__wrapper {
width: var(--gauge-wrapper-width);
}

.lh-scorescale {
display: inline-flex;
margin: 12px auto 0 auto;
border: 1px solid var(--color-gray-200);
border-radius: 20px;
padding: 8px 8px;
}

.lh-scorescale-range {
display: flex;
align-items: center;
margin: 0 12px;
font-family: var(--report-font-family-monospace);
white-space: nowrap;
}

.lh-scorescale-range::before {
content: '';
width: var(--scorescale-width);
height: var(--scorescale-height);
border-radius: 10px;
display: block;
margin-right: 10px;
}

.lh-scorescale-range--pass::before {
background-color: var(--color-pass);
}

.lh-scorescale-range--average::before {
background-color: var(--color-average);
}

.lh-scorescale-range--fail::before {
background-color: var(--color-fail);
}

/* Hide category score gauages if it's a single category report */
.lh-header--solo-category .lh-scores-wrapper {
display: none;
}


.lh-categories {
width: 100%;
overflow: hidden;
}

.lh-category {
padding: var(--category-padding);
max-width: var(--report-width);
margin: 0 auto;
}

.lh-category-wrapper {
border-bottom: 1px solid var(--color-gray-200);
}

.lh-category-wrapper:first-of-type {
border-top: 1px solid var(--color-gray-200);
}

/* section hash link jump should preserve fixed header
https://css-tricks.com/hash-tag-links-padding/
*/
.lh-category > .lh-permalink {
--sticky-header-height: calc(var(--gauge-circle-size) + var(--score-container-padding) * 2);
--topbar-plus-header: calc(var(--topbar-height) + var(--sticky-header-height));
margin-top: calc(var(--topbar-plus-header) * -1);
padding-bottom: var(--topbar-plus-header);
display: block;
visibility: hidden;
}

.lh-category-header {
font-size: var(--category-header-font-size);
min-height: var(--gauge-circle-size);
margin-bottom: var(--section-padding-vertical);
}

.lh-category-header .lh-score__gauge {
max-width: 400px;
width: auto;
margin: 0px auto;
}

.lh-category-header .lh-audit__title {
font-size: var(--category-header-font-size);
line-height: var(--header-line-height);
}

#lh-log {
position: fixed;
background-color: #323232;
color: #fff;
min-height: 48px;
min-width: 288px;
padding: 16px 24px;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
border-radius: 2px;
margin: 12px;
font-size: 14px;
cursor: default;
transition: transform 0.3s, opacity 0.3s;
transform: translateY(100px);
opacity: 0;
bottom: 0;
left: 0;
z-index: 3;
}

#lh-log.show {
opacity: 1;
transform: translateY(0);
}

/* 964 fits the min-width of the filmstrip */
@media screen and (max-width: 964px) {
.lh-report {
margin-left: 0;
width: 100%;
}
}

@media print {
body {
-webkit-print-color-adjust: exact; /* print background colors */
}
.lh-container {
display: block;
}
.lh-report {
margin-left: 0;
padding-top: 0;
}
.lh-categories {
margin-top: 0;
}
}

.lh-table {
border-collapse: collapse;
/* Can't assign padding to table, so shorten the width instead. */
width: calc(100% - var(--audit-description-padding-left));
}

.lh-table thead th {
font-weight: normal;
color: var(--color-gray-600);
/* See text-wrapping comment on .lh-container. */
word-break: normal;
}

.lh-table tbody tr:nth-child(odd) {
background-color: var(--table-higlight-background-color);
}

.lh-table th,
.lh-table td {
padding: 8px 6px;
}
.lh-table th:first-child {
padding-left: 0;
}
.lh-table th:last-child {
padding-right: 0;
}

/* Looks unnecessary, but mostly for keeping the <th>s left-aligned */
.lh-table-column--text,
.lh-table-column--source-location,
.lh-table-column--url,
/* .lh-table-column--thumbnail, */
/* .lh-table-column--empty,*/
.lh-table-column--code,
.lh-table-column--node {
text-align: left;
}

.lh-table-column--bytes,
.lh-table-column--timespanMs,
.lh-table-column--ms,
.lh-table-column--numeric {
text-align: right;
word-break: normal;
}



.lh-table .lh-table-column--thumbnail {
width: var(--image-preview-size);
padding: 0;
}

.lh-table-column--url {
min-width: 250px;
}

/* Keep columns narrow if they follow the URL column */
/* 12% was determined to be a decent narrow width, but wide enough for column headings */
.lh-table-column--url + th.lh-table-column--bytes,
.lh-table-column--url + .lh-table-column--bytes + th.lh-table-column--bytes,
.lh-table-column--url + .lh-table-column--ms,
.lh-table-column--url + .lh-table-column--ms + th.lh-table-column--bytes,
.lh-table-column--url + .lh-table-column--bytes + th.lh-table-column--timespanMs {
width: 12%;
}


.lh-text__url-host {
display: inline;
}

.lh-text__url-host {
margin-left: calc(var(--report-font-size) / 2);
opacity: 0.6;
font-size: 90%
}

.lh-thumbnail {
object-fit: cover;
width: var(--image-preview-size);
height: var(--image-preview-size);
display: block;
}

.lh-unknown pre {
overflow: scroll;
border: solid 1px var(--color-gray-200);
}

.lh-text__url > a {
color: inherit;
text-decoration: none;
}

.lh-text__url > a:hover {
text-decoration: underline dotted #999;
}

.lh-sub-rows:not(:first-child) .lh-sub-row {
margin-left: 20px;
color: var(--color-gray-700);
}
.lh-sub-row {
margin-bottom: 0;
}

/* Chevron
https://codepen.io/paulirish/pen/LmzEmK
*/
.lh-chevron {
--chevron-angle: 42deg;
/* Edge doesn't support transform: rotate(calc(...)), so we define it here */
--chevron-angle-right: -42deg;
width: var(--chevron-size);
height: var(--chevron-size);
margin-top: calc((var(--report-line-height) - 12px) / 2);
}

.lh-chevron__lines {
transition: transform 0.4s;
transform: translateY(var(--report-line-height));
}
.lh-chevron__line {
stroke: var(--chevron-line-stroke);
stroke-width: var(--chevron-size);
stroke-linecap: square;
transform-origin: 50%;
transform: rotate(var(--chevron-angle));
transition: transform 300ms, stroke 300ms;
}

.lh-audit-group > summary > .lh-audit-group__summary > .lh-chevron .lh-chevron__line-right,
.lh-audit-group[open] > summary > .lh-audit-group__summary > .lh-chevron .lh-chevron__line-left,
.lh-audit > .lh-expandable-details .lh-chevron__line-right,
.lh-audit > .lh-expandable-details[open] .lh-chevron__line-left {
transform: rotate(var(--chevron-angle-right));
}

.lh-audit-group[open] > summary > .lh-audit-group__summary > .lh-chevron .lh-chevron__line-right,
.lh-audit > .lh-expandable-details[open] .lh-chevron__line-right {
transform: rotate(var(--chevron-angle));
}

.lh-audit-group[open] > summary > .lh-audit-group__summary > .lh-chevron .lh-chevron__lines,
.lh-audit > .lh-expandable-details[open] .lh-chevron__lines {
transform: translateY(calc(var(--chevron-size) * -1));
}



/* Tooltip */
.tooltip-boundary {
position: relative;
}

.tooltip {
position: absolute;
display: none; /* Don't retain these layers when not needed */
opacity: 0;
background: #ffffff;
min-width: 246px;
max-width: 275px;
padding: 15px;
border-radius: 5px;
text-align: initial;
}
/* shrink tooltips to not be cutoff on left edge of narrow viewports
45vw is chosen to be ~= width of the left column of metrics
*/
@media screen and (max-width: 535px) {
.tooltip {
min-width: 45vw;
padding: 3vw;
}
}

.tooltip-boundary:hover {
background-color: var(--color-hover);
}

.tooltip-boundary:hover .tooltip {
display: block;
animation: fadeInTooltip 250ms;
animation-fill-mode: forwards;
animation-delay: 850ms;
bottom: 100%;
z-index: 1;
will-change: opacity;
right: 0;
pointer-events: none;
}

.tooltip::before {
content: "";
border: solid transparent;
border-bottom-color: #fff;
border-width: 10px;
position: absolute;
bottom: -20px;
right: 6px;
transform: rotate(180deg);
pointer-events: none;
}

@keyframes fadeInTooltip {
0% { opacity: 0; }
75% { opacity: 1; }
100% { opacity: 1; filter: drop-shadow(1px 0px 1px #aaa) drop-shadow(0px 2px 4px hsla(206, 6%, 25%, 0.15)); pointer-events: auto; }
}


</style>`
Insert cell
{
// Rendering the categories.
const dom = new self.DOM(document);
const renderer = new self.ReportRenderer(dom);
const container = document.createElement('div');
renderer.renderReport(self.lhr, container);

// Exclude the topbar because it doesn't work at all in observable.
const result = container.querySelector('.lh-report').innerHTML;
return html`${result}`;
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more