static/frontend: add missing license headers

Change-Id: Ibf822729bf7ad59ee16bc2808aec270e8820d489
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/455957
Run-TryBot: Jamal Carvalho <jamal@golang.org>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/static/frontend/about/about.css b/static/frontend/about/about.css
index 11b9e6e..75a5125 100644
--- a/static/frontend/about/about.css
+++ b/static/frontend/about/about.css
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2022 The Go Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
 .about-Wrapper ul {
     list-style-type: disc;
     padding-left: 2em;
diff --git a/static/frontend/about/about.min.css.map b/static/frontend/about/about.min.css.map
index 40c9779..75c7861 100644
--- a/static/frontend/about/about.min.css.map
+++ b/static/frontend/about/about.min.css.map
@@ -1,7 +1,7 @@
 {
   "version": 3,
   "sources": ["about.css"],
-  "sourcesContent": [".about-Wrapper ul {\n    list-style-type: disc;\n    padding-left: 2em;\n}\n.about-Wrapper li {\n    margin: 0.5em 0;\n}\n.about-Wrapper b {\n    font-weight: bold;\n}\n\na.btn {\n    background: var(--color-button);\n    font-style: normal;\n    font-weight: 400;\n    font-size: 1rem;\n    line-height: 1rem;\n    border-radius: 0.3125rem;\n    color: #FFF;\n    display: block;\n    padding: 0.625rem;\n    margin-top: 1rem;\n    text-align: center;\n    text-decoration: none;\n}\n\n.about-Content {\n    padding: 3rem 0;\n    padding: 2rem var(--gutter);\n}\n.about-Content ul {\n    overflow-wrap: break-word;\n}\n.about-Content h1 {\n    font-weight: 400;\n    font-size: 2.25rem;\n    line-height: 2rem;\n}\n.about-Content h2 {\n    font-weight: 400;\n    font-size: 1.5rem;\n    line-height: 2rem;\n}\n.about-Content h3 {\n    font-weight: 400;\n    font-size: 1.125rem;\n    line-height: 2rem;\n}\n.about-Content p {\n    font-weight: 400;\n    font-size: 0.875rem;\n    line-height: 1.5rem;\n}\n.about-Wrapper {\n    grid-template-areas:\n        \"content\";\n}\n.about-Content {\n    grid-area: content;\n}\n.Sidebar {\n    display: none;\n    grid-area: Sidebar;\n    padding: 3rem;\n    padding-top: 9rem;\n}\n.Sidebar a {\n    width: 7.5rem;\n}\n.Sidebar h4 {\n    font-style: normal;\n    font-weight: 500;\n    font-size: 1rem;\n    line-height: 1.5rem;\n}\n.Sidebar p, .Sidebar-faq .link {\n    font-style: normal;\n    font-weight: 400;\n    font-size: 0.875rem;\n    line-height: 1.5rem;\n}\n.Sidebar-faq h4 {\n    font-size: 0.813rem;\n    margin-top: 1.25rem;\n    margin-bottom: 0.375rem;\n}\n.Sidebar-faq p {\n    margin-top: 0;\n    margin-bottom: 0.625rem;\n}\n.Sidebar-socialLinks {\n    display: flex;\n    align-items: center;\n}\n.Sidebar-socialLinks a {\n    display: flex;\n    width: unset;\n    margin-right: 0.675rem;\n}\n.LeftNav-columns {\n    display: flex;\n}\n\n.LeftNav-sidebar {\n    display: none;\n    grid-area: LeftNav-sidebar;\n    padding: 3rem;\n    height: 100vh;\n    position: sticky;\n    top: 0;\n    overflow: auto;\n    margin-bottom: 1rem;\n}\n\n.LeftNav-sidebar + article.Article {\n    margin: unset;\n    margin-top: 3rem;\n    margin-bottom: 1.875rem;\n}\n\n.LeftNav {\n    display: flex;\n    flex-direction: column;\n}\n\n.LeftNav a {\n    display: flex;\n    align-items: center;\n    padding-bottom: 0.675rem;\n    padding-top: 0.675rem;\n    text-decoration: none;\n    border-bottom: var(--border);\n}\n\n.LeftNav a span {\n    flex: 30;\n    margin: 0 0.75rem;\n    font-style: normal;\n    font-weight: 500;\n    font-size: 1rem;\n    line-height: 1.5rem;\n    color: var(--color-text-subtle);\n}\n\n\n.LeftNav .LeftSubnav a span {\n    font-size: 0.875rem;\n    font-weight: 400;\n}\n\n.LeftNav a.active,\n.LeftNav a:hover,\n.LeftNav a:active,\n.LeftNav a:focus {\n    background: var(--color-background-info);\n}\n\n.LeftNav a.active span,\n.LeftNav a:hover span,\n.LeftNav a:active span,\n.LeftNav a:focus span {\n    color: var(--color-text);\n}\n\n.LeftNav ul.LeftSubnav li a.active,\n.LeftNav ul.LeftSubnav li a:hover,\n.LeftNav ul.LeftSubnav li a:active,\n.LeftNav ul.LeftSubnav li a:focus {\n    background: var(--color-background-accented);\n}\n\n.LeftSubnav {\n    list-style: none;\n    padding: unset;\n    margin-top: unset;\n    margin-bottom: unset;\n}\n\n.LeftSubnav a {\n    padding-left: 1rem;\n}\n\n.LeftSubnav + a {\n    border-top: var(--border);\n}\n\n.LeftSubnav img {\n    visibility: hidden;\n    flex: 1;\n}\n\n.LeftSubnav a.active img,\n.LeftSubnav a:hover img,\n.LeftSubnav a:focus img,\n.LeftSubnav a:active img {\n    visibility: visible;\n}\n\nul.LeftSubnav {\n    padding-left: unset;\n}\n\n.LeftSubnav li {\n    margin: unset;\n    list-style: none;\n}\n\n.LeftNav-columns .LeftNav .LeftSubnav a,\n.LeftNav .LeftSubnav a {\n    border-bottom: unset;\n}\n@media screen and (min-width: 78rem) {\n    .Sidebar {\n        display: block;\n    }\n    .about-Wrapper {\n        display: grid;\n    }\n    .about-Content {\n        padding: 3rem 0;\n    }\n}\n@media (min-width: 31.25rem) {\n    .about-Wrapper {\n        grid-template-columns: 1fr 3fr;\n        grid-template-areas:\n        \"content content\";\n    }\n    nav.LeftNav ul {\n        display: flex;\n        justify-content: space-between;\n    }\n}\n@media (min-width: 43.75rem) {\n    .about-Wrapper {\n        grid-template-columns: 1.5fr 4fr 1.5fr;\n        grid-template-areas:\n        \"LeftNav-sidebar content Sidebar\";\n    }\n    nav.LeftNav ul {\n        flex-direction: column;\n    }\n}\n@media only screen and (min-width: 90rem) {\n    .LeftNav-sidebar {\n        display: block;\n    }\n}"],
-  "mappings": ";;;;;AAAA,kBACI,qBACA,iBAEJ,kBAJA,cAOA,iBACI,gBAGJ,MACI,+BACA,kBACA,gBACA,eACA,iBAhBJ,uBAkBI,WACA,cAnBJ,gBAqBI,gBACA,kBACA,qBAGJ,eA1BA,eA4BI,2BAEJ,kBACI,yBAEJ,kBACI,gBACA,kBACA,iBAEJ,kBACI,gBACA,iBACA,iBAEJ,kBACI,gBACA,mBACA,iBAEJ,iBACI,gBACA,kBACA,mBAEJ,eACI,8BAGJ,eACI,kBAEJ,SACI,aACA,kBA9DJ,uBAkEA,WACI,aAEJ,YACI,kBACA,gBACA,eACA,mBAEJ,8BACI,kBACA,gBACA,kBACA,mBAEJ,gBACI,kBACA,mBACA,sBAEJ,eACI,aACA,sBAEJ,qBACI,aACA,mBAEJ,uBACI,aACA,YACA,qBAEJ,iBACI,aAGJ,iBACI,aACA,0BAzGJ,aA2GI,aACA,gBACA,MACA,cACA,mBAGJ,iCACI,aACA,gBACA,uBAGJ,SACI,aACA,sBAGJ,WACI,aACA,mBACA,uBACA,oBACA,qBACA,4BAGJ,gBACI,QAvIJ,gBAyII,kBACA,gBACA,eACA,mBACA,+BAIJ,4BACI,kBACA,gBAGJ,sEAII,wCAGJ,0FAII,wBAGJ,0IAII,4CAGJ,YACI,gBACA,cACA,iBACA,oBAGJ,cACI,kBAGJ,cACI,yBAGJ,gBACI,kBACA,OAGJ,kGAII,mBAGJ,cACI,mBAGJ,eACI,aACA,gBAGJ,+DAEI,oBAEJ,qCACI,SACI,cAEJ,eACI,aAEJ,eA1NJ,gBA8NA,6BACI,eACI,8BACA,sCAGJ,eACI,aACA,+BAGR,6BACI,eACI,sCACA,sDAGJ,eACI,uBAGR,0CACI,iBACI",
+  "sourcesContent": ["/*\n * Copyright 2022 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n.about-Wrapper ul {\n    list-style-type: disc;\n    padding-left: 2em;\n}\n.about-Wrapper li {\n    margin: 0.5em 0;\n}\n.about-Wrapper b {\n    font-weight: bold;\n}\n\na.btn {\n    background: var(--color-button);\n    font-style: normal;\n    font-weight: 400;\n    font-size: 1rem;\n    line-height: 1rem;\n    border-radius: 0.3125rem;\n    color: #FFF;\n    display: block;\n    padding: 0.625rem;\n    margin-top: 1rem;\n    text-align: center;\n    text-decoration: none;\n}\n\n.about-Content {\n    padding: 3rem 0;\n    padding: 2rem var(--gutter);\n}\n.about-Content ul {\n    overflow-wrap: break-word;\n}\n.about-Content h1 {\n    font-weight: 400;\n    font-size: 2.25rem;\n    line-height: 2rem;\n}\n.about-Content h2 {\n    font-weight: 400;\n    font-size: 1.5rem;\n    line-height: 2rem;\n}\n.about-Content h3 {\n    font-weight: 400;\n    font-size: 1.125rem;\n    line-height: 2rem;\n}\n.about-Content p {\n    font-weight: 400;\n    font-size: 0.875rem;\n    line-height: 1.5rem;\n}\n.about-Wrapper {\n    grid-template-areas:\n        \"content\";\n}\n.about-Content {\n    grid-area: content;\n}\n.Sidebar {\n    display: none;\n    grid-area: Sidebar;\n    padding: 3rem;\n    padding-top: 9rem;\n}\n.Sidebar a {\n    width: 7.5rem;\n}\n.Sidebar h4 {\n    font-style: normal;\n    font-weight: 500;\n    font-size: 1rem;\n    line-height: 1.5rem;\n}\n.Sidebar p, .Sidebar-faq .link {\n    font-style: normal;\n    font-weight: 400;\n    font-size: 0.875rem;\n    line-height: 1.5rem;\n}\n.Sidebar-faq h4 {\n    font-size: 0.813rem;\n    margin-top: 1.25rem;\n    margin-bottom: 0.375rem;\n}\n.Sidebar-faq p {\n    margin-top: 0;\n    margin-bottom: 0.625rem;\n}\n.Sidebar-socialLinks {\n    display: flex;\n    align-items: center;\n}\n.Sidebar-socialLinks a {\n    display: flex;\n    width: unset;\n    margin-right: 0.675rem;\n}\n.LeftNav-columns {\n    display: flex;\n}\n\n.LeftNav-sidebar {\n    display: none;\n    grid-area: LeftNav-sidebar;\n    padding: 3rem;\n    height: 100vh;\n    position: sticky;\n    top: 0;\n    overflow: auto;\n    margin-bottom: 1rem;\n}\n\n.LeftNav-sidebar + article.Article {\n    margin: unset;\n    margin-top: 3rem;\n    margin-bottom: 1.875rem;\n}\n\n.LeftNav {\n    display: flex;\n    flex-direction: column;\n}\n\n.LeftNav a {\n    display: flex;\n    align-items: center;\n    padding-bottom: 0.675rem;\n    padding-top: 0.675rem;\n    text-decoration: none;\n    border-bottom: var(--border);\n}\n\n.LeftNav a span {\n    flex: 30;\n    margin: 0 0.75rem;\n    font-style: normal;\n    font-weight: 500;\n    font-size: 1rem;\n    line-height: 1.5rem;\n    color: var(--color-text-subtle);\n}\n\n\n.LeftNav .LeftSubnav a span {\n    font-size: 0.875rem;\n    font-weight: 400;\n}\n\n.LeftNav a.active,\n.LeftNav a:hover,\n.LeftNav a:active,\n.LeftNav a:focus {\n    background: var(--color-background-info);\n}\n\n.LeftNav a.active span,\n.LeftNav a:hover span,\n.LeftNav a:active span,\n.LeftNav a:focus span {\n    color: var(--color-text);\n}\n\n.LeftNav ul.LeftSubnav li a.active,\n.LeftNav ul.LeftSubnav li a:hover,\n.LeftNav ul.LeftSubnav li a:active,\n.LeftNav ul.LeftSubnav li a:focus {\n    background: var(--color-background-accented);\n}\n\n.LeftSubnav {\n    list-style: none;\n    padding: unset;\n    margin-top: unset;\n    margin-bottom: unset;\n}\n\n.LeftSubnav a {\n    padding-left: 1rem;\n}\n\n.LeftSubnav + a {\n    border-top: var(--border);\n}\n\n.LeftSubnav img {\n    visibility: hidden;\n    flex: 1;\n}\n\n.LeftSubnav a.active img,\n.LeftSubnav a:hover img,\n.LeftSubnav a:focus img,\n.LeftSubnav a:active img {\n    visibility: visible;\n}\n\nul.LeftSubnav {\n    padding-left: unset;\n}\n\n.LeftSubnav li {\n    margin: unset;\n    list-style: none;\n}\n\n.LeftNav-columns .LeftNav .LeftSubnav a,\n.LeftNav .LeftSubnav a {\n    border-bottom: unset;\n}\n@media screen and (min-width: 78rem) {\n    .Sidebar {\n        display: block;\n    }\n    .about-Wrapper {\n        display: grid;\n    }\n    .about-Content {\n        padding: 3rem 0;\n    }\n}\n@media (min-width: 31.25rem) {\n    .about-Wrapper {\n        grid-template-columns: 1fr 3fr;\n        grid-template-areas:\n        \"content content\";\n    }\n    nav.LeftNav ul {\n        display: flex;\n        justify-content: space-between;\n    }\n}\n@media (min-width: 43.75rem) {\n    .about-Wrapper {\n        grid-template-columns: 1.5fr 4fr 1.5fr;\n        grid-template-areas:\n        \"LeftNav-sidebar content Sidebar\";\n    }\n    nav.LeftNav ul {\n        flex-direction: column;\n    }\n}\n@media only screen and (min-width: 90rem) {\n    .LeftNav-sidebar {\n        display: block;\n    }\n}"],
+  "mappings": ";;;;;AAMA,kBACI,qBACA,iBAEJ,kBAVA,cAaA,iBACI,gBAGJ,MACI,+BACA,kBACA,gBACA,eACA,iBAtBJ,uBAwBI,WACA,cAzBJ,gBA2BI,gBACA,kBACA,qBAGJ,eAhCA,eAkCI,2BAEJ,kBACI,yBAEJ,kBACI,gBACA,kBACA,iBAEJ,kBACI,gBACA,iBACA,iBAEJ,kBACI,gBACA,mBACA,iBAEJ,iBACI,gBACA,kBACA,mBAEJ,eACI,8BAGJ,eACI,kBAEJ,SACI,aACA,kBApEJ,uBAwEA,WACI,aAEJ,YACI,kBACA,gBACA,eACA,mBAEJ,8BACI,kBACA,gBACA,kBACA,mBAEJ,gBACI,kBACA,mBACA,sBAEJ,eACI,aACA,sBAEJ,qBACI,aACA,mBAEJ,uBACI,aACA,YACA,qBAEJ,iBACI,aAGJ,iBACI,aACA,0BA/GJ,aAiHI,aACA,gBACA,MACA,cACA,mBAGJ,iCACI,aACA,gBACA,uBAGJ,SACI,aACA,sBAGJ,WACI,aACA,mBACA,uBACA,oBACA,qBACA,4BAGJ,gBACI,QA7IJ,gBA+II,kBACA,gBACA,eACA,mBACA,+BAIJ,4BACI,kBACA,gBAGJ,sEAII,wCAGJ,0FAII,wBAGJ,0IAII,4CAGJ,YACI,gBACA,cACA,iBACA,oBAGJ,cACI,kBAGJ,cACI,yBAGJ,gBACI,kBACA,OAGJ,kGAII,mBAGJ,cACI,mBAGJ,eACI,aACA,gBAGJ,+DAEI,oBAEJ,qCACI,SACI,cAEJ,eACI,aAEJ,eAhOJ,gBAoOA,6BACI,eACI,8BACA,sCAGJ,eACI,aACA,+BAGR,6BACI,eACI,sCACA,sDAGJ,eACI,uBAGR,0CACI,iBACI",
   "names": []
 }
diff --git a/static/frontend/about/index.js b/static/frontend/about/index.js
index 45b43cd..99bd03f 100644
--- a/static/frontend/about/index.js
+++ b/static/frontend/about/index.js
@@ -1,2 +1,8 @@
-var O=async function(){if(!["/about"].includes(window.location.pathname))return;let d="h2, h3, h4",u=".LeftNav a",i=document.querySelector(".LeftNav"),c=document.querySelector(".go-Content"),h=!1;function a(t="",r={},...o){if(!t)throw new Error("Provide `type` to create document element.");let n=Object.assign(document.createElement(t),r);return o.forEach(s=>{typeof s=="string"?n.appendChild(document.createTextNode(s)):Array.isArray(s)?s.forEach(l=>n.appendChild(l)):s instanceof HTMLElement&&n.appendChild(s)}),n}function T(){return new Promise((t,r)=>{var s,l,f,L,v,E,p,y,H,A;let o=[],n=[];if(!c||!i)return r(".SiteContent not found.");if(i instanceof HTMLElement&&!((s=i==null?void 0:i.dataset)==null?void 0:s.hydrate))return t(!0);for(let e of c.querySelectorAll(d))if(e instanceof HTMLElement&&!((l=e==null?void 0:e.dataset)==null?void 0:l.ignore))switch(e.tagName){case"H2":o=[...o,{id:e.id,label:((f=e==null?void 0:e.dataset)==null?void 0:f.title)?e.dataset.title:(L=e.textContent)!=null?L:""}];break;case"H3":case"H4":((v=o[o.length-1])==null?void 0:v.subnav)?o[o.length-1].subnav&&((A=o[o.length-1].subnav)==null||A.push({id:e.id,label:((y=e==null?void 0:e.dataset)==null?void 0:y.title)?e.dataset.title:(H=e.textContent)!=null?H:""})):o[o.length-1].subnav=[{id:e.id,label:((E=e==null?void 0:e.dataset)==null?void 0:E.title)?e.dataset.title:(p=e.textContent)!=null?p:""}];break}for(let e of o){let C=a("a",{href:"#"+e.id},a("span",{},e.label));if(n=[...n,C],e==null?void 0:e.subnav){let b=[];for(let M of e.subnav){let x=a("li",{},a("a",{href:"#"+M.id},a("img",{src:"/static/frontend/about/dot.svg",width:"5",height:"5"}),a("span",{},M.label)));b=[...b,x]}let N=a("ul",{className:"LeftSubnav"},b);n=[...n,N]}}return n.forEach(e=>i.appendChild(e)),t(!0)})}function S(){return new Promise(t=>{if(!document.querySelectorAll(u))return t(!0);for(let r of document.querySelectorAll(u))if(r instanceof HTMLAnchorElement&&r.href===location.href){m(r);break}t(!0)})}function k(){return new Promise(t=>{if(!document.querySelectorAll(u))return t(!0);for(let r of document.querySelectorAll(u))r.classList.remove("active");t(!0)})}function m(t){t instanceof HTMLAnchorElement&&k().then(()=>{var o,n,s;t.classList.add("active");let r=(o=t==null?void 0:t.parentNode)==null?void 0:o.parentNode;r instanceof HTMLElement&&((n=r==null?void 0:r.classList)==null?void 0:n.contains("LeftSubnav"))&&((s=r.previousElementSibling)==null||s.classList.add("active"))})}function w(){g();let t=document.querySelector('[href="'+location.hash+'"]');t instanceof HTMLAnchorElement&&m(t)}function g(){h=!0,setTimeout(()=>{h=!1},200)}function q(){var t;if(window.addEventListener("hashchange",w),c==null?void 0:c.querySelectorAll(d)){let r=n=>{if(!h&&Array.isArray(n)&&n.length>0){for(let s of n)if(s.isIntersecting&&s.target instanceof HTMLElement){let{id:l}=s.target,f=document.querySelector('[href="#'+l+'"]');f instanceof HTMLAnchorElement&&m(f);break}}},o=new IntersectionObserver(r,{threshold:0,rootMargin:"0px 0px -50% 0px"});for(let n of c.querySelectorAll(d))n instanceof HTMLElement&&!((t=n==null?void 0:n.dataset)==null?void 0:t.ignore)&&o.observe(n)}}try{await T(),await S(),location.hash&&g(),q()}catch(t){t instanceof Error?console.error(t.message):console.error(t)}};export{O as initJumpLinks};
+var O=async function(){if(!["/about"].includes(window.location.pathname))return;let d="h2, h3, h4",u=".LeftNav a",i=document.querySelector(".LeftNav"),c=document.querySelector(".go-Content"),h=!1;function a(t="",r={},...o){if(!t)throw new Error("Provide `type` to create document element.");let n=Object.assign(document.createElement(t),r);return o.forEach(s=>{typeof s=="string"?n.appendChild(document.createTextNode(s)):Array.isArray(s)?s.forEach(l=>n.appendChild(l)):s instanceof HTMLElement&&n.appendChild(s)}),n}function T(){return new Promise((t,r)=>{var s,l,f,L,v,E,p,y,H,A;let o=[],n=[];if(!c||!i)return r(".SiteContent not found.");if(i instanceof HTMLElement&&!((s=i==null?void 0:i.dataset)!=null&&s.hydrate))return t(!0);for(let e of c.querySelectorAll(d))if(e instanceof HTMLElement&&!((l=e==null?void 0:e.dataset)!=null&&l.ignore))switch(e.tagName){case"H2":o=[...o,{id:e.id,label:(f=e==null?void 0:e.dataset)!=null&&f.title?e.dataset.title:(L=e.textContent)!=null?L:""}];break;case"H3":case"H4":(v=o[o.length-1])!=null&&v.subnav?o[o.length-1].subnav&&((A=o[o.length-1].subnav)==null||A.push({id:e.id,label:(y=e==null?void 0:e.dataset)!=null&&y.title?e.dataset.title:(H=e.textContent)!=null?H:""})):o[o.length-1].subnav=[{id:e.id,label:(E=e==null?void 0:e.dataset)!=null&&E.title?e.dataset.title:(p=e.textContent)!=null?p:""}];break}for(let e of o){let C=a("a",{href:"#"+e.id},a("span",{},e.label));if(n=[...n,C],e!=null&&e.subnav){let b=[];for(let M of e.subnav){let x=a("li",{},a("a",{href:"#"+M.id},a("img",{src:"/static/frontend/about/dot.svg",width:"5",height:"5"}),a("span",{},M.label)));b=[...b,x]}let N=a("ul",{className:"LeftSubnav"},b);n=[...n,N]}}return n.forEach(e=>i.appendChild(e)),t(!0)})}function S(){return new Promise(t=>{if(!document.querySelectorAll(u))return t(!0);for(let r of document.querySelectorAll(u))if(r instanceof HTMLAnchorElement&&r.href===location.href){m(r);break}t(!0)})}function k(){return new Promise(t=>{if(!document.querySelectorAll(u))return t(!0);for(let r of document.querySelectorAll(u))r.classList.remove("active");t(!0)})}function m(t){t instanceof HTMLAnchorElement&&k().then(()=>{var o,n,s;t.classList.add("active");let r=(o=t==null?void 0:t.parentNode)==null?void 0:o.parentNode;r instanceof HTMLElement&&((n=r==null?void 0:r.classList)==null?void 0:n.contains("LeftSubnav"))&&((s=r.previousElementSibling)==null||s.classList.add("active"))})}function w(){g();let t=document.querySelector('[href="'+location.hash+'"]');t instanceof HTMLAnchorElement&&m(t)}function g(){h=!0,setTimeout(()=>{h=!1},200)}function q(){var t;if(window.addEventListener("hashchange",w),c!=null&&c.querySelectorAll(d)){let r=n=>{if(!h&&Array.isArray(n)&&n.length>0){for(let s of n)if(s.isIntersecting&&s.target instanceof HTMLElement){let{id:l}=s.target,f=document.querySelector('[href="#'+l+'"]');f instanceof HTMLAnchorElement&&m(f);break}}},o=new IntersectionObserver(r,{threshold:0,rootMargin:"0px 0px -50% 0px"});for(let n of c.querySelectorAll(d))n instanceof HTMLElement&&!((t=n==null?void 0:n.dataset)!=null&&t.ignore)&&o.observe(n)}}try{await T(),await S(),location.hash&&g(),q()}catch(t){t instanceof Error?console.error(t.message):console.error(t)}};export{O as initJumpLinks};
+/**
+ * @license
+ * Copyright 2022 The Go Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
 //# sourceMappingURL=index.js.map
diff --git a/static/frontend/about/index.js.map b/static/frontend/about/index.js.map
index aa99842..bea2a15 100644
--- a/static/frontend/about/index.js.map
+++ b/static/frontend/about/index.js.map
@@ -1,7 +1,7 @@
 {
   "version": 3,
   "sources": ["index.ts"],
-  "sourcesContent": ["/**\n * Left Navigation.\n */\nexport const initJumpLinks = async function () {\n  const pagesWithJumpLinks = ['/about'];\n  if (!pagesWithJumpLinks.includes(window.location.pathname)) {\n    // stop the file from doing anything else if the page doesn't have jumplinks\n    return;\n  }\n\n  // these might be generated or not so don't grab references to the elements until actually need them.\n  const titles = 'h2, h3, h4';\n  const nav = '.LeftNav a';\n  // these are always in the dom so we can get them now and throw errors if they're not.\n  const leftNav = document.querySelector('.LeftNav');\n  const siteContent = document.querySelector('.go-Content');\n  let isObserverDisabled = false;\n\n  /**\n   * El function\n   * @example el('h1', {className: 'title'}, 'Welcome to the site');\n   * @example el('ul', {className: 'list'}, el('li', {}, 'Item one'), el('li', {}, 'Item two'), el('li', {}, 'Item three'));\n   * @example el('img', {src: '/url.svg'});\n   */\n  function el(\n    type = '',\n    props: { [key: string]: string } = {},\n    ...children: (HTMLElement | HTMLElement[] | string | undefined)[]\n  ) {\n    // Error, no type declared.\n    if (!type) {\n      throw new Error('Provide `type` to create document element.');\n    }\n\n    // Create element with optional attribute props\n    const docEl = Object.assign(document.createElement(type), props);\n\n    // Children: array containing strings or elements\n    children.forEach(child => {\n      if (typeof child === 'string') {\n        docEl.appendChild(document.createTextNode(child));\n      } else if (Array.isArray(child)) {\n        child.forEach(c => docEl.appendChild(c));\n      } else if (child instanceof HTMLElement) {\n        docEl.appendChild(child);\n      }\n    });\n\n    return docEl;\n  }\n  /**  Build Nav if data hydrate is present. */\n  function buildNav() {\n    return new Promise((resolve, reject) => {\n      let navItems: { id: string; label: string; subnav?: { id: string; label: string }[] }[] = [];\n      let elements: HTMLElement[] = [];\n\n      if (!siteContent || !leftNav) {\n        return reject('.SiteContent not found.');\n      }\n      if (leftNav instanceof HTMLElement && !leftNav?.dataset?.hydrate) {\n        return resolve(true);\n      }\n\n      for (const title of siteContent.querySelectorAll(titles)) {\n        if (title instanceof HTMLElement && !title?.dataset?.ignore) {\n          switch (title.tagName) {\n            case 'H2':\n              navItems = [\n                ...navItems,\n                {\n                  id: title.id,\n                  label: title?.dataset?.title ? title.dataset.title : title.textContent ?? '',\n                },\n              ];\n              break;\n\n            case 'H3':\n            case 'H4':\n              if (!navItems[navItems.length - 1]?.subnav) {\n                navItems[navItems.length - 1].subnav = [\n                  {\n                    id: title.id,\n                    label: title?.dataset?.title ? title.dataset.title : title.textContent ?? '',\n                  },\n                ];\n              } else if (navItems[navItems.length - 1].subnav) {\n                navItems[navItems.length - 1].subnav?.push({\n                  id: title.id,\n                  label: title?.dataset?.title ? title.dataset.title : title.textContent ?? '',\n                });\n              }\n              break;\n          }\n        }\n      }\n\n      for (const navItem of navItems) {\n        const link = el('a', { href: '#' + navItem.id }, el('span', {}, navItem.label));\n        elements = [...elements, link];\n        if (navItem?.subnav) {\n          let subLinks: HTMLElement[] = [];\n          for (const subnavItem of navItem.subnav) {\n            const subItem = el(\n              'li',\n              {},\n              el(\n                'a',\n                { href: '#' + subnavItem.id },\n                el('img', { src: '/static/frontend/about/dot.svg', width: '5', height: '5' }),\n                el('span', {}, subnavItem.label)\n              )\n            );\n            subLinks = [...subLinks, subItem];\n          }\n          const list = el('ul', { className: 'LeftSubnav' }, subLinks);\n          elements = [...elements, list];\n        }\n      }\n\n      elements.forEach(element => leftNav.appendChild(element));\n\n      return resolve(true);\n    });\n  }\n  /**\n   * Set the correct active element.\n   */\n  function setNav() {\n    return new Promise(resolve => {\n      if (!document.querySelectorAll(nav)) return resolve(true);\n      for (const a of document.querySelectorAll(nav)) {\n        if (a instanceof HTMLAnchorElement && a.href === location.href) {\n          setElementActive(a);\n          break;\n        }\n      }\n      resolve(true);\n    });\n  }\n  /** resetNav: removes all .active from nav elements */\n  function resetNav() {\n    return new Promise(resolve => {\n      if (!document.querySelectorAll(nav)) return resolve(true);\n      for (const a of document.querySelectorAll(nav)) {\n        a.classList.remove('active');\n      }\n      resolve(true);\n    });\n  }\n  /** setElementActive: controls resetting nav and highlighting the appropriate nav items */\n  function setElementActive(element: HTMLAnchorElement) {\n    if (element instanceof HTMLAnchorElement) {\n      resetNav().then(() => {\n        element.classList.add('active');\n        const parent = element?.parentNode?.parentNode;\n        if (parent instanceof HTMLElement && parent?.classList?.contains('LeftSubnav')) {\n          parent.previousElementSibling?.classList.add('active');\n        }\n      });\n    }\n  }\n  /** setLinkManually: disables observer and selects the clicked nav item. */\n  function setLinkManually() {\n    delayObserver();\n    const link = document.querySelector('[href=\"' + location.hash + '\"]');\n    if (link instanceof HTMLAnchorElement) {\n      setElementActive(link);\n    }\n  }\n  /** delayObserver: Quick on off switch for intersection observer. */\n  function delayObserver() {\n    isObserverDisabled = true;\n    setTimeout(() => {\n      isObserverDisabled = false;\n    }, 200);\n  }\n  /** observeSections: kicks off observation of titles as well as manual clicks with hashchange */\n  function observeSections() {\n    window.addEventListener('hashchange', setLinkManually);\n\n    if (siteContent?.querySelectorAll(titles)) {\n      const callback: IntersectionObserverCallback = entries => {\n        if (!isObserverDisabled && Array.isArray(entries) && entries.length > 0) {\n          for (const entry of entries) {\n            if (entry.isIntersecting && entry.target instanceof HTMLElement) {\n              const { id } = entry.target;\n              const link = document.querySelector('[href=\"#' + id + '\"]');\n              if (link instanceof HTMLAnchorElement) {\n                setElementActive(link);\n              }\n              break;\n            }\n          }\n        }\n      };\n      // rootMargin is important when multiple sections are in the observable area **on page load**.\n      // they will still be highlighted on scroll because of the root margin.\n      const ob = new IntersectionObserver(callback, {\n        threshold: 0,\n        rootMargin: '0px 0px -50% 0px',\n      });\n      for (const title of siteContent.querySelectorAll(titles)) {\n        if (title instanceof HTMLElement && !title?.dataset?.ignore) {\n          ob.observe(title);\n        }\n      }\n    }\n  }\n\n  try {\n    await buildNav();\n    await setNav();\n    if (location.hash) {\n      delayObserver();\n    }\n    observeSections();\n  } catch (e) {\n    if (e instanceof Error) {\n      console.error(e.message);\n    } else {\n      console.error(e);\n    }\n  }\n};\n"],
-  "mappings": "AAGO,GAAM,GAAgB,gBAAkB,CAE7C,GAAI,CAAC,AADsB,CAAC,UACJ,SAAS,OAAO,SAAS,UAE/C,OAIF,GAAM,GAAS,aACT,EAAM,aAEN,EAAU,SAAS,cAAc,YACjC,EAAc,SAAS,cAAc,eACvC,EAAqB,GAQzB,WACE,EAAO,GACP,EAAmC,MAChC,EACH,CAEA,GAAI,CAAC,EACH,KAAM,IAAI,OAAM,8CAIlB,GAAM,GAAQ,OAAO,OAAO,SAAS,cAAc,GAAO,GAG1D,SAAS,QAAQ,GAAS,CACxB,AAAI,MAAO,IAAU,SACnB,EAAM,YAAY,SAAS,eAAe,IACrC,AAAI,MAAM,QAAQ,GACvB,EAAM,QAAQ,GAAK,EAAM,YAAY,IAC5B,YAAiB,cAC1B,EAAM,YAAY,KAIf,EAGT,YAAoB,CAClB,MAAO,IAAI,SAAQ,CAAC,EAAS,IAAW,CApD5C,wBAqDM,GAAI,GAAsF,GACtF,EAA0B,GAE9B,GAAI,CAAC,GAAe,CAAC,EACnB,MAAO,GAAO,2BAEhB,GAAI,YAAmB,cAAe,CAAC,qBAAS,UAAT,cAAkB,SACvD,MAAO,GAAQ,IAGjB,OAAW,KAAS,GAAY,iBAAiB,GAC/C,GAAI,YAAiB,cAAe,CAAC,qBAAO,UAAP,cAAgB,QACnD,OAAQ,EAAM,aACP,KACH,EAAW,CACT,GAAG,EACH,CACE,GAAI,EAAM,GACV,MAAO,qBAAO,UAAP,cAAgB,OAAQ,EAAM,QAAQ,MAAQ,KAAM,cAAN,OAAqB,KAG9E,UAEG,SACA,KACH,AAAK,MAAS,EAAS,OAAS,KAA3B,cAA+B,QAOzB,EAAS,EAAS,OAAS,GAAG,QACvC,MAAS,EAAS,OAAS,GAAG,SAA9B,QAAsC,KAAK,CACzC,GAAI,EAAM,GACV,MAAO,qBAAO,UAAP,cAAgB,OAAQ,EAAM,QAAQ,MAAQ,KAAM,cAAN,OAAqB,MAT5E,EAAS,EAAS,OAAS,GAAG,OAAS,CACrC,CACE,GAAI,EAAM,GACV,MAAO,qBAAO,UAAP,cAAgB,OAAQ,EAAM,QAAQ,MAAQ,KAAM,cAAN,OAAqB,KAShF,MAKR,OAAW,KAAW,GAAU,CAC9B,GAAM,GAAO,EAAG,IAAK,CAAE,KAAM,IAAM,EAAQ,IAAM,EAAG,OAAQ,GAAI,EAAQ,QAExE,GADA,EAAW,CAAC,GAAG,EAAU,GACrB,iBAAS,OAAQ,CACnB,GAAI,GAA0B,GAC9B,OAAW,KAAc,GAAQ,OAAQ,CACvC,GAAM,GAAU,EACd,KACA,GACA,EACE,IACA,CAAE,KAAM,IAAM,EAAW,IACzB,EAAG,MAAO,CAAE,IAAK,iCAAkC,MAAO,IAAK,OAAQ,MACvE,EAAG,OAAQ,GAAI,EAAW,SAG9B,EAAW,CAAC,GAAG,EAAU,GAE3B,GAAM,GAAO,EAAG,KAAM,CAAE,UAAW,cAAgB,GACnD,EAAW,CAAC,GAAG,EAAU,IAI7B,SAAS,QAAQ,GAAW,EAAQ,YAAY,IAEzC,EAAQ,MAMnB,YAAkB,CAChB,MAAO,IAAI,SAAQ,GAAW,CAC5B,GAAI,CAAC,SAAS,iBAAiB,GAAM,MAAO,GAAQ,IACpD,OAAW,KAAK,UAAS,iBAAiB,GACxC,GAAI,YAAa,oBAAqB,EAAE,OAAS,SAAS,KAAM,CAC9D,EAAiB,GACjB,MAGJ,EAAQ,MAIZ,YAAoB,CAClB,MAAO,IAAI,SAAQ,GAAW,CAC5B,GAAI,CAAC,SAAS,iBAAiB,GAAM,MAAO,GAAQ,IACpD,OAAW,KAAK,UAAS,iBAAiB,GACxC,EAAE,UAAU,OAAO,UAErB,EAAQ,MAIZ,WAA0B,EAA4B,CACpD,AAAI,YAAmB,oBACrB,IAAW,KAAK,IAAM,CAxJ5B,UAyJQ,EAAQ,UAAU,IAAI,UACtB,GAAM,GAAS,oBAAS,aAAT,cAAqB,WACpC,AAAI,YAAkB,cAAe,qBAAQ,YAAR,cAAmB,SAAS,gBAC/D,MAAO,yBAAP,QAA+B,UAAU,IAAI,aAMrD,YAA2B,CACzB,IACA,GAAM,GAAO,SAAS,cAAc,UAAY,SAAS,KAAO,MAChE,AAAI,YAAgB,oBAClB,EAAiB,GAIrB,YAAyB,CACvB,EAAqB,GACrB,WAAW,IAAM,CACf,EAAqB,IACpB,KAGL,YAA2B,CAjL7B,MAoLI,GAFA,OAAO,iBAAiB,aAAc,GAElC,iBAAa,iBAAiB,GAAS,CACzC,GAAM,GAAyC,GAAW,CACxD,GAAI,CAAC,GAAsB,MAAM,QAAQ,IAAY,EAAQ,OAAS,GACpE,OAAW,KAAS,GAClB,GAAI,EAAM,gBAAkB,EAAM,iBAAkB,aAAa,CAC/D,GAAM,CAAE,MAAO,EAAM,OACf,EAAO,SAAS,cAAc,WAAa,EAAK,MACtD,AAAI,YAAgB,oBAClB,EAAiB,GAEnB,SAOF,EAAK,GAAI,sBAAqB,EAAU,CAC5C,UAAW,EACX,WAAY,qBAEd,OAAW,KAAS,GAAY,iBAAiB,GAC/C,AAAI,YAAiB,cAAe,CAAC,qBAAO,UAAP,cAAgB,SACnD,EAAG,QAAQ,IAMnB,GAAI,CACF,KAAM,KACN,KAAM,KACF,SAAS,MACX,IAEF,UACO,EAAP,CACA,AAAI,YAAa,OACf,QAAQ,MAAM,EAAE,SAEhB,QAAQ,MAAM",
-  "names": []
+  "sourcesContent": ["/**\n * @license\n * Copyright 2022 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * Left Navigation.\n */\nexport const initJumpLinks = async function () {\n  const pagesWithJumpLinks = ['/about'];\n  if (!pagesWithJumpLinks.includes(window.location.pathname)) {\n    // stop the file from doing anything else if the page doesn't have jumplinks\n    return;\n  }\n\n  // these might be generated or not so don't grab references to the elements until actually need them.\n  const titles = 'h2, h3, h4';\n  const nav = '.LeftNav a';\n  // these are always in the dom so we can get them now and throw errors if they're not.\n  const leftNav = document.querySelector('.LeftNav');\n  const siteContent = document.querySelector('.go-Content');\n  let isObserverDisabled = false;\n\n  /**\n   * El function\n   * @example el('h1', {className: 'title'}, 'Welcome to the site');\n   * @example el('ul', {className: 'list'}, el('li', {}, 'Item one'), el('li', {}, 'Item two'), el('li', {}, 'Item three'));\n   * @example el('img', {src: '/url.svg'});\n   */\n  function el(\n    type = '',\n    props: { [key: string]: string } = {},\n    ...children: (HTMLElement | HTMLElement[] | string | undefined)[]\n  ) {\n    // Error, no type declared.\n    if (!type) {\n      throw new Error('Provide `type` to create document element.');\n    }\n\n    // Create element with optional attribute props\n    const docEl = Object.assign(document.createElement(type), props);\n\n    // Children: array containing strings or elements\n    children.forEach(child => {\n      if (typeof child === 'string') {\n        docEl.appendChild(document.createTextNode(child));\n      } else if (Array.isArray(child)) {\n        child.forEach(c => docEl.appendChild(c));\n      } else if (child instanceof HTMLElement) {\n        docEl.appendChild(child);\n      }\n    });\n\n    return docEl;\n  }\n  /**  Build Nav if data hydrate is present. */\n  function buildNav() {\n    return new Promise((resolve, reject) => {\n      let navItems: { id: string; label: string; subnav?: { id: string; label: string }[] }[] = [];\n      let elements: HTMLElement[] = [];\n\n      if (!siteContent || !leftNav) {\n        return reject('.SiteContent not found.');\n      }\n      if (leftNav instanceof HTMLElement && !leftNav?.dataset?.hydrate) {\n        return resolve(true);\n      }\n\n      for (const title of siteContent.querySelectorAll(titles)) {\n        if (title instanceof HTMLElement && !title?.dataset?.ignore) {\n          switch (title.tagName) {\n            case 'H2':\n              navItems = [\n                ...navItems,\n                {\n                  id: title.id,\n                  label: title?.dataset?.title ? title.dataset.title : title.textContent ?? '',\n                },\n              ];\n              break;\n\n            case 'H3':\n            case 'H4':\n              if (!navItems[navItems.length - 1]?.subnav) {\n                navItems[navItems.length - 1].subnav = [\n                  {\n                    id: title.id,\n                    label: title?.dataset?.title ? title.dataset.title : title.textContent ?? '',\n                  },\n                ];\n              } else if (navItems[navItems.length - 1].subnav) {\n                navItems[navItems.length - 1].subnav?.push({\n                  id: title.id,\n                  label: title?.dataset?.title ? title.dataset.title : title.textContent ?? '',\n                });\n              }\n              break;\n          }\n        }\n      }\n\n      for (const navItem of navItems) {\n        const link = el('a', { href: '#' + navItem.id }, el('span', {}, navItem.label));\n        elements = [...elements, link];\n        if (navItem?.subnav) {\n          let subLinks: HTMLElement[] = [];\n          for (const subnavItem of navItem.subnav) {\n            const subItem = el(\n              'li',\n              {},\n              el(\n                'a',\n                { href: '#' + subnavItem.id },\n                el('img', { src: '/static/frontend/about/dot.svg', width: '5', height: '5' }),\n                el('span', {}, subnavItem.label)\n              )\n            );\n            subLinks = [...subLinks, subItem];\n          }\n          const list = el('ul', { className: 'LeftSubnav' }, subLinks);\n          elements = [...elements, list];\n        }\n      }\n\n      elements.forEach(element => leftNav.appendChild(element));\n\n      return resolve(true);\n    });\n  }\n  /**\n   * Set the correct active element.\n   */\n  function setNav() {\n    return new Promise(resolve => {\n      if (!document.querySelectorAll(nav)) return resolve(true);\n      for (const a of document.querySelectorAll(nav)) {\n        if (a instanceof HTMLAnchorElement && a.href === location.href) {\n          setElementActive(a);\n          break;\n        }\n      }\n      resolve(true);\n    });\n  }\n  /** resetNav: removes all .active from nav elements */\n  function resetNav() {\n    return new Promise(resolve => {\n      if (!document.querySelectorAll(nav)) return resolve(true);\n      for (const a of document.querySelectorAll(nav)) {\n        a.classList.remove('active');\n      }\n      resolve(true);\n    });\n  }\n  /** setElementActive: controls resetting nav and highlighting the appropriate nav items */\n  function setElementActive(element: HTMLAnchorElement) {\n    if (element instanceof HTMLAnchorElement) {\n      resetNav().then(() => {\n        element.classList.add('active');\n        const parent = element?.parentNode?.parentNode;\n        if (parent instanceof HTMLElement && parent?.classList?.contains('LeftSubnav')) {\n          parent.previousElementSibling?.classList.add('active');\n        }\n      });\n    }\n  }\n  /** setLinkManually: disables observer and selects the clicked nav item. */\n  function setLinkManually() {\n    delayObserver();\n    const link = document.querySelector('[href=\"' + location.hash + '\"]');\n    if (link instanceof HTMLAnchorElement) {\n      setElementActive(link);\n    }\n  }\n  /** delayObserver: Quick on off switch for intersection observer. */\n  function delayObserver() {\n    isObserverDisabled = true;\n    setTimeout(() => {\n      isObserverDisabled = false;\n    }, 200);\n  }\n  /** observeSections: kicks off observation of titles as well as manual clicks with hashchange */\n  function observeSections() {\n    window.addEventListener('hashchange', setLinkManually);\n\n    if (siteContent?.querySelectorAll(titles)) {\n      const callback: IntersectionObserverCallback = entries => {\n        if (!isObserverDisabled && Array.isArray(entries) && entries.length > 0) {\n          for (const entry of entries) {\n            if (entry.isIntersecting && entry.target instanceof HTMLElement) {\n              const { id } = entry.target;\n              const link = document.querySelector('[href=\"#' + id + '\"]');\n              if (link instanceof HTMLAnchorElement) {\n                setElementActive(link);\n              }\n              break;\n            }\n          }\n        }\n      };\n      // rootMargin is important when multiple sections are in the observable area **on page load**.\n      // they will still be highlighted on scroll because of the root margin.\n      const ob = new IntersectionObserver(callback, {\n        threshold: 0,\n        rootMargin: '0px 0px -50% 0px',\n      });\n      for (const title of siteContent.querySelectorAll(titles)) {\n        if (title instanceof HTMLElement && !title?.dataset?.ignore) {\n          ob.observe(title);\n        }\n      }\n    }\n  }\n\n  try {\n    await buildNav();\n    await setNav();\n    if (location.hash) {\n      delayObserver();\n    }\n    observeSections();\n  } catch (e) {\n    if (e instanceof Error) {\n      console.error(e.message);\n    } else {\n      console.error(e);\n    }\n  }\n};\n"],
+  "mappings": "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",
+  "names": ["initJumpLinks", "titles", "nav", "leftNav", "siteContent", "isObserverDisabled", "el", "type", "props", "children", "docEl", "child", "c", "buildNav", "resolve", "reject", "_a", "_b", "_c", "_d", "_e", "_f", "_g", "_h", "_i", "_j", "navItems", "elements", "title", "navItem", "link", "subLinks", "subnavItem", "subItem", "list", "element", "setNav", "a", "setElementActive", "resetNav", "parent", "setLinkManually", "delayObserver", "observeSections", "callback", "entries", "entry", "id", "ob", "e"]
 }
diff --git a/static/frontend/about/index.ts b/static/frontend/about/index.ts
index cccc8f0..5d676bc 100644
--- a/static/frontend/about/index.ts
+++ b/static/frontend/about/index.ts
@@ -1,4 +1,11 @@
 /**
+ * @license
+ * Copyright 2022 The Go Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+/**
  * Left Navigation.
  */
 export const initJumpLinks = async function () {
diff --git a/static/frontend/frontend.js b/static/frontend/frontend.js
index f346cd6..89c6416 100644
--- a/static/frontend/frontend.js
+++ b/static/frontend/frontend.js
@@ -1,4 +1,4 @@
-function K(){let n=document.querySelector(".js-header");document.querySelectorAll(".js-desktop-menu-hover").forEach(c=>{c.addEventListener("mouseenter",a=>{let u=a.target,s=document.querySelector(".forced-open");s&&s!==c&&(s.blur(),s.classList.remove("forced-open")),u.focus(),u.blur()});let r=a=>{var d,h;let u=a.target,s=u==null?void 0:u.classList.contains("forced-open"),t=a.currentTarget;s?(t.removeEventListener("blur",()=>t.classList.remove("forced-open")),t.classList.remove("forced-open"),t.classList.add("forced-closed"),t.blur(),(d=t==null?void 0:t.parentNode)==null||d.addEventListener("mouseout",()=>{t.classList.remove("forced-closed")})):(t.classList.remove("forced-closed"),t.classList.add("forced-open"),t.focus(),t.addEventListener("blur",()=>t.classList.remove("forced-open")),(h=t==null?void 0:t.parentNode)==null||h.removeEventListener("mouseout",()=>{t.classList.remove("forced-closed")}))};c.addEventListener("click",r)}),document.querySelectorAll(".Header-menuItem").forEach(c=>{c.addEventListener("keyup",r=>{var u;let a=r;a.key==="Escape"&&((u=a.target)==null||u.blur())})});let i=document.querySelectorAll(".js-headerMenuButton");i.forEach(c=>{c.addEventListener("click",r=>{r.preventDefault();let a=n==null?void 0:n.classList.contains("is-active");a?g(n):M(n),c.setAttribute("aria-expanded",a?"true":"false")})});let l=document.querySelector(".js-scrim");l==null||l.addEventListener("click",c=>{c.preventDefault(),document.querySelectorAll(".go-NavigationDrawer-submenuItem.is-active").forEach(a=>g(a)),g(n),i.forEach(a=>{a.setAttribute("aria-expanded",(n==null?void 0:n.classList.contains("is-active"))?"true":"false")})});let m=c=>{if(!c)return[];let r=Array.from(c.querySelectorAll(":scope > .go-NavigationDrawer-nav > .go-NavigationDrawer-list > .go-NavigationDrawer-listItem > a, :scope > .go-NavigationDrawer-nav > .go-NavigationDrawer-list > .go-NavigationDrawer-listItem > .go-Header-socialIcons > a")||[]),a=c.querySelector(".go-NavigationDrawer-header > a");return a&&r.unshift(a),r},p=c=>{if(!!c)return c.classList.contains("go-NavigationDrawer-submenuItem")},g=c=>{var u,s;if(!c)return;let r=m(c);c.classList.remove("is-active");let a=(u=c.closest(".go-NavigationDrawer-listItem"))==null?void 0:u.querySelector(":scope > a");a==null||a.focus(),r==null||r.forEach(t=>t==null?void 0:t.setAttribute("tabindex","-1")),r&&r[0]&&(r[0].removeEventListener("keydown",L(c)),r[r.length-1].removeEventListener("keydown",b(c))),c===n&&i&&((s=i[0])==null||s.focus())},M=c=>{let r=m(c);c.classList.add("is-active"),r.forEach(a=>a.setAttribute("tabindex","0")),r[0].focus(),r[0].addEventListener("keydown",L(c)),r[r.length-1].addEventListener("keydown",b(c))},L=c=>r=>{r.key==="Tab"&&r.shiftKey&&(r.preventDefault(),g(c))},b=c=>r=>{r.key==="Tab"&&!r.shiftKey&&(r.preventDefault(),g(c))},w=c=>{var u;let r=p(c),a=m(c);c.addEventListener("keyup",s=>{s.key==="Escape"&&g(c)}),a.forEach(s=>{let t=s.closest("li");if(t&&t.classList.contains("js-mobile-subnav-trigger")){let d=t.querySelector(".go-NavigationDrawer-submenuItem");s.addEventListener("click",()=>{M(d)})}}),r&&(g(c),(u=c==null?void 0:c.querySelector(".go-NavigationDrawer-header"))==null||u.addEventListener("click",s=>{s.preventDefault(),g(c)}))};document.querySelectorAll(".go-NavigationDrawer").forEach(c=>w(c)),g(n)}function P(){let n=document.querySelector(".js-searchForm"),e=document.querySelector(".js-expandSearch"),o=n==null?void 0:n.querySelector("input"),i=document.querySelector(".js-headerLogo"),l=document.querySelector(".js-headerMenuButton");e==null||e.addEventListener("click",()=>{n==null||n.classList.add("go-SearchForm--expanded"),i==null||i.classList.add("go-Header-logo--hidden"),l==null||l.classList.add("go-Header-navOpen--hidden"),o==null||o.focus()}),document==null||document.addEventListener("click",m=>{(n==null?void 0:n.contains(m.target))||(n==null||n.classList.remove("go-SearchForm--expanded"),i==null||i.classList.remove("go-Header-logo--hidden"),l==null||l.classList.remove("go-Header-navOpen--hidden"))})}var x=class{constructor(e){this.el=e;this.setActive=e=>{this.activeIndex=(e+this.slides.length)%this.slides.length,this.el.setAttribute("data-slide-index",String(this.activeIndex));for(let o of this.dots)o.classList.remove("go-Carousel-dot--active");this.dots[this.activeIndex].classList.add("go-Carousel-dot--active");for(let o of this.slides)o.setAttribute("aria-hidden","true");this.slides[this.activeIndex].removeAttribute("aria-hidden"),this.liveRegion.textContent="Slide "+(this.activeIndex+1)+" of "+this.slides.length};var o;this.slides=Array.from(e.querySelectorAll(".go-Carousel-slide")),this.dots=[],this.liveRegion=document.createElement("div"),this.activeIndex=Number((o=e.getAttribute("data-slide-index"))!=null?o:0),this.initSlides(),this.initArrows(),this.initDots(),this.initLiveRegion()}initSlides(){for(let[e,o]of this.slides.entries())e!==this.activeIndex&&o.setAttribute("aria-hidden","true")}initArrows(){var o,i;let e=document.createElement("ul");e.classList.add("go-Carousel-arrows"),e.innerHTML=`
+function P(){let n=document.querySelector(".js-header");document.querySelectorAll(".js-desktop-menu-hover").forEach(c=>{c.addEventListener("mouseenter",a=>{let u=a.target,s=document.querySelector(".forced-open");s&&s!==c&&(s.blur(),s.classList.remove("forced-open")),u.focus(),u.blur()});let r=a=>{var d,h;let u=a.target,s=u==null?void 0:u.classList.contains("forced-open"),t=a.currentTarget;s?(t.removeEventListener("blur",()=>t.classList.remove("forced-open")),t.classList.remove("forced-open"),t.classList.add("forced-closed"),t.blur(),(d=t==null?void 0:t.parentNode)==null||d.addEventListener("mouseout",()=>{t.classList.remove("forced-closed")})):(t.classList.remove("forced-closed"),t.classList.add("forced-open"),t.focus(),t.addEventListener("blur",()=>t.classList.remove("forced-open")),(h=t==null?void 0:t.parentNode)==null||h.removeEventListener("mouseout",()=>{t.classList.remove("forced-closed")}))};c.addEventListener("click",r)}),document.querySelectorAll(".Header-menuItem").forEach(c=>{c.addEventListener("keyup",r=>{var u;let a=r;a.key==="Escape"&&((u=a.target)==null||u.blur())})});let i=document.querySelectorAll(".js-headerMenuButton");i.forEach(c=>{c.addEventListener("click",r=>{r.preventDefault();let a=n==null?void 0:n.classList.contains("is-active");a?g(n):w(n),c.setAttribute("aria-expanded",a?"true":"false")})});let l=document.querySelector(".js-scrim");l==null||l.addEventListener("click",c=>{c.preventDefault(),document.querySelectorAll(".go-NavigationDrawer-submenuItem.is-active").forEach(a=>g(a)),g(n),i.forEach(a=>{a.setAttribute("aria-expanded",n!=null&&n.classList.contains("is-active")?"true":"false")})});let m=c=>{if(!c)return[];let r=Array.from(c.querySelectorAll(":scope > .go-NavigationDrawer-nav > .go-NavigationDrawer-list > .go-NavigationDrawer-listItem > a, :scope > .go-NavigationDrawer-nav > .go-NavigationDrawer-list > .go-NavigationDrawer-listItem > .go-Header-socialIcons > a")||[]),a=c.querySelector(".go-NavigationDrawer-header > a");return a&&r.unshift(a),r},p=c=>{if(!!c)return c.classList.contains("go-NavigationDrawer-submenuItem")},g=c=>{var u,s;if(!c)return;let r=m(c);c.classList.remove("is-active");let a=(u=c.closest(".go-NavigationDrawer-listItem"))==null?void 0:u.querySelector(":scope > a");a==null||a.focus(),r==null||r.forEach(t=>t==null?void 0:t.setAttribute("tabindex","-1")),r&&r[0]&&(r[0].removeEventListener("keydown",L(c)),r[r.length-1].removeEventListener("keydown",b(c))),c===n&&i&&((s=i[0])==null||s.focus())},w=c=>{let r=m(c);c.classList.add("is-active"),r.forEach(a=>a.setAttribute("tabindex","0")),r[0].focus(),r[0].addEventListener("keydown",L(c)),r[r.length-1].addEventListener("keydown",b(c))},L=c=>r=>{r.key==="Tab"&&r.shiftKey&&(r.preventDefault(),g(c))},b=c=>r=>{r.key==="Tab"&&!r.shiftKey&&(r.preventDefault(),g(c))},M=c=>{var u;let r=p(c),a=m(c);c.addEventListener("keyup",s=>{s.key==="Escape"&&g(c)}),a.forEach(s=>{let t=s.closest("li");if(t&&t.classList.contains("js-mobile-subnav-trigger")){let d=t.querySelector(".go-NavigationDrawer-submenuItem");s.addEventListener("click",()=>{w(d)})}}),r&&(g(c),(u=c==null?void 0:c.querySelector(".go-NavigationDrawer-header"))==null||u.addEventListener("click",s=>{s.preventDefault(),g(c)}))};document.querySelectorAll(".go-NavigationDrawer").forEach(c=>M(c)),g(n)}function U(){let n=document.querySelector(".js-searchForm"),e=document.querySelector(".js-expandSearch"),o=n==null?void 0:n.querySelector("input"),i=document.querySelector(".js-headerLogo"),l=document.querySelector(".js-headerMenuButton");e==null||e.addEventListener("click",()=>{n==null||n.classList.add("go-SearchForm--expanded"),i==null||i.classList.add("go-Header-logo--hidden"),l==null||l.classList.add("go-Header-navOpen--hidden"),o==null||o.focus()}),document==null||document.addEventListener("click",m=>{n!=null&&n.contains(m.target)||(n==null||n.classList.remove("go-SearchForm--expanded"),i==null||i.classList.remove("go-Header-logo--hidden"),l==null||l.classList.remove("go-Header-navOpen--hidden"))})}var k=class{constructor(e){this.el=e;this.setActive=e=>{this.activeIndex=(e+this.slides.length)%this.slides.length,this.el.setAttribute("data-slide-index",String(this.activeIndex));for(let o of this.dots)o.classList.remove("go-Carousel-dot--active");this.dots[this.activeIndex].classList.add("go-Carousel-dot--active");for(let o of this.slides)o.setAttribute("aria-hidden","true");this.slides[this.activeIndex].removeAttribute("aria-hidden"),this.liveRegion.textContent="Slide "+(this.activeIndex+1)+" of "+this.slides.length};var o;this.slides=Array.from(e.querySelectorAll(".go-Carousel-slide")),this.dots=[],this.liveRegion=document.createElement("div"),this.activeIndex=Number((o=e.getAttribute("data-slide-index"))!=null?o:0),this.initSlides(),this.initArrows(),this.initDots(),this.initLiveRegion()}initSlides(){for(let[e,o]of this.slides.entries())e!==this.activeIndex&&o.setAttribute("aria-hidden","true")}initArrows(){var o,i;let e=document.createElement("ul");e.classList.add("go-Carousel-arrows"),e.innerHTML=`
       <li>
         <button class="go-Carousel-prevSlide" aria-label="Go to previous slide">
           <img class="go-Icon" height="24" width="24" src="/static/shared/icon/arrow_left_gm_grey_24dp.svg" alt="">
@@ -9,7 +9,7 @@
           <img class="go-Icon" height="24" width="24" src="/static/shared/icon/arrow_right_gm_grey_24dp.svg" alt="">
         </button>
       </li>
-    `,(o=e.querySelector(".go-Carousel-prevSlide"))==null||o.addEventListener("click",()=>this.setActive(this.activeIndex-1)),(i=e.querySelector(".go-Carousel-nextSlide"))==null||i.addEventListener("click",()=>this.setActive(this.activeIndex+1)),this.el.append(e)}initDots(){let e=document.createElement("ul");e.classList.add("go-Carousel-dots");for(let o=0;o<this.slides.length;o++){let i=document.createElement("li"),l=document.createElement("button");l.classList.add("go-Carousel-dot"),o===this.activeIndex&&l.classList.add("go-Carousel-dot--active"),l.innerHTML=`<span class="go-Carousel-obscured">Slide ${o+1}</span>`,l.addEventListener("click",()=>this.setActive(o)),i.append(l),e.append(i),this.dots.push(l)}this.el.append(e)}initLiveRegion(){this.liveRegion.setAttribute("aria-live","polite"),this.liveRegion.setAttribute("aria-atomic","true"),this.liveRegion.setAttribute("class","go-Carousel-obscured"),this.liveRegion.textContent=`Slide ${this.activeIndex+1} of ${this.slides.length}`,this.el.appendChild(this.liveRegion)}};var C=class{constructor(e){this.el=e;var o,i,l,m,p;this.data=(o=e.dataset.toCopy)!=null?o:e.innerText,!this.data&&((i=e.parentElement)==null?void 0:i.classList.contains("go-InputGroup"))&&(this.data=(p=this.data||((m=(l=e.parentElement)==null?void 0:l.querySelector("input"))==null?void 0:m.value))!=null?p:""),e.addEventListener("click",g=>this.handleCopyClick(g))}handleCopyClick(e){e.preventDefault();let o=1e3;if(!navigator.clipboard){this.showTooltipText("Unable to copy",o);return}navigator.clipboard.writeText(this.data).then(()=>{this.showTooltipText("Copied!",o)}).catch(()=>{this.showTooltipText("Unable to copy",o)})}showTooltipText(e,o){this.el.setAttribute("data-tooltip",e),setTimeout(()=>this.el.setAttribute("data-tooltip",""),o)}};var q=class{constructor(e){this.el=e;document.addEventListener("click",o=>{this.el.contains(o.target)||this.el.removeAttribute("open")})}};var I=class{constructor(e){this.el=e;this.el.addEventListener("change",o=>{let i=o.target,l=i.value;i.value.startsWith("/")||(l="/"+l),window.location.href=l})}};var N=class{constructor(e){this.el=e;window.dialogPolyfill&&window.dialogPolyfill.registerDialog(e),this.init()}init(){let e=document.querySelector(`[aria-controls="${this.el.id}"]`);e&&e.addEventListener("click",()=>{var o;this.el.showModal?this.el.showModal():this.el.setAttribute("opened","true"),(o=this.el.querySelector("input"))==null||o.focus()});for(let o of this.el.querySelectorAll("[data-modal-close]"))o.addEventListener("click",()=>{this.el.close?this.el.close():this.el.removeAttribute("opened")})}};function k(n,e,o,i){var l;(l=window.dataLayer)!=null||(window.dataLayer=[]),typeof n=="string"?window.dataLayer.push({event:n,event_category:e,event_action:o,event_label:i}):window.dataLayer.push(n)}function U(n){var e;(e=window.dataLayer)!=null||(window.dataLayer=[]),window.dataLayer.push(n)}var W=class{constructor(){this.handlers={},document.addEventListener("keydown",e=>this.handleKeyPress(e))}on(e,o,i,l){var m,p;return(p=(m=this.handlers)[e])!=null||(m[e]=new Set),this.handlers[e].add({description:o,callback:i,...l}),this}handleKeyPress(e){var o;for(let i of(o=this.handlers[e.key.toLowerCase()])!=null?o:new Set){if(i.target&&i.target!==e.target)return;let l=e.target;if(!i.target&&((l==null?void 0:l.tagName)==="INPUT"||(l==null?void 0:l.tagName)==="SELECT"||(l==null?void 0:l.tagName)==="TEXTAREA")||(l==null?void 0:l.isContentEditable)||i.withMeta&&!(e.ctrlKey||e.metaKey)||!i.withMeta&&(e.ctrlKey||e.metaKey))return;k("keypress","hotkeys",`${e.key} pressed`,i.description),i.callback(e)}}},H=new W;function $(){var u;let n=document.querySelector(".JumpDialog"),e=n==null?void 0:n.querySelector(".JumpDialog-body"),o=n==null?void 0:n.querySelector(".JumpDialog-list"),i=n==null?void 0:n.querySelector(".JumpDialog-input"),l=document.querySelector(".js-documentation"),m;function p(){let s=[];if(!!l){for(let t of l.querySelectorAll("[data-kind]"))s.push(g(t));for(let t of s)t.link.addEventListener("click",function(){n==null||n.close()});return s.sort(function(t,d){return t.lower.localeCompare(d.lower)}),s}}function g(s){var E;let t=document.createElement("a"),d=s.getAttribute("id");t.setAttribute("href","#"+d),t.setAttribute("tabindex","-1"),t.setAttribute("data-gtmc","jump to link");let h=s.getAttribute("data-kind");return{link:t,name:d!=null?d:"",kind:h!=null?h:"",lower:(E=d==null?void 0:d.toLowerCase())!=null?E:""}}let M,L=-1;function b(s){for(M=s,m||(m=p()),w(-1);o==null?void 0:o.firstChild;)o.firstChild.remove();if(s){let t=s.toLowerCase(),d=[],h=[],E=[],S=(v,y,T)=>v.name.substring(0,y)+"<b>"+v.name.substring(y,T)+"</b>"+v.name.substring(T);for(let v of m!=null?m:[]){let y=v.name.toLowerCase();if(y===t)v.link.innerHTML=S(v,0,v.name.length),d.push(v);else if(y.startsWith(t))v.link.innerHTML=S(v,0,s.length),h.push(v);else{let T=y.indexOf(t);T>-1&&(v.link.innerHTML=S(v,T,T+s.length),E.push(v))}}for(let v of d.concat(h).concat(E))o==null||o.appendChild(v.link)}else{if(!m||m.length===0){let t=document.createElement("i");t.innerHTML="There are no symbols on this page.",o==null||o.appendChild(t)}for(let t of m!=null?m:[])t.link.innerHTML=t.name+" <i>"+t.kind+"</i>",o==null||o.appendChild(t.link)}e&&(e.scrollTop=0),(m==null?void 0:m.length)&&o&&o.children.length>0&&w(0)}function w(s){let t=o==null?void 0:o.children;if(!(!t||!e)){if(L>=0&&t[L].classList.remove("JumpDialog-active"),s>=t.length&&(s=t.length-1),s>=0){t[s].classList.add("JumpDialog-active");let d=t[s].offsetTop-t[0].offsetTop,h=d+t[s].clientHeight;d<e.scrollTop?e.scrollTop=d:h>e.scrollTop+e.clientHeight&&(e.scrollTop=h-e.clientHeight)}L=s}}function c(s){if(L<0)return;let t=L+s;t<0&&(t=0),w(t)}i==null||i.addEventListener("keyup",function(){i.value.toUpperCase()!=M.toUpperCase()&&b(i.value)}),i==null||i.addEventListener("keydown",function(s){let t=38,d=40,h=13;switch(s.which){case t:c(-1),s.preventDefault();break;case d:c(1),s.preventDefault();break;case h:L>=0&&o&&(o.children[L].click(),s.preventDefault());break}});let r=document.querySelector(".ShortcutsDialog");H.on("f","open jump to modal",s=>{var t;(n==null?void 0:n.open)||(r==null?void 0:r.open)||(s.preventDefault(),i&&(i.value=""),(t=n==null?void 0:n.showModal)==null||t.call(n),i==null||i.focus(),b(""))}).on("?","open shortcuts modal",()=>{var s;(n==null?void 0:n.open)||(r==null?void 0:r.open)||(s=r==null?void 0:r.showModal)==null||s.call(r)});let a=document.querySelector(".js-jumpToInput");a&&a.addEventListener("click",()=>{var s;i&&(i.value=""),b(""),!((n==null?void 0:n.open)||(r==null?void 0:r.open))&&((s=n==null?void 0:n.showModal)==null||s.call(n),i==null||i.focus())}),(u=document.querySelector(".js-openShortcuts"))==null||u.addEventListener("click",()=>{var s;(s=r==null?void 0:r.showModal)==null||s.call(r)})}var G=async function(){if(!["/about"].includes(window.location.pathname))return;let e="h2, h3, h4",o=".LeftNav a",i=document.querySelector(".LeftNav"),l=document.querySelector(".go-Content"),m=!1;function p(a="",u={},...s){if(!a)throw new Error("Provide `type` to create document element.");let t=Object.assign(document.createElement(a),u);return s.forEach(d=>{typeof d=="string"?t.appendChild(document.createTextNode(d)):Array.isArray(d)?d.forEach(h=>t.appendChild(h)):d instanceof HTMLElement&&t.appendChild(d)}),t}function g(){return new Promise((a,u)=>{var d,h,E,S,v,y,T,O,J,R;let s=[],t=[];if(!l||!i)return u(".SiteContent not found.");if(i instanceof HTMLElement&&!((d=i==null?void 0:i.dataset)==null?void 0:d.hydrate))return a(!0);for(let f of l.querySelectorAll(e))if(f instanceof HTMLElement&&!((h=f==null?void 0:f.dataset)==null?void 0:h.ignore))switch(f.tagName){case"H2":s=[...s,{id:f.id,label:((E=f==null?void 0:f.dataset)==null?void 0:E.title)?f.dataset.title:(S=f.textContent)!=null?S:""}];break;case"H3":case"H4":((v=s[s.length-1])==null?void 0:v.subnav)?s[s.length-1].subnav&&((R=s[s.length-1].subnav)==null||R.push({id:f.id,label:((O=f==null?void 0:f.dataset)==null?void 0:O.title)?f.dataset.title:(J=f.textContent)!=null?J:""})):s[s.length-1].subnav=[{id:f.id,label:((y=f==null?void 0:f.dataset)==null?void 0:y.title)?f.dataset.title:(T=f.textContent)!=null?T:""}];break}for(let f of s){let V=p("a",{href:"#"+f.id},p("span",{},f.label));if(t=[...t,V],f==null?void 0:f.subnav){let A=[];for(let _ of f.subnav){let z=p("li",{},p("a",{href:"#"+_.id},p("img",{src:"/static/frontend/about/dot.svg",width:"5",height:"5"}),p("span",{},_.label)));A=[...A,z]}let X=p("ul",{className:"LeftSubnav"},A);t=[...t,X]}}return t.forEach(f=>i.appendChild(f)),a(!0)})}function M(){return new Promise(a=>{if(!document.querySelectorAll(o))return a(!0);for(let u of document.querySelectorAll(o))if(u instanceof HTMLAnchorElement&&u.href===location.href){b(u);break}a(!0)})}function L(){return new Promise(a=>{if(!document.querySelectorAll(o))return a(!0);for(let u of document.querySelectorAll(o))u.classList.remove("active");a(!0)})}function b(a){a instanceof HTMLAnchorElement&&L().then(()=>{var s,t,d;a.classList.add("active");let u=(s=a==null?void 0:a.parentNode)==null?void 0:s.parentNode;u instanceof HTMLElement&&((t=u==null?void 0:u.classList)==null?void 0:t.contains("LeftSubnav"))&&((d=u.previousElementSibling)==null||d.classList.add("active"))})}function w(){c();let a=document.querySelector('[href="'+location.hash+'"]');a instanceof HTMLAnchorElement&&b(a)}function c(){m=!0,setTimeout(()=>{m=!1},200)}function r(){var a;if(window.addEventListener("hashchange",w),l==null?void 0:l.querySelectorAll(e)){let u=t=>{if(!m&&Array.isArray(t)&&t.length>0){for(let d of t)if(d.isIntersecting&&d.target instanceof HTMLElement){let{id:h}=d.target,E=document.querySelector('[href="#'+h+'"]');E instanceof HTMLAnchorElement&&b(E);break}}},s=new IntersectionObserver(u,{threshold:0,rootMargin:"0px 0px -50% 0px"});for(let t of l.querySelectorAll(e))t instanceof HTMLElement&&!((a=t==null?void 0:t.dataset)==null?void 0:a.ignore)&&s.observe(t)}}try{await g(),await M(),location.hash&&c(),r()}catch(a){a instanceof Error?console.error(a.message):console.error(a)}};window.addEventListener("load",()=>{var n;for(let e of document.querySelectorAll(".js-clipboard"))new C(e);for(let e of document.querySelectorAll(".js-modal"))new N(e);for(let e of document.querySelectorAll(".js-tooltip"))new q(e);for(let e of document.querySelectorAll(".js-selectNav"))new I(e);for(let e of document.querySelectorAll(".js-carousel"))new x(e);for(let e of document.querySelectorAll(".js-toggleTheme"))e.addEventListener("click",()=>{Y()});((n=document.querySelector(".js-gtmID"))==null?void 0:n.dataset.gtmid)&&window.dataLayer?U(function(){B()}):B(),K(),P(),$(),G()});H.on("/","focus search",n=>{let e=Array.from(document.querySelectorAll(".js-searchFocus")).pop();e&&!window.navigator.userAgent.includes("Firefox")&&(n.preventDefault(),e.focus())});H.on("y","set canonical url",()=>{var e;let n=(e=document.querySelector(".js-canonicalURLPath"))==null?void 0:e.dataset.canonicalUrlPath;if(n&&n!==""){let o=window.location.hash;o&&(n+=o),window.history.replaceState(null,"",n)}});(function(){k({"gtm.start":new Date().getTime(),event:"gtm.js"})})();function B(){let n=new URLSearchParams(window.location.search),e=n.get("utm_source");if(e!=="gopls"&&e!=="godoc"&&e!=="pkggodev")return;let o=new URL(window.location.href);n.delete("utm_source"),o.search=n.toString(),window.history.replaceState(null,"",o.toString())}function Y(){let n="dark",e=document.documentElement.getAttribute("data-theme");e==="dark"?n="light":e==="light"&&(n="auto");let o="";location.hostname.endsWith("go.dev")&&(o="domain=.go.dev;"),document.documentElement.setAttribute("data-theme",n),document.cookie=`prefers-color-scheme=${n};${o}path=/;max-age=31536000;`}
+    `,(o=e.querySelector(".go-Carousel-prevSlide"))==null||o.addEventListener("click",()=>this.setActive(this.activeIndex-1)),(i=e.querySelector(".go-Carousel-nextSlide"))==null||i.addEventListener("click",()=>this.setActive(this.activeIndex+1)),this.el.append(e)}initDots(){let e=document.createElement("ul");e.classList.add("go-Carousel-dots");for(let o=0;o<this.slides.length;o++){let i=document.createElement("li"),l=document.createElement("button");l.classList.add("go-Carousel-dot"),o===this.activeIndex&&l.classList.add("go-Carousel-dot--active"),l.innerHTML=`<span class="go-Carousel-obscured">Slide ${o+1}</span>`,l.addEventListener("click",()=>this.setActive(o)),i.append(l),e.append(i),this.dots.push(l)}this.el.append(e)}initLiveRegion(){this.liveRegion.setAttribute("aria-live","polite"),this.liveRegion.setAttribute("aria-atomic","true"),this.liveRegion.setAttribute("class","go-Carousel-obscured"),this.liveRegion.textContent=`Slide ${this.activeIndex+1} of ${this.slides.length}`,this.el.appendChild(this.liveRegion)}};var A=class{constructor(e){this.el=e;var o,i,l,m,p;this.data=(o=e.dataset.toCopy)!=null?o:e.innerText,!this.data&&((i=e.parentElement)==null?void 0:i.classList.contains("go-InputGroup"))&&(this.data=(p=this.data||((m=(l=e.parentElement)==null?void 0:l.querySelector("input"))==null?void 0:m.value))!=null?p:""),e.addEventListener("click",g=>this.handleCopyClick(g))}handleCopyClick(e){e.preventDefault();let o=1e3;if(!navigator.clipboard){this.showTooltipText("Unable to copy",o);return}navigator.clipboard.writeText(this.data).then(()=>{this.showTooltipText("Copied!",o)}).catch(()=>{this.showTooltipText("Unable to copy",o)})}showTooltipText(e,o){this.el.setAttribute("data-tooltip",e),setTimeout(()=>this.el.setAttribute("data-tooltip",""),o)}};var x=class{constructor(e){this.el=e;document.addEventListener("click",o=>{this.el.contains(o.target)||this.el.removeAttribute("open")})}};var q=class{constructor(e){this.el=e;this.el.addEventListener("change",o=>{let i=o.target,l=i.value;i.value.startsWith("/")||(l="/"+l),window.location.href=l})}};var C=class{constructor(e){this.el=e;window.dialogPolyfill&&window.dialogPolyfill.registerDialog(e),this.init()}init(){let e=document.querySelector(`[aria-controls="${this.el.id}"]`);e&&e.addEventListener("click",()=>{var o;this.el.showModal?this.el.showModal():this.el.setAttribute("opened","true"),(o=this.el.querySelector("input"))==null||o.focus()});for(let o of this.el.querySelectorAll("[data-modal-close]"))o.addEventListener("click",()=>{this.el.close?this.el.close():this.el.removeAttribute("opened")})}};function I(n,e,o,i){var l;(l=window.dataLayer)!=null||(window.dataLayer=[]),typeof n=="string"?window.dataLayer.push({event:n,event_category:e,event_action:o,event_label:i}):window.dataLayer.push(n)}function W(n){var e;(e=window.dataLayer)!=null||(window.dataLayer=[]),window.dataLayer.push(n)}var O=class{constructor(){this.handlers={},document.addEventListener("keydown",e=>this.handleKeyPress(e))}on(e,o,i,l){var m,p;return(p=(m=this.handlers)[e])!=null||(m[e]=new Set),this.handlers[e].add({description:o,callback:i,...l}),this}handleKeyPress(e){var o;for(let i of(o=this.handlers[e.key.toLowerCase()])!=null?o:new Set){if(i.target&&i.target!==e.target)return;let l=e.target;if(!i.target&&((l==null?void 0:l.tagName)==="INPUT"||(l==null?void 0:l.tagName)==="SELECT"||(l==null?void 0:l.tagName)==="TEXTAREA")||l!=null&&l.isContentEditable||i.withMeta&&!(e.ctrlKey||e.metaKey)||!i.withMeta&&(e.ctrlKey||e.metaKey))return;I("keypress","hotkeys",`${e.key} pressed`,i.description),i.callback(e)}}},H=new O;function $(){var u;let n=document.querySelector(".JumpDialog"),e=n==null?void 0:n.querySelector(".JumpDialog-body"),o=n==null?void 0:n.querySelector(".JumpDialog-list"),i=n==null?void 0:n.querySelector(".JumpDialog-input"),l=document.querySelector(".js-documentation"),m;function p(){let s=[];if(!!l){for(let t of l.querySelectorAll("[data-kind]"))s.push(g(t));for(let t of s)t.link.addEventListener("click",function(){n==null||n.close()});return s.sort(function(t,d){return t.lower.localeCompare(d.lower)}),s}}function g(s){var E;let t=document.createElement("a"),d=s.getAttribute("id");t.setAttribute("href","#"+d),t.setAttribute("tabindex","-1"),t.setAttribute("data-gtmc","jump to link");let h=s.getAttribute("data-kind");return{link:t,name:d!=null?d:"",kind:h!=null?h:"",lower:(E=d==null?void 0:d.toLowerCase())!=null?E:""}}let w,L=-1;function b(s){for(w=s,m||(m=p()),M(-1);o!=null&&o.firstChild;)o.firstChild.remove();if(s){let t=s.toLowerCase(),d=[],h=[],E=[],S=(v,y,T)=>v.name.substring(0,y)+"<b>"+v.name.substring(y,T)+"</b>"+v.name.substring(T);for(let v of m!=null?m:[]){let y=v.name.toLowerCase();if(y===t)v.link.innerHTML=S(v,0,v.name.length),d.push(v);else if(y.startsWith(t))v.link.innerHTML=S(v,0,s.length),h.push(v);else{let T=y.indexOf(t);T>-1&&(v.link.innerHTML=S(v,T,T+s.length),E.push(v))}}for(let v of d.concat(h).concat(E))o==null||o.appendChild(v.link)}else{if(!m||m.length===0){let t=document.createElement("i");t.innerHTML="There are no symbols on this page.",o==null||o.appendChild(t)}for(let t of m!=null?m:[])t.link.innerHTML=t.name+" <i>"+t.kind+"</i>",o==null||o.appendChild(t.link)}e&&(e.scrollTop=0),(m==null?void 0:m.length)&&o&&o.children.length>0&&M(0)}function M(s){let t=o==null?void 0:o.children;if(!(!t||!e)){if(L>=0&&t[L].classList.remove("JumpDialog-active"),s>=t.length&&(s=t.length-1),s>=0){t[s].classList.add("JumpDialog-active");let d=t[s].offsetTop-t[0].offsetTop,h=d+t[s].clientHeight;d<e.scrollTop?e.scrollTop=d:h>e.scrollTop+e.clientHeight&&(e.scrollTop=h-e.clientHeight)}L=s}}function c(s){if(L<0)return;let t=L+s;t<0&&(t=0),M(t)}i==null||i.addEventListener("keyup",function(){i.value.toUpperCase()!=w.toUpperCase()&&b(i.value)}),i==null||i.addEventListener("keydown",function(s){switch(s.which){case 38:c(-1),s.preventDefault();break;case 40:c(1),s.preventDefault();break;case 13:L>=0&&o&&(o.children[L].click(),s.preventDefault());break}});let r=document.querySelector(".ShortcutsDialog");H.on("f","open jump to modal",s=>{var t;(n==null?void 0:n.open)||(r==null?void 0:r.open)||(s.preventDefault(),i&&(i.value=""),(t=n==null?void 0:n.showModal)==null||t.call(n),i==null||i.focus(),b(""))}).on("?","open shortcuts modal",()=>{var s;(n==null?void 0:n.open)||(r==null?void 0:r.open)||(s=r==null?void 0:r.showModal)==null||s.call(r)});let a=document.querySelector(".js-jumpToInput");a&&a.addEventListener("click",()=>{var s;i&&(i.value=""),b(""),!((n==null?void 0:n.open)||(r==null?void 0:r.open))&&((s=n==null?void 0:n.showModal)==null||s.call(n),i==null||i.focus())}),(u=document.querySelector(".js-openShortcuts"))==null||u.addEventListener("click",()=>{var s;(s=r==null?void 0:r.showModal)==null||s.call(r)})}var G=async function(){if(!["/about"].includes(window.location.pathname))return;let e="h2, h3, h4",o=".LeftNav a",i=document.querySelector(".LeftNav"),l=document.querySelector(".go-Content"),m=!1;function p(a="",u={},...s){if(!a)throw new Error("Provide `type` to create document element.");let t=Object.assign(document.createElement(a),u);return s.forEach(d=>{typeof d=="string"?t.appendChild(document.createTextNode(d)):Array.isArray(d)?d.forEach(h=>t.appendChild(h)):d instanceof HTMLElement&&t.appendChild(d)}),t}function g(){return new Promise((a,u)=>{var d,h,E,S,v,y,T,J,R,_;let s=[],t=[];if(!l||!i)return u(".SiteContent not found.");if(i instanceof HTMLElement&&!((d=i==null?void 0:i.dataset)!=null&&d.hydrate))return a(!0);for(let f of l.querySelectorAll(e))if(f instanceof HTMLElement&&!((h=f==null?void 0:f.dataset)!=null&&h.ignore))switch(f.tagName){case"H2":s=[...s,{id:f.id,label:(E=f==null?void 0:f.dataset)!=null&&E.title?f.dataset.title:(S=f.textContent)!=null?S:""}];break;case"H3":case"H4":(v=s[s.length-1])!=null&&v.subnav?s[s.length-1].subnav&&((_=s[s.length-1].subnav)==null||_.push({id:f.id,label:(J=f==null?void 0:f.dataset)!=null&&J.title?f.dataset.title:(R=f.textContent)!=null?R:""})):s[s.length-1].subnav=[{id:f.id,label:(y=f==null?void 0:f.dataset)!=null&&y.title?f.dataset.title:(T=f.textContent)!=null?T:""}];break}for(let f of s){let V=p("a",{href:"#"+f.id},p("span",{},f.label));if(t=[...t,V],f!=null&&f.subnav){let N=[];for(let K of f.subnav){let z=p("li",{},p("a",{href:"#"+K.id},p("img",{src:"/static/frontend/about/dot.svg",width:"5",height:"5"}),p("span",{},K.label)));N=[...N,z]}let X=p("ul",{className:"LeftSubnav"},N);t=[...t,X]}}return t.forEach(f=>i.appendChild(f)),a(!0)})}function w(){return new Promise(a=>{if(!document.querySelectorAll(o))return a(!0);for(let u of document.querySelectorAll(o))if(u instanceof HTMLAnchorElement&&u.href===location.href){b(u);break}a(!0)})}function L(){return new Promise(a=>{if(!document.querySelectorAll(o))return a(!0);for(let u of document.querySelectorAll(o))u.classList.remove("active");a(!0)})}function b(a){a instanceof HTMLAnchorElement&&L().then(()=>{var s,t,d;a.classList.add("active");let u=(s=a==null?void 0:a.parentNode)==null?void 0:s.parentNode;u instanceof HTMLElement&&((t=u==null?void 0:u.classList)==null?void 0:t.contains("LeftSubnav"))&&((d=u.previousElementSibling)==null||d.classList.add("active"))})}function M(){c();let a=document.querySelector('[href="'+location.hash+'"]');a instanceof HTMLAnchorElement&&b(a)}function c(){m=!0,setTimeout(()=>{m=!1},200)}function r(){var a;if(window.addEventListener("hashchange",M),l!=null&&l.querySelectorAll(e)){let u=t=>{if(!m&&Array.isArray(t)&&t.length>0){for(let d of t)if(d.isIntersecting&&d.target instanceof HTMLElement){let{id:h}=d.target,E=document.querySelector('[href="#'+h+'"]');E instanceof HTMLAnchorElement&&b(E);break}}},s=new IntersectionObserver(u,{threshold:0,rootMargin:"0px 0px -50% 0px"});for(let t of l.querySelectorAll(e))t instanceof HTMLElement&&!((a=t==null?void 0:t.dataset)!=null&&a.ignore)&&s.observe(t)}}try{await g(),await w(),location.hash&&c(),r()}catch(a){a instanceof Error?console.error(a.message):console.error(a)}};window.addEventListener("load",()=>{var n;for(let e of document.querySelectorAll(".js-clipboard"))new A(e);for(let e of document.querySelectorAll(".js-modal"))new C(e);for(let e of document.querySelectorAll(".js-tooltip"))new x(e);for(let e of document.querySelectorAll(".js-selectNav"))new q(e);for(let e of document.querySelectorAll(".js-carousel"))new k(e);for(let e of document.querySelectorAll(".js-toggleTheme"))e.addEventListener("click",()=>{Y()});((n=document.querySelector(".js-gtmID"))==null?void 0:n.dataset.gtmid)&&window.dataLayer?W(function(){B()}):B(),P(),U(),$(),G()});H.on("/","focus search",n=>{let e=Array.from(document.querySelectorAll(".js-searchFocus")).pop();e&&!window.navigator.userAgent.includes("Firefox")&&(n.preventDefault(),e.focus())});H.on("y","set canonical url",()=>{var e;let n=(e=document.querySelector(".js-canonicalURLPath"))==null?void 0:e.dataset.canonicalUrlPath;if(n&&n!==""){let o=window.location.hash;o&&(n+=o),window.history.replaceState(null,"",n)}});(function(){I({"gtm.start":new Date().getTime(),event:"gtm.js"})})();function B(){let n=new URLSearchParams(window.location.search),e=n.get("utm_source");if(e!=="gopls"&&e!=="godoc"&&e!=="pkggodev")return;let o=new URL(window.location.href);n.delete("utm_source"),o.search=n.toString(),window.history.replaceState(null,"",o.toString())}function Y(){let n="dark",e=document.documentElement.getAttribute("data-theme");e==="dark"?n="light":e==="light"&&(n="auto");let o="";location.hostname.endsWith("go.dev")&&(o="domain=.go.dev;"),document.documentElement.setAttribute("data-theme",n),document.cookie=`prefers-color-scheme=${n};${o}path=/;max-age=31536000;`}
 /*!
  * @license
  * Copyright 2019-2020 The Go Authors. All rights reserved.
@@ -28,4 +28,10 @@
  * Use of this source code is governed by a BSD-style
  * license that can be found in the LICENSE file.
  */
+/**
+ * @license
+ * Copyright 2022 The Go Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
 //# sourceMappingURL=frontend.js.map
diff --git a/static/frontend/frontend.js.map b/static/frontend/frontend.js.map
index d5135b5..a839474 100644
--- a/static/frontend/frontend.js.map
+++ b/static/frontend/frontend.js.map
@@ -1,7 +1,7 @@
 {
   "version": 3,
   "sources": ["../shared/header/header.ts", "../shared/carousel/carousel.ts", "../shared/clipboard/clipboard.ts", "../shared/tooltip/tooltip.ts", "../shared/outline/select.ts", "../shared/modal/modal.ts", "../shared/analytics/analytics.ts", "../shared/keyboard/keyboard.ts", "../shared/jump/jump.ts", "about/index.ts", "frontend.ts"],
-  "sourcesContent": ["/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nexport function registerHeaderListeners(): void {\n  const header = document.querySelector('.js-header') as HTMLElement;\n\n  // Desktop menu hover state\n  const menuItemHovers = document.querySelectorAll('.js-desktop-menu-hover');\n  menuItemHovers.forEach(menuItemHover => {\n    // when user clicks on the dropdown menu item on desktop or mobile,\n    // force the menu to stay open until the user clicks off of it.\n    menuItemHover.addEventListener('mouseenter', e => {\n      const target = e.target as HTMLElement;\n      const forced = document.querySelector('.forced-open') as HTMLElement;\n      if (forced && forced !== menuItemHover) {\n        forced.blur();\n        forced.classList.remove('forced-open');\n      }\n      // prevents menus that have been tabbed into from staying open\n      // when you hover over another menu\n      target.focus();\n      target.blur();\n    });\n\n    const toggleForcedOpen = (e: Event) => {\n      const target = e.target as HTMLElement;\n      const isForced = target?.classList.contains('forced-open');\n      const currentTarget = e.currentTarget as HTMLElement;\n      if (isForced) {\n        currentTarget.removeEventListener('blur', () =>\n          currentTarget.classList.remove('forced-open')\n        );\n        currentTarget.classList.remove('forced-open');\n        currentTarget.classList.add('forced-closed');\n        currentTarget.blur();\n        currentTarget?.parentNode?.addEventListener('mouseout', () => {\n          currentTarget.classList.remove('forced-closed');\n        });\n      } else {\n        currentTarget.classList.remove('forced-closed');\n        currentTarget.classList.add('forced-open');\n        currentTarget.focus();\n        currentTarget.addEventListener('blur', () => currentTarget.classList.remove('forced-open'));\n        currentTarget?.parentNode?.removeEventListener('mouseout', () => {\n          currentTarget.classList.remove('forced-closed');\n        });\n      }\n    };\n    menuItemHover.addEventListener('click', toggleForcedOpen);\n  });\n\n  // ensure desktop submenus are closed when esc is pressed\n  const headerItems = document.querySelectorAll('.Header-menuItem');\n  headerItems.forEach(header => {\n    header.addEventListener('keyup', e => {\n      const event = e as KeyboardEvent;\n      if (event.key === 'Escape') {\n        (event.target as HTMLElement)?.blur();\n      }\n    });\n  });\n\n  // Mobile menu subnav menus\n  const headerbuttons = document.querySelectorAll('.js-headerMenuButton');\n  headerbuttons.forEach(button => {\n    button.addEventListener('click', e => {\n      e.preventDefault();\n      const isActive = header?.classList.contains('is-active');\n      if (isActive) {\n        handleNavigationDrawerInactive(header);\n      } else {\n        handleNavigationDrawerActive(header);\n      }\n      button.setAttribute('aria-expanded', isActive ? 'true' : 'false');\n    });\n  });\n\n  const scrim = document.querySelector('.js-scrim');\n  scrim?.addEventListener('click', e => {\n    e.preventDefault();\n\n    // find any active submenus and close them\n    const activeSubnavs = document.querySelectorAll('.go-NavigationDrawer-submenuItem.is-active');\n    activeSubnavs.forEach(subnav => handleNavigationDrawerInactive(subnav as HTMLElement));\n\n    handleNavigationDrawerInactive(header);\n\n    headerbuttons.forEach(button => {\n      button.setAttribute(\n        'aria-expanded',\n        header?.classList.contains('is-active') ? 'true' : 'false'\n      );\n    });\n  });\n\n  const getNavigationDrawerMenuItems = (navigationDrawer: HTMLElement): HTMLElement[] => {\n    if (!navigationDrawer) {\n      return [];\n    }\n\n    const menuItems = Array.from(\n      navigationDrawer.querySelectorAll(\n        ':scope > .go-NavigationDrawer-nav > .go-NavigationDrawer-list > .go-NavigationDrawer-listItem > a, :scope > .go-NavigationDrawer-nav > .go-NavigationDrawer-list > .go-NavigationDrawer-listItem > .go-Header-socialIcons > a'\n      ) || []\n    );\n\n    const anchorEl = navigationDrawer.querySelector('.go-NavigationDrawer-header > a');\n    if (anchorEl) {\n      menuItems.unshift(anchorEl);\n    }\n    return menuItems as HTMLElement[];\n  };\n\n  const getNavigationDrawerIsSubnav = (navigationDrawer: HTMLElement) => {\n    if (!navigationDrawer) {\n      return;\n    }\n    return navigationDrawer.classList.contains('go-NavigationDrawer-submenuItem');\n  };\n\n  const handleNavigationDrawerInactive = (navigationDrawer: HTMLElement) => {\n    if (!navigationDrawer) {\n      return;\n    }\n    const menuItems = getNavigationDrawerMenuItems(navigationDrawer);\n    navigationDrawer.classList.remove('is-active');\n    const parentMenuItem = navigationDrawer\n      .closest('.go-NavigationDrawer-listItem')\n      ?.querySelector(':scope > a') as HTMLElement;\n    parentMenuItem?.focus();\n    menuItems?.forEach(item => item?.setAttribute('tabindex', '-1'));\n    if (menuItems && menuItems[0]) {\n      menuItems[0].removeEventListener('keydown', handleMenuItemTabLeftFactory(navigationDrawer));\n      menuItems[menuItems.length - 1].removeEventListener(\n        'keydown',\n        handleMenuItemTabRightFactory(navigationDrawer)\n      );\n    }\n\n    if (navigationDrawer === header) {\n      headerbuttons && (headerbuttons[0] as HTMLElement)?.focus();\n    }\n  };\n\n  const handleNavigationDrawerActive = (navigationDrawer: HTMLElement) => {\n    const menuItems = getNavigationDrawerMenuItems(navigationDrawer);\n\n    navigationDrawer.classList.add('is-active');\n    menuItems.forEach(item => item.setAttribute('tabindex', '0'));\n    menuItems[0].focus();\n\n    menuItems[0].addEventListener('keydown', handleMenuItemTabLeftFactory(navigationDrawer));\n    menuItems[menuItems.length - 1].addEventListener(\n      'keydown',\n      handleMenuItemTabRightFactory(navigationDrawer)\n    );\n  };\n\n  const handleMenuItemTabLeftFactory = (navigationDrawer: HTMLElement) => {\n    return (e: KeyboardEvent) => {\n      if (e.key === 'Tab' && e.shiftKey) {\n        e.preventDefault();\n        handleNavigationDrawerInactive(navigationDrawer);\n      }\n    };\n  };\n\n  const handleMenuItemTabRightFactory = (navigationDrawer: HTMLElement) => {\n    return (e: KeyboardEvent) => {\n      if (e.key === 'Tab' && !e.shiftKey) {\n        e.preventDefault();\n        handleNavigationDrawerInactive(navigationDrawer);\n      }\n    };\n  };\n\n  const prepMobileNavigationDrawer = (navigationDrawer: HTMLElement) => {\n    const isSubnav = getNavigationDrawerIsSubnav(navigationDrawer);\n    const menuItems = getNavigationDrawerMenuItems(navigationDrawer);\n    navigationDrawer.addEventListener('keyup', e => {\n      if (e.key === 'Escape') {\n        handleNavigationDrawerInactive(navigationDrawer);\n      }\n    });\n\n    menuItems.forEach(item => {\n      const parentLi = item.closest('li');\n      if (parentLi && parentLi.classList.contains('js-mobile-subnav-trigger')) {\n        const submenu = parentLi.querySelector('.go-NavigationDrawer-submenuItem') as HTMLElement;\n        item.addEventListener('click', () => {\n          handleNavigationDrawerActive(submenu);\n        });\n      }\n    });\n    if (isSubnav) {\n      handleNavigationDrawerInactive(navigationDrawer);\n      navigationDrawer\n        ?.querySelector('.go-NavigationDrawer-header')\n        ?.addEventListener('click', e => {\n          e.preventDefault();\n          handleNavigationDrawerInactive(navigationDrawer);\n        });\n    }\n  };\n\n  document\n    .querySelectorAll('.go-NavigationDrawer')\n    .forEach(drawer => prepMobileNavigationDrawer(drawer as HTMLElement));\n\n  handleNavigationDrawerInactive(header);\n}\n\nexport function registerSearchFormListeners(): void {\n  const searchForm = document.querySelector('.js-searchForm');\n  const expandSearch = document.querySelector('.js-expandSearch');\n  const input = searchForm?.querySelector('input');\n  const headerLogo = document.querySelector('.js-headerLogo');\n  const menuButton = document.querySelector('.js-headerMenuButton');\n  expandSearch?.addEventListener('click', () => {\n    searchForm?.classList.add('go-SearchForm--expanded');\n    headerLogo?.classList.add('go-Header-logo--hidden');\n    menuButton?.classList.add('go-Header-navOpen--hidden');\n    input?.focus();\n  });\n  document?.addEventListener('click', e => {\n    if (!searchForm?.contains(e.target as Node)) {\n      searchForm?.classList.remove('go-SearchForm--expanded');\n      headerLogo?.classList.remove('go-Header-logo--hidden');\n      menuButton?.classList.remove('go-Header-navOpen--hidden');\n    }\n  });\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * Carousel Controller adds event listeners, accessibility enhancements, and\n * control elements to a carousel component.\n */\nexport class CarouselController {\n  /**\n   * slides is a collection of slides in the carousel.\n   */\n  private slides: HTMLLIElement[];\n  /**\n   * dots is a collection of dot navigation controls, added to the carousel\n   * by this controller.\n   */\n  private dots: HTMLElement[];\n  /**\n   * liveRegion is a visually hidden element that notifies assitive devices\n   * of visual changes to the carousel. They are added to the carousel by\n   * this controller.\n   */\n  private liveRegion: HTMLElement;\n  /**\n   * activeIndex is the 0-index of the currently active slide.\n   */\n  private activeIndex: number;\n\n  constructor(private el: HTMLElement) {\n    this.slides = Array.from(el.querySelectorAll('.go-Carousel-slide'));\n    this.dots = [];\n    this.liveRegion = document.createElement('div');\n    this.activeIndex = Number(el.getAttribute('data-slide-index') ?? 0);\n\n    this.initSlides();\n    this.initArrows();\n    this.initDots();\n    this.initLiveRegion();\n  }\n\n  private initSlides() {\n    for (const [i, v] of this.slides.entries()) {\n      if (i === this.activeIndex) continue;\n      v.setAttribute('aria-hidden', 'true');\n    }\n  }\n\n  private initArrows() {\n    const arrows = document.createElement('ul');\n    arrows.classList.add('go-Carousel-arrows');\n    arrows.innerHTML = `\n      <li>\n        <button class=\"go-Carousel-prevSlide\" aria-label=\"Go to previous slide\">\n          <img class=\"go-Icon\" height=\"24\" width=\"24\" src=\"/static/shared/icon/arrow_left_gm_grey_24dp.svg\" alt=\"\">\n        </button>\n      </li>\n      <li>\n        <button class=\"go-Carousel-nextSlide\" aria-label=\"Go to next slide\">\n          <img class=\"go-Icon\" height=\"24\" width=\"24\" src=\"/static/shared/icon/arrow_right_gm_grey_24dp.svg\" alt=\"\">\n        </button>\n      </li>\n    `;\n    arrows\n      .querySelector('.go-Carousel-prevSlide')\n      ?.addEventListener('click', () => this.setActive(this.activeIndex - 1));\n    arrows\n      .querySelector('.go-Carousel-nextSlide')\n      ?.addEventListener('click', () => this.setActive(this.activeIndex + 1));\n    this.el.append(arrows);\n  }\n\n  private initDots() {\n    const dots = document.createElement('ul');\n    dots.classList.add('go-Carousel-dots');\n    for (let i = 0; i < this.slides.length; i++) {\n      const li = document.createElement('li');\n      const button = document.createElement('button');\n      button.classList.add('go-Carousel-dot');\n      if (i === this.activeIndex) {\n        button.classList.add('go-Carousel-dot--active');\n      }\n      button.innerHTML = `<span class=\"go-Carousel-obscured\">Slide ${i + 1}</span>`;\n      button.addEventListener('click', () => this.setActive(i));\n      li.append(button);\n      dots.append(li);\n      this.dots.push(button);\n    }\n    this.el.append(dots);\n  }\n\n  private initLiveRegion() {\n    this.liveRegion.setAttribute('aria-live', 'polite');\n    this.liveRegion.setAttribute('aria-atomic', 'true');\n    this.liveRegion.setAttribute('class', 'go-Carousel-obscured');\n    this.liveRegion.textContent = `Slide ${this.activeIndex + 1} of ${this.slides.length}`;\n    this.el.appendChild(this.liveRegion);\n  }\n\n  private setActive = (index: number) => {\n    this.activeIndex = (index + this.slides.length) % this.slides.length;\n    this.el.setAttribute('data-slide-index', String(this.activeIndex));\n    for (const d of this.dots) {\n      d.classList.remove('go-Carousel-dot--active');\n    }\n    this.dots[this.activeIndex].classList.add('go-Carousel-dot--active');\n    for (const s of this.slides) {\n      s.setAttribute('aria-hidden', 'true');\n    }\n    this.slides[this.activeIndex].removeAttribute('aria-hidden');\n    this.liveRegion.textContent = 'Slide ' + (this.activeIndex + 1) + ' of ' + this.slides.length;\n  };\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This class decorates an element to copy arbitrary data attached via a data-\n * attribute to the clipboard.\n */\nexport class ClipboardController {\n  /**\n   * The data to be copied to the clipboard.\n   */\n  private data: string;\n\n  /**\n   * @param el The element that will trigger copying text to the clipboard. The text is\n   * expected to be within its data-to-copy attribute.\n   */\n  constructor(private el: HTMLButtonElement) {\n    this.data = el.dataset['toCopy'] ?? el.innerText;\n    // if data-to-copy is empty and the button is part of an input group\n    // capture the value of the input.\n    if (!this.data && el.parentElement?.classList.contains('go-InputGroup')) {\n      this.data = (this.data || el.parentElement?.querySelector('input')?.value) ?? '';\n    }\n    el.addEventListener('click', e => this.handleCopyClick(e));\n  }\n\n  /**\n   * Handles when the primary element is clicked.\n   */\n  handleCopyClick(e: MouseEvent): void {\n    e.preventDefault();\n    const TOOLTIP_SHOW_DURATION_MS = 1000;\n\n    // This API is not available on iOS.\n    if (!navigator.clipboard) {\n      this.showTooltipText('Unable to copy', TOOLTIP_SHOW_DURATION_MS);\n      return;\n    }\n    navigator.clipboard\n      .writeText(this.data)\n      .then(() => {\n        this.showTooltipText('Copied!', TOOLTIP_SHOW_DURATION_MS);\n      })\n      .catch(() => {\n        this.showTooltipText('Unable to copy', TOOLTIP_SHOW_DURATION_MS);\n      });\n  }\n\n  /**\n   * Shows the given text in a tooltip for a specified amount of time, in milliseconds.\n   */\n  showTooltipText(text: string, durationMs: number): void {\n    this.el.setAttribute('data-tooltip', text);\n    setTimeout(() => this.el.setAttribute('data-tooltip', ''), durationMs);\n  }\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * ToolTipController handles closing tooltips on external clicks.\n */\nexport class ToolTipController {\n  constructor(private el: HTMLDetailsElement) {\n    document.addEventListener('click', e => {\n      const insideTooltip = this.el.contains(e.target as Element);\n      if (!insideTooltip) {\n        this.el.removeAttribute('open');\n      }\n    });\n  }\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { TreeNavController } from './tree.js';\n\nexport class SelectNavController {\n  constructor(private el: Element) {\n    this.el.addEventListener('change', e => {\n      const target = e.target as HTMLSelectElement;\n      let href = target.value;\n      if (!target.value.startsWith('/')) {\n        href = '/' + href;\n      }\n      window.location.href = href;\n    });\n  }\n}\n\nexport function makeSelectNav(tree: TreeNavController): HTMLLabelElement {\n  const label = document.createElement('label');\n  label.classList.add('go-Label');\n  label.setAttribute('aria-label', 'Menu');\n  const select = document.createElement('select');\n  select.classList.add('go-Select', 'js-selectNav');\n  label.appendChild(select);\n  const outline = document.createElement('optgroup');\n  outline.label = 'Outline';\n  select.appendChild(outline);\n  const groupMap: Record<string, HTMLOptGroupElement> = {};\n  let group: HTMLOptGroupElement;\n  for (const t of tree.treeitems) {\n    if (Number(t.depth) > 4) continue;\n    if (t.groupTreeitem) {\n      group = groupMap[t.groupTreeitem.label];\n      if (!group) {\n        group = groupMap[t.groupTreeitem.label] = document.createElement('optgroup');\n        group.label = t.groupTreeitem.label;\n        select.appendChild(group);\n      }\n    } else {\n      group = outline;\n    }\n    const o = document.createElement('option');\n    o.label = t.label;\n    o.textContent = t.label;\n    o.value = (t.el as HTMLAnchorElement).href.replace(window.location.origin, '').replace('/', '');\n    group.appendChild(o);\n  }\n  tree.addObserver(t => {\n    const hash = (t.el as HTMLAnchorElement).hash;\n    const value = select.querySelector<HTMLOptionElement>(`[value$=\"${hash}\"]`)?.value;\n    if (value) {\n      select.value = value;\n    }\n  }, 50);\n  return label;\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\ninterface Window {\n  dialogPolyfill?: {\n    registerDialog: (el: HTMLDialogElement) => void;\n  };\n}\n\ndeclare const window: Window;\n\n/**\n * ModalController registers a dialog element with the polyfill if\n * necessary for the current browser, add adds event listeners to\n * close and open modals.\n */\nexport class ModalController {\n  constructor(private el: HTMLDialogElement) {\n    if (window.dialogPolyfill) {\n      window.dialogPolyfill.registerDialog(el);\n    }\n    this.init();\n  }\n\n  init() {\n    const button = document.querySelector<HTMLButtonElement>(`[aria-controls=\"${this.el.id}\"]`);\n    if (button) {\n      button.addEventListener('click', () => {\n        if (this.el.showModal) {\n          this.el.showModal();\n        } else {\n          this.el.setAttribute('opened', 'true');\n        }\n        this.el.querySelector('input')?.focus();\n      });\n    }\n    for (const btn of this.el.querySelectorAll<HTMLButtonElement>('[data-modal-close]')) {\n      btn.addEventListener('click', () => {\n        if (this.el.close) {\n          this.el.close();\n        } else {\n          this.el.removeAttribute('opened');\n        }\n      });\n    }\n  }\n}\n", "interface TagManagerEvent {\n  /**\n   * event is the name of the event, used to filter events in\n   * Google Analytics.\n   */\n  event: string;\n\n  /**\n   * event_category is a name that you supply as a way to group objects\n   * that to analyze. Typically, you will use the same category name\n   * multiple times over related UI elements (buttons, links, etc).\n   */\n  event_category?: string;\n\n  /**\n   * event_action is used to name the type of event or interaction you\n   * want to measure for a particular web object. For example, with a\n   * single \"form\" category, you can analyze a number of specific events\n   * with this parameter, such as: form entered, form submitted.\n   */\n  event_action?: string;\n\n  /**\n   * event_label provide additional information for events that you want\n   * to analyze, such as the text label of a link.\n   */\n  event_label?: string;\n\n  /**\n   * gtm.start is used to initialize Google Tag Manager.\n   */\n  'gtm.start'?: number;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ndeclare global {\n  interface Window {\n    dataLayer?: (TagManagerEvent | VoidFunction)[];\n    ga?: unknown;\n  }\n}\n\n/**\n * track sends events to Google Tag Manager.\n */\nexport function track(\n  event: string | TagManagerEvent,\n  category?: string,\n  action?: string,\n  label?: string\n): void {\n  window.dataLayer ??= [];\n  if (typeof event === 'string') {\n    window.dataLayer.push({\n      event,\n      event_category: category,\n      event_action: action,\n      event_label: label,\n    });\n  } else {\n    window.dataLayer.push(event);\n  }\n}\n\n/**\n * func adds functions to run sequentionally after\n * Google Tag Manager is ready.\n */\nexport function func(fn: () => void): void {\n  window.dataLayer ??= [];\n  window.dataLayer.push(fn);\n}\n", "/*!\n * @license\n * Copyright 2019-2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { track } from '../analytics/analytics';\n\n/**\n * Options are keyhandler callback options.\n */\ninterface Options {\n  /**\n   * target is the element the key event should filter on. The\n   * default target is the document.\n   */\n  target?: Element;\n\n  /**\n   * withMeta specifies if the event callback should fire when\n   * the key is pressed with a meta key (ctrl, alt, etc). By\n   * default meta keypresses are ignored.\n   */\n  withMeta?: boolean;\n}\n\n/**\n * KeyHandler is the config for a keyboard event callback.\n */\ninterface KeyHandler extends Options {\n  description: string;\n  callback: (e: KeyboardEvent) => void;\n}\n\n/**\n * KeyboardController controls event callbacks for sitewide\n * keyboard events. Multiple callbacks can be registered for\n * a single key and by default the controller ignores events\n * for text input targets.\n */\nclass KeyboardController {\n  handlers: Record<string, Set<KeyHandler>>;\n\n  constructor() {\n    this.handlers = {};\n    document.addEventListener('keydown', e => this.handleKeyPress(e));\n  }\n\n  /**\n   * on registers keyboard event callbacks.\n   * @param key the key to register.\n   * @param description name of the event.\n   * @param callback event callback.\n   * @param options set target and withMeta options to override the default behaviors.\n   */\n  on(key: string, description: string, callback: (e: KeyboardEvent) => void, options?: Options) {\n    this.handlers[key] ??= new Set();\n    this.handlers[key].add({ description, callback, ...options });\n    return this;\n  }\n\n  private handleKeyPress(e: KeyboardEvent) {\n    for (const handler of this.handlers[e.key.toLowerCase()] ?? new Set()) {\n      if (handler.target && handler.target !== e.target) {\n        return;\n      }\n      const t = e.target as HTMLElement | null;\n      if (\n        !handler.target &&\n        (t?.tagName === 'INPUT' || t?.tagName === 'SELECT' || t?.tagName === 'TEXTAREA')\n      ) {\n        return;\n      }\n      if (t?.isContentEditable) {\n        return;\n      }\n      if (\n        (handler.withMeta && !(e.ctrlKey || e.metaKey)) ||\n        (!handler.withMeta && (e.ctrlKey || e.metaKey))\n      ) {\n        return;\n      }\n      track('keypress', 'hotkeys', `${e.key} pressed`, handler.description);\n      handler.callback(e);\n    }\n  }\n}\n\nexport const keyboard = new KeyboardController();\n", "/*!\n * @license\n * Copyright 2019-2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n// This file implements the behavior of the \"jump to symbol\" dialog for Go\n// package documentation, as well as the simple dialog that displays keyboard\n// shortcuts.\n\n// The DOM for the dialogs is at the bottom of static/frontend/unit/main/_modals.tmpl.\n// The CSS is in static/frontend/unit/main/_modals.css.\n\n// The dialog is activated by pressing the 'f' key. It presents a list\n// (#JumpDialog-list) of all Go symbols displayed in the documentation.\n// Entering text in the dialog's text box (#JumpDialog-filter) restricts the\n// list to symbols containing the text. Clicking on an symbol jumps to\n// its documentation.\n\n// This code is based on\n// https://go.googlesource.com/gddo/+/refs/heads/master/gddo-server/assets/site.js.\n// It was modified to remove the dependence on jquery and bootstrap.\n\nimport { keyboard } from '../keyboard/keyboard';\n\nexport function initModals(): void {\n  const jumpDialog = document.querySelector<HTMLDialogElement>('.JumpDialog');\n  const jumpBody = jumpDialog?.querySelector<HTMLDivElement>('.JumpDialog-body');\n  const jumpList = jumpDialog?.querySelector<HTMLDivElement>('.JumpDialog-list');\n  const jumpFilter = jumpDialog?.querySelector<HTMLInputElement>('.JumpDialog-input');\n  const doc = document.querySelector<HTMLDivElement>('.js-documentation');\n\n  interface JumpListItem {\n    link: HTMLAnchorElement;\n    name: string;\n    kind: string;\n    lower: string;\n  }\n\n  let jumpListItems: JumpListItem[] | undefined; // All the symbols in the doc; computed only once.\n\n  // collectJumpListItems returns a list of items, one for each symbol in the\n  // documentation on the current page.\n  //\n  // It uses the data-kind attribute generated in the documentation HTML to find\n  // the symbols and their id attributes.\n  //\n  // If there are no data-kind attributes, then we have older doc; fall back to\n  // a less precise method.\n  function collectJumpListItems() {\n    const items = [];\n    if (!doc) return;\n    for (const el of doc.querySelectorAll('[data-kind]')) {\n      items.push(newJumpListItem(el));\n    }\n\n    // Clicking on any of the links closes the dialog.\n    for (const item of items) {\n      item.link.addEventListener('click', function () {\n        jumpDialog?.close();\n      });\n    }\n    // Sort case-insensitively by symbol name.\n    items.sort(function (a, b) {\n      return a.lower.localeCompare(b.lower);\n    });\n    return items;\n  }\n\n  // newJumpListItem creates a new item for the DOM element el.\n  // An item is an object with:\n  // - name: the element's id (which is the symbol name)\n  // - kind: the element's kind (function, variable, etc.),\n  // - link: a link ('a' tag) to the element\n  // - lower: the name in lower case, just for sorting\n  function newJumpListItem(el: Element): JumpListItem {\n    const a = document.createElement('a');\n    const name = el.getAttribute('id');\n    a.setAttribute('href', '#' + name);\n    a.setAttribute('tabindex', '-1');\n    a.setAttribute('data-gtmc', 'jump to link');\n    const kind = el.getAttribute('data-kind');\n    return {\n      link: a,\n      name: name ?? '',\n      kind: kind ?? '',\n      lower: name?.toLowerCase() ?? '', // for sorting\n    };\n  }\n\n  let lastFilterValue: string; // The last contents of the filter text box.\n  let activeJumpItem = -1; // The index of the currently active item in the list.\n\n  // updateJumpList sets the elements of the dialog list to\n  // everything whose name contains filter.\n  function updateJumpList(filter: string) {\n    lastFilterValue = filter;\n    if (!jumpListItems) {\n      jumpListItems = collectJumpListItems();\n    }\n    setActiveJumpItem(-1);\n\n    // Remove all children from list.\n    while (jumpList?.firstChild) {\n      jumpList.firstChild.remove();\n    }\n\n    if (filter) {\n      // A filter is set. We treat the filter as a substring that can appear in\n      // an item name (case insensitive), and find the following matches - in\n      // order of priority:\n      //\n      // 1. Exact matches (the filter matches the item's name exactly)\n      // 2. Prefix matches (the item's name starts with filter)\n      // 3. Infix matches (the filter is a substring of the item's name)\n      const filterLowerCase = filter.toLowerCase();\n\n      const exactMatches = [];\n      const prefixMatches = [];\n      const infixMatches = [];\n\n      // makeLinkHtml creates the link name HTML for a list item. item is the DOM\n      // item. item.name.substr(boldStart, boldEnd) will be bolded.\n      const makeLinkHtml = (item: JumpListItem, boldStart: number, boldEnd: number) => {\n        return (\n          item.name.substring(0, boldStart) +\n          '<b>' +\n          item.name.substring(boldStart, boldEnd) +\n          '</b>' +\n          item.name.substring(boldEnd)\n        );\n      };\n\n      for (const item of jumpListItems ?? []) {\n        const nameLowerCase = item.name.toLowerCase();\n\n        if (nameLowerCase === filterLowerCase) {\n          item.link.innerHTML = makeLinkHtml(item, 0, item.name.length);\n          exactMatches.push(item);\n        } else if (nameLowerCase.startsWith(filterLowerCase)) {\n          item.link.innerHTML = makeLinkHtml(item, 0, filter.length);\n          prefixMatches.push(item);\n        } else {\n          const index = nameLowerCase.indexOf(filterLowerCase);\n          if (index > -1) {\n            item.link.innerHTML = makeLinkHtml(item, index, index + filter.length);\n            infixMatches.push(item);\n          }\n        }\n      }\n\n      for (const item of exactMatches.concat(prefixMatches).concat(infixMatches)) {\n        jumpList?.appendChild(item.link);\n      }\n    } else {\n      if (!jumpListItems || jumpListItems.length === 0) {\n        const msg = document.createElement('i');\n        msg.innerHTML = 'There are no symbols on this page.';\n        jumpList?.appendChild(msg);\n      }\n      // No filter set; display all items in their existing order.\n      for (const item of jumpListItems ?? []) {\n        item.link.innerHTML = item.name + ' <i>' + item.kind + '</i>';\n        jumpList?.appendChild(item.link);\n      }\n    }\n\n    if (jumpBody) {\n      jumpBody.scrollTop = 0;\n    }\n    if (jumpListItems?.length && jumpList && jumpList.children.length > 0) {\n      setActiveJumpItem(0);\n    }\n  }\n\n  // Set the active jump item to n.\n  function setActiveJumpItem(n: number) {\n    const cs = jumpList?.children as HTMLCollectionOf<HTMLElement> | null | undefined;\n    if (!cs || !jumpBody) {\n      return;\n    }\n    if (activeJumpItem >= 0) {\n      cs[activeJumpItem].classList.remove('JumpDialog-active');\n    }\n    if (n >= cs.length) {\n      n = cs.length - 1;\n    }\n    if (n >= 0) {\n      cs[n].classList.add('JumpDialog-active');\n\n      // Scroll so the active item is visible.\n      // For some reason cs[n].scrollIntoView() doesn't behave as I'd expect:\n      // it moves the entire dialog box in the viewport.\n\n      // Get the top and bottom of the active item relative to jumpBody.\n      const activeTop = cs[n].offsetTop - cs[0].offsetTop;\n      const activeBottom = activeTop + cs[n].clientHeight;\n      if (activeTop < jumpBody.scrollTop) {\n        // Off the top; scroll up.\n        jumpBody.scrollTop = activeTop;\n      } else if (activeBottom > jumpBody.scrollTop + jumpBody.clientHeight) {\n        // Off the bottom; scroll down.\n        jumpBody.scrollTop = activeBottom - jumpBody.clientHeight;\n      }\n    }\n    activeJumpItem = n;\n  }\n\n  // Increment the activeJumpItem by delta.\n  function incActiveJumpItem(delta: number) {\n    if (activeJumpItem < 0) {\n      return;\n    }\n    let n = activeJumpItem + delta;\n    if (n < 0) {\n      n = 0;\n    }\n    setActiveJumpItem(n);\n  }\n\n  // Pressing a key in the filter updates the list (if the filter actually changed).\n  jumpFilter?.addEventListener('keyup', function () {\n    if (jumpFilter.value.toUpperCase() != lastFilterValue.toUpperCase()) {\n      updateJumpList(jumpFilter.value);\n    }\n  });\n\n  // Pressing enter in the filter selects the first element in the list.\n  jumpFilter?.addEventListener('keydown', function (event) {\n    const upArrow = 38;\n    const downArrow = 40;\n    const enterKey = 13;\n    switch (event.which) {\n      case upArrow:\n        incActiveJumpItem(-1);\n        event.preventDefault();\n        break;\n      case downArrow:\n        incActiveJumpItem(1);\n        event.preventDefault();\n        break;\n      case enterKey:\n        if (activeJumpItem >= 0) {\n          if (jumpList) {\n            (jumpList.children[activeJumpItem] as HTMLElement).click();\n            event.preventDefault();\n          }\n        }\n        break;\n    }\n  });\n\n  const shortcutsDialog = document.querySelector<HTMLDialogElement>('.ShortcutsDialog');\n\n  // - Pressing 'f' or 'F' opens the jump-to-symbol dialog.\n  // - Pressing '?' opens up the shortcut dialog.\n  // Ignore a keypress if a dialog is already open, or if it is pressed on a\n  // component that wants to consume it.\n  keyboard\n    .on('f', 'open jump to modal', e => {\n      if (jumpDialog?.open || shortcutsDialog?.open) {\n        return;\n      }\n      e.preventDefault();\n      if (jumpFilter) {\n        jumpFilter.value = '';\n      }\n      jumpDialog?.showModal?.();\n      jumpFilter?.focus();\n      updateJumpList('');\n    })\n    .on('?', 'open shortcuts modal', () => {\n      if (jumpDialog?.open || shortcutsDialog?.open) {\n        return;\n      }\n      shortcutsDialog?.showModal?.();\n    });\n\n  const jumpOutlineInput = document.querySelector('.js-jumpToInput');\n  if (jumpOutlineInput) {\n    jumpOutlineInput.addEventListener('click', () => {\n      if (jumpFilter) {\n        jumpFilter.value = '';\n      }\n      updateJumpList('');\n      if (jumpDialog?.open || shortcutsDialog?.open) {\n        return;\n      }\n      jumpDialog?.showModal?.();\n      jumpFilter?.focus();\n    });\n  }\n\n  document.querySelector('.js-openShortcuts')?.addEventListener('click', () => {\n    shortcutsDialog?.showModal?.();\n  });\n}\n", "/**\n * Left Navigation.\n */\nexport const initJumpLinks = async function () {\n  const pagesWithJumpLinks = ['/about'];\n  if (!pagesWithJumpLinks.includes(window.location.pathname)) {\n    // stop the file from doing anything else if the page doesn't have jumplinks\n    return;\n  }\n\n  // these might be generated or not so don't grab references to the elements until actually need them.\n  const titles = 'h2, h3, h4';\n  const nav = '.LeftNav a';\n  // these are always in the dom so we can get them now and throw errors if they're not.\n  const leftNav = document.querySelector('.LeftNav');\n  const siteContent = document.querySelector('.go-Content');\n  let isObserverDisabled = false;\n\n  /**\n   * El function\n   * @example el('h1', {className: 'title'}, 'Welcome to the site');\n   * @example el('ul', {className: 'list'}, el('li', {}, 'Item one'), el('li', {}, 'Item two'), el('li', {}, 'Item three'));\n   * @example el('img', {src: '/url.svg'});\n   */\n  function el(\n    type = '',\n    props: { [key: string]: string } = {},\n    ...children: (HTMLElement | HTMLElement[] | string | undefined)[]\n  ) {\n    // Error, no type declared.\n    if (!type) {\n      throw new Error('Provide `type` to create document element.');\n    }\n\n    // Create element with optional attribute props\n    const docEl = Object.assign(document.createElement(type), props);\n\n    // Children: array containing strings or elements\n    children.forEach(child => {\n      if (typeof child === 'string') {\n        docEl.appendChild(document.createTextNode(child));\n      } else if (Array.isArray(child)) {\n        child.forEach(c => docEl.appendChild(c));\n      } else if (child instanceof HTMLElement) {\n        docEl.appendChild(child);\n      }\n    });\n\n    return docEl;\n  }\n  /**  Build Nav if data hydrate is present. */\n  function buildNav() {\n    return new Promise((resolve, reject) => {\n      let navItems: { id: string; label: string; subnav?: { id: string; label: string }[] }[] = [];\n      let elements: HTMLElement[] = [];\n\n      if (!siteContent || !leftNav) {\n        return reject('.SiteContent not found.');\n      }\n      if (leftNav instanceof HTMLElement && !leftNav?.dataset?.hydrate) {\n        return resolve(true);\n      }\n\n      for (const title of siteContent.querySelectorAll(titles)) {\n        if (title instanceof HTMLElement && !title?.dataset?.ignore) {\n          switch (title.tagName) {\n            case 'H2':\n              navItems = [\n                ...navItems,\n                {\n                  id: title.id,\n                  label: title?.dataset?.title ? title.dataset.title : title.textContent ?? '',\n                },\n              ];\n              break;\n\n            case 'H3':\n            case 'H4':\n              if (!navItems[navItems.length - 1]?.subnav) {\n                navItems[navItems.length - 1].subnav = [\n                  {\n                    id: title.id,\n                    label: title?.dataset?.title ? title.dataset.title : title.textContent ?? '',\n                  },\n                ];\n              } else if (navItems[navItems.length - 1].subnav) {\n                navItems[navItems.length - 1].subnav?.push({\n                  id: title.id,\n                  label: title?.dataset?.title ? title.dataset.title : title.textContent ?? '',\n                });\n              }\n              break;\n          }\n        }\n      }\n\n      for (const navItem of navItems) {\n        const link = el('a', { href: '#' + navItem.id }, el('span', {}, navItem.label));\n        elements = [...elements, link];\n        if (navItem?.subnav) {\n          let subLinks: HTMLElement[] = [];\n          for (const subnavItem of navItem.subnav) {\n            const subItem = el(\n              'li',\n              {},\n              el(\n                'a',\n                { href: '#' + subnavItem.id },\n                el('img', { src: '/static/frontend/about/dot.svg', width: '5', height: '5' }),\n                el('span', {}, subnavItem.label)\n              )\n            );\n            subLinks = [...subLinks, subItem];\n          }\n          const list = el('ul', { className: 'LeftSubnav' }, subLinks);\n          elements = [...elements, list];\n        }\n      }\n\n      elements.forEach(element => leftNav.appendChild(element));\n\n      return resolve(true);\n    });\n  }\n  /**\n   * Set the correct active element.\n   */\n  function setNav() {\n    return new Promise(resolve => {\n      if (!document.querySelectorAll(nav)) return resolve(true);\n      for (const a of document.querySelectorAll(nav)) {\n        if (a instanceof HTMLAnchorElement && a.href === location.href) {\n          setElementActive(a);\n          break;\n        }\n      }\n      resolve(true);\n    });\n  }\n  /** resetNav: removes all .active from nav elements */\n  function resetNav() {\n    return new Promise(resolve => {\n      if (!document.querySelectorAll(nav)) return resolve(true);\n      for (const a of document.querySelectorAll(nav)) {\n        a.classList.remove('active');\n      }\n      resolve(true);\n    });\n  }\n  /** setElementActive: controls resetting nav and highlighting the appropriate nav items */\n  function setElementActive(element: HTMLAnchorElement) {\n    if (element instanceof HTMLAnchorElement) {\n      resetNav().then(() => {\n        element.classList.add('active');\n        const parent = element?.parentNode?.parentNode;\n        if (parent instanceof HTMLElement && parent?.classList?.contains('LeftSubnav')) {\n          parent.previousElementSibling?.classList.add('active');\n        }\n      });\n    }\n  }\n  /** setLinkManually: disables observer and selects the clicked nav item. */\n  function setLinkManually() {\n    delayObserver();\n    const link = document.querySelector('[href=\"' + location.hash + '\"]');\n    if (link instanceof HTMLAnchorElement) {\n      setElementActive(link);\n    }\n  }\n  /** delayObserver: Quick on off switch for intersection observer. */\n  function delayObserver() {\n    isObserverDisabled = true;\n    setTimeout(() => {\n      isObserverDisabled = false;\n    }, 200);\n  }\n  /** observeSections: kicks off observation of titles as well as manual clicks with hashchange */\n  function observeSections() {\n    window.addEventListener('hashchange', setLinkManually);\n\n    if (siteContent?.querySelectorAll(titles)) {\n      const callback: IntersectionObserverCallback = entries => {\n        if (!isObserverDisabled && Array.isArray(entries) && entries.length > 0) {\n          for (const entry of entries) {\n            if (entry.isIntersecting && entry.target instanceof HTMLElement) {\n              const { id } = entry.target;\n              const link = document.querySelector('[href=\"#' + id + '\"]');\n              if (link instanceof HTMLAnchorElement) {\n                setElementActive(link);\n              }\n              break;\n            }\n          }\n        }\n      };\n      // rootMargin is important when multiple sections are in the observable area **on page load**.\n      // they will still be highlighted on scroll because of the root margin.\n      const ob = new IntersectionObserver(callback, {\n        threshold: 0,\n        rootMargin: '0px 0px -50% 0px',\n      });\n      for (const title of siteContent.querySelectorAll(titles)) {\n        if (title instanceof HTMLElement && !title?.dataset?.ignore) {\n          ob.observe(title);\n        }\n      }\n    }\n  }\n\n  try {\n    await buildNav();\n    await setNav();\n    if (location.hash) {\n      delayObserver();\n    }\n    observeSections();\n  } catch (e) {\n    if (e instanceof Error) {\n      console.error(e.message);\n    } else {\n      console.error(e);\n    }\n  }\n};\n", "/**\n * @license\n * Copyright 2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { registerHeaderListeners, registerSearchFormListeners } from 'static/shared/header/header';\nimport { CarouselController } from 'static/shared/carousel/carousel';\nimport { ClipboardController } from 'static/shared/clipboard/clipboard';\nimport { ToolTipController } from 'static/shared/tooltip/tooltip';\nimport { SelectNavController } from 'static/shared/outline/select';\nimport { ModalController } from 'static/shared/modal/modal';\nimport { initModals } from 'static/shared/jump/jump';\n\nimport { keyboard } from 'static/shared/keyboard/keyboard';\nimport * as analytics from 'static/shared/analytics/analytics';\nimport { initJumpLinks } from './about/index';\n\nwindow.addEventListener('load', () => {\n  for (const el of document.querySelectorAll<HTMLButtonElement>('.js-clipboard')) {\n    new ClipboardController(el);\n  }\n\n  for (const el of document.querySelectorAll<HTMLDialogElement>('.js-modal')) {\n    new ModalController(el);\n  }\n\n  for (const t of document.querySelectorAll<HTMLDetailsElement>('.js-tooltip')) {\n    new ToolTipController(t);\n  }\n\n  for (const el of document.querySelectorAll<HTMLSelectElement>('.js-selectNav')) {\n    new SelectNavController(el);\n  }\n\n  for (const el of document.querySelectorAll<HTMLSelectElement>('.js-carousel')) {\n    new CarouselController(el);\n  }\n\n  for (const el of document.querySelectorAll('.js-toggleTheme')) {\n    el.addEventListener('click', () => {\n      toggleTheme();\n    });\n  }\n\n  if (document.querySelector<HTMLElement>('.js-gtmID')?.dataset.gtmid && window.dataLayer) {\n    analytics.func(function () {\n      removeUTMSource();\n    });\n  } else {\n    removeUTMSource();\n  }\n\n  registerHeaderListeners();\n  registerSearchFormListeners();\n  initModals();\n  initJumpLinks();\n});\n\n// Pressing '/' focuses the search box\nkeyboard.on('/', 'focus search', e => {\n  const searchInput = Array.from(\n    document.querySelectorAll<HTMLInputElement>('.js-searchFocus')\n  ).pop();\n  // Favoring the Firefox quick find feature over search input\n  // focus. See: https://github.com/golang/go/issues/41093.\n  if (searchInput && !window.navigator.userAgent.includes('Firefox')) {\n    e.preventDefault();\n    searchInput.focus();\n  }\n});\n\n// Pressing 'y' changes the browser URL to the canonical URL\n// without triggering a reload.\nkeyboard.on('y', 'set canonical url', () => {\n  let canonicalURLPath = document.querySelector<HTMLDivElement>('.js-canonicalURLPath')?.dataset[\n    'canonicalUrlPath'\n  ];\n  if (canonicalURLPath && canonicalURLPath !== '') {\n    const fragment = window.location.hash;\n    if (fragment) {\n      canonicalURLPath += fragment;\n    }\n    window.history.replaceState(null, '', canonicalURLPath);\n  }\n});\n\n/**\n * setupGoogleTagManager initializes Google Tag Manager.\n */\n(function setupGoogleTagManager() {\n  analytics.track({\n    'gtm.start': new Date().getTime(),\n    event: 'gtm.js',\n  });\n})();\n\n/**\n * removeUTMSource removes the utm_source GET parameter if present.\n * This is done using JavaScript, so that the utm_source is still\n * captured by Google Analytics.\n */\nfunction removeUTMSource() {\n  const urlParams = new URLSearchParams(window.location.search);\n  const utmSource = urlParams.get('utm_source');\n  if (utmSource !== 'gopls' && utmSource !== 'godoc' && utmSource !== 'pkggodev') {\n    return;\n  }\n\n  /** Strip the utm_source query parameter and replace the URL. **/\n  const newURL = new URL(window.location.href);\n  urlParams.delete('utm_source');\n  newURL.search = urlParams.toString();\n  window.history.replaceState(null, '', newURL.toString());\n}\n\n/**\n * toggleTheme switches the preferred color scheme between auto, light, and dark.\n */\nfunction toggleTheme() {\n  let nextTheme = 'dark';\n  const theme = document.documentElement.getAttribute('data-theme');\n  if (theme === 'dark') {\n    nextTheme = 'light';\n  } else if (theme === 'light') {\n    nextTheme = 'auto';\n  }\n  let domain = '';\n  if (location.hostname.endsWith('go.dev')) {\n    domain = 'domain=.go.dev;';\n  }\n  document.documentElement.setAttribute('data-theme', nextTheme);\n  document.cookie = `prefers-color-scheme=${nextTheme};${domain}path=/;max-age=31536000;`;\n}\n"],
-  "mappings": "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",
-  "names": []
+  "sourcesContent": ["/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nexport function registerHeaderListeners(): void {\n  const header = document.querySelector('.js-header') as HTMLElement;\n\n  // Desktop menu hover state\n  const menuItemHovers = document.querySelectorAll('.js-desktop-menu-hover');\n  menuItemHovers.forEach(menuItemHover => {\n    // when user clicks on the dropdown menu item on desktop or mobile,\n    // force the menu to stay open until the user clicks off of it.\n    menuItemHover.addEventListener('mouseenter', e => {\n      const target = e.target as HTMLElement;\n      const forced = document.querySelector('.forced-open') as HTMLElement;\n      if (forced && forced !== menuItemHover) {\n        forced.blur();\n        forced.classList.remove('forced-open');\n      }\n      // prevents menus that have been tabbed into from staying open\n      // when you hover over another menu\n      target.focus();\n      target.blur();\n    });\n\n    const toggleForcedOpen = (e: Event) => {\n      const target = e.target as HTMLElement;\n      const isForced = target?.classList.contains('forced-open');\n      const currentTarget = e.currentTarget as HTMLElement;\n      if (isForced) {\n        currentTarget.removeEventListener('blur', () =>\n          currentTarget.classList.remove('forced-open')\n        );\n        currentTarget.classList.remove('forced-open');\n        currentTarget.classList.add('forced-closed');\n        currentTarget.blur();\n        currentTarget?.parentNode?.addEventListener('mouseout', () => {\n          currentTarget.classList.remove('forced-closed');\n        });\n      } else {\n        currentTarget.classList.remove('forced-closed');\n        currentTarget.classList.add('forced-open');\n        currentTarget.focus();\n        currentTarget.addEventListener('blur', () => currentTarget.classList.remove('forced-open'));\n        currentTarget?.parentNode?.removeEventListener('mouseout', () => {\n          currentTarget.classList.remove('forced-closed');\n        });\n      }\n    };\n    menuItemHover.addEventListener('click', toggleForcedOpen);\n  });\n\n  // ensure desktop submenus are closed when esc is pressed\n  const headerItems = document.querySelectorAll('.Header-menuItem');\n  headerItems.forEach(header => {\n    header.addEventListener('keyup', e => {\n      const event = e as KeyboardEvent;\n      if (event.key === 'Escape') {\n        (event.target as HTMLElement)?.blur();\n      }\n    });\n  });\n\n  // Mobile menu subnav menus\n  const headerbuttons = document.querySelectorAll('.js-headerMenuButton');\n  headerbuttons.forEach(button => {\n    button.addEventListener('click', e => {\n      e.preventDefault();\n      const isActive = header?.classList.contains('is-active');\n      if (isActive) {\n        handleNavigationDrawerInactive(header);\n      } else {\n        handleNavigationDrawerActive(header);\n      }\n      button.setAttribute('aria-expanded', isActive ? 'true' : 'false');\n    });\n  });\n\n  const scrim = document.querySelector('.js-scrim');\n  scrim?.addEventListener('click', e => {\n    e.preventDefault();\n\n    // find any active submenus and close them\n    const activeSubnavs = document.querySelectorAll('.go-NavigationDrawer-submenuItem.is-active');\n    activeSubnavs.forEach(subnav => handleNavigationDrawerInactive(subnav as HTMLElement));\n\n    handleNavigationDrawerInactive(header);\n\n    headerbuttons.forEach(button => {\n      button.setAttribute(\n        'aria-expanded',\n        header?.classList.contains('is-active') ? 'true' : 'false'\n      );\n    });\n  });\n\n  const getNavigationDrawerMenuItems = (navigationDrawer: HTMLElement): HTMLElement[] => {\n    if (!navigationDrawer) {\n      return [];\n    }\n\n    const menuItems = Array.from(\n      navigationDrawer.querySelectorAll(\n        ':scope > .go-NavigationDrawer-nav > .go-NavigationDrawer-list > .go-NavigationDrawer-listItem > a, :scope > .go-NavigationDrawer-nav > .go-NavigationDrawer-list > .go-NavigationDrawer-listItem > .go-Header-socialIcons > a'\n      ) || []\n    );\n\n    const anchorEl = navigationDrawer.querySelector('.go-NavigationDrawer-header > a');\n    if (anchorEl) {\n      menuItems.unshift(anchorEl);\n    }\n    return menuItems as HTMLElement[];\n  };\n\n  const getNavigationDrawerIsSubnav = (navigationDrawer: HTMLElement) => {\n    if (!navigationDrawer) {\n      return;\n    }\n    return navigationDrawer.classList.contains('go-NavigationDrawer-submenuItem');\n  };\n\n  const handleNavigationDrawerInactive = (navigationDrawer: HTMLElement) => {\n    if (!navigationDrawer) {\n      return;\n    }\n    const menuItems = getNavigationDrawerMenuItems(navigationDrawer);\n    navigationDrawer.classList.remove('is-active');\n    const parentMenuItem = navigationDrawer\n      .closest('.go-NavigationDrawer-listItem')\n      ?.querySelector(':scope > a') as HTMLElement;\n    parentMenuItem?.focus();\n    menuItems?.forEach(item => item?.setAttribute('tabindex', '-1'));\n    if (menuItems && menuItems[0]) {\n      menuItems[0].removeEventListener('keydown', handleMenuItemTabLeftFactory(navigationDrawer));\n      menuItems[menuItems.length - 1].removeEventListener(\n        'keydown',\n        handleMenuItemTabRightFactory(navigationDrawer)\n      );\n    }\n\n    if (navigationDrawer === header) {\n      headerbuttons && (headerbuttons[0] as HTMLElement)?.focus();\n    }\n  };\n\n  const handleNavigationDrawerActive = (navigationDrawer: HTMLElement) => {\n    const menuItems = getNavigationDrawerMenuItems(navigationDrawer);\n\n    navigationDrawer.classList.add('is-active');\n    menuItems.forEach(item => item.setAttribute('tabindex', '0'));\n    menuItems[0].focus();\n\n    menuItems[0].addEventListener('keydown', handleMenuItemTabLeftFactory(navigationDrawer));\n    menuItems[menuItems.length - 1].addEventListener(\n      'keydown',\n      handleMenuItemTabRightFactory(navigationDrawer)\n    );\n  };\n\n  const handleMenuItemTabLeftFactory = (navigationDrawer: HTMLElement) => {\n    return (e: KeyboardEvent) => {\n      if (e.key === 'Tab' && e.shiftKey) {\n        e.preventDefault();\n        handleNavigationDrawerInactive(navigationDrawer);\n      }\n    };\n  };\n\n  const handleMenuItemTabRightFactory = (navigationDrawer: HTMLElement) => {\n    return (e: KeyboardEvent) => {\n      if (e.key === 'Tab' && !e.shiftKey) {\n        e.preventDefault();\n        handleNavigationDrawerInactive(navigationDrawer);\n      }\n    };\n  };\n\n  const prepMobileNavigationDrawer = (navigationDrawer: HTMLElement) => {\n    const isSubnav = getNavigationDrawerIsSubnav(navigationDrawer);\n    const menuItems = getNavigationDrawerMenuItems(navigationDrawer);\n    navigationDrawer.addEventListener('keyup', e => {\n      if (e.key === 'Escape') {\n        handleNavigationDrawerInactive(navigationDrawer);\n      }\n    });\n\n    menuItems.forEach(item => {\n      const parentLi = item.closest('li');\n      if (parentLi && parentLi.classList.contains('js-mobile-subnav-trigger')) {\n        const submenu = parentLi.querySelector('.go-NavigationDrawer-submenuItem') as HTMLElement;\n        item.addEventListener('click', () => {\n          handleNavigationDrawerActive(submenu);\n        });\n      }\n    });\n    if (isSubnav) {\n      handleNavigationDrawerInactive(navigationDrawer);\n      navigationDrawer\n        ?.querySelector('.go-NavigationDrawer-header')\n        ?.addEventListener('click', e => {\n          e.preventDefault();\n          handleNavigationDrawerInactive(navigationDrawer);\n        });\n    }\n  };\n\n  document\n    .querySelectorAll('.go-NavigationDrawer')\n    .forEach(drawer => prepMobileNavigationDrawer(drawer as HTMLElement));\n\n  handleNavigationDrawerInactive(header);\n}\n\nexport function registerSearchFormListeners(): void {\n  const searchForm = document.querySelector('.js-searchForm');\n  const expandSearch = document.querySelector('.js-expandSearch');\n  const input = searchForm?.querySelector('input');\n  const headerLogo = document.querySelector('.js-headerLogo');\n  const menuButton = document.querySelector('.js-headerMenuButton');\n  expandSearch?.addEventListener('click', () => {\n    searchForm?.classList.add('go-SearchForm--expanded');\n    headerLogo?.classList.add('go-Header-logo--hidden');\n    menuButton?.classList.add('go-Header-navOpen--hidden');\n    input?.focus();\n  });\n  document?.addEventListener('click', e => {\n    if (!searchForm?.contains(e.target as Node)) {\n      searchForm?.classList.remove('go-SearchForm--expanded');\n      headerLogo?.classList.remove('go-Header-logo--hidden');\n      menuButton?.classList.remove('go-Header-navOpen--hidden');\n    }\n  });\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * Carousel Controller adds event listeners, accessibility enhancements, and\n * control elements to a carousel component.\n */\nexport class CarouselController {\n  /**\n   * slides is a collection of slides in the carousel.\n   */\n  private slides: HTMLLIElement[];\n  /**\n   * dots is a collection of dot navigation controls, added to the carousel\n   * by this controller.\n   */\n  private dots: HTMLElement[];\n  /**\n   * liveRegion is a visually hidden element that notifies assitive devices\n   * of visual changes to the carousel. They are added to the carousel by\n   * this controller.\n   */\n  private liveRegion: HTMLElement;\n  /**\n   * activeIndex is the 0-index of the currently active slide.\n   */\n  private activeIndex: number;\n\n  constructor(private el: HTMLElement) {\n    this.slides = Array.from(el.querySelectorAll('.go-Carousel-slide'));\n    this.dots = [];\n    this.liveRegion = document.createElement('div');\n    this.activeIndex = Number(el.getAttribute('data-slide-index') ?? 0);\n\n    this.initSlides();\n    this.initArrows();\n    this.initDots();\n    this.initLiveRegion();\n  }\n\n  private initSlides() {\n    for (const [i, v] of this.slides.entries()) {\n      if (i === this.activeIndex) continue;\n      v.setAttribute('aria-hidden', 'true');\n    }\n  }\n\n  private initArrows() {\n    const arrows = document.createElement('ul');\n    arrows.classList.add('go-Carousel-arrows');\n    arrows.innerHTML = `\n      <li>\n        <button class=\"go-Carousel-prevSlide\" aria-label=\"Go to previous slide\">\n          <img class=\"go-Icon\" height=\"24\" width=\"24\" src=\"/static/shared/icon/arrow_left_gm_grey_24dp.svg\" alt=\"\">\n        </button>\n      </li>\n      <li>\n        <button class=\"go-Carousel-nextSlide\" aria-label=\"Go to next slide\">\n          <img class=\"go-Icon\" height=\"24\" width=\"24\" src=\"/static/shared/icon/arrow_right_gm_grey_24dp.svg\" alt=\"\">\n        </button>\n      </li>\n    `;\n    arrows\n      .querySelector('.go-Carousel-prevSlide')\n      ?.addEventListener('click', () => this.setActive(this.activeIndex - 1));\n    arrows\n      .querySelector('.go-Carousel-nextSlide')\n      ?.addEventListener('click', () => this.setActive(this.activeIndex + 1));\n    this.el.append(arrows);\n  }\n\n  private initDots() {\n    const dots = document.createElement('ul');\n    dots.classList.add('go-Carousel-dots');\n    for (let i = 0; i < this.slides.length; i++) {\n      const li = document.createElement('li');\n      const button = document.createElement('button');\n      button.classList.add('go-Carousel-dot');\n      if (i === this.activeIndex) {\n        button.classList.add('go-Carousel-dot--active');\n      }\n      button.innerHTML = `<span class=\"go-Carousel-obscured\">Slide ${i + 1}</span>`;\n      button.addEventListener('click', () => this.setActive(i));\n      li.append(button);\n      dots.append(li);\n      this.dots.push(button);\n    }\n    this.el.append(dots);\n  }\n\n  private initLiveRegion() {\n    this.liveRegion.setAttribute('aria-live', 'polite');\n    this.liveRegion.setAttribute('aria-atomic', 'true');\n    this.liveRegion.setAttribute('class', 'go-Carousel-obscured');\n    this.liveRegion.textContent = `Slide ${this.activeIndex + 1} of ${this.slides.length}`;\n    this.el.appendChild(this.liveRegion);\n  }\n\n  private setActive = (index: number) => {\n    this.activeIndex = (index + this.slides.length) % this.slides.length;\n    this.el.setAttribute('data-slide-index', String(this.activeIndex));\n    for (const d of this.dots) {\n      d.classList.remove('go-Carousel-dot--active');\n    }\n    this.dots[this.activeIndex].classList.add('go-Carousel-dot--active');\n    for (const s of this.slides) {\n      s.setAttribute('aria-hidden', 'true');\n    }\n    this.slides[this.activeIndex].removeAttribute('aria-hidden');\n    this.liveRegion.textContent = 'Slide ' + (this.activeIndex + 1) + ' of ' + this.slides.length;\n  };\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This class decorates an element to copy arbitrary data attached via a data-\n * attribute to the clipboard.\n */\nexport class ClipboardController {\n  /**\n   * The data to be copied to the clipboard.\n   */\n  private data: string;\n\n  /**\n   * @param el The element that will trigger copying text to the clipboard. The text is\n   * expected to be within its data-to-copy attribute.\n   */\n  constructor(private el: HTMLButtonElement) {\n    this.data = el.dataset['toCopy'] ?? el.innerText;\n    // if data-to-copy is empty and the button is part of an input group\n    // capture the value of the input.\n    if (!this.data && el.parentElement?.classList.contains('go-InputGroup')) {\n      this.data = (this.data || el.parentElement?.querySelector('input')?.value) ?? '';\n    }\n    el.addEventListener('click', e => this.handleCopyClick(e));\n  }\n\n  /**\n   * Handles when the primary element is clicked.\n   */\n  handleCopyClick(e: MouseEvent): void {\n    e.preventDefault();\n    const TOOLTIP_SHOW_DURATION_MS = 1000;\n\n    // This API is not available on iOS.\n    if (!navigator.clipboard) {\n      this.showTooltipText('Unable to copy', TOOLTIP_SHOW_DURATION_MS);\n      return;\n    }\n    navigator.clipboard\n      .writeText(this.data)\n      .then(() => {\n        this.showTooltipText('Copied!', TOOLTIP_SHOW_DURATION_MS);\n      })\n      .catch(() => {\n        this.showTooltipText('Unable to copy', TOOLTIP_SHOW_DURATION_MS);\n      });\n  }\n\n  /**\n   * Shows the given text in a tooltip for a specified amount of time, in milliseconds.\n   */\n  showTooltipText(text: string, durationMs: number): void {\n    this.el.setAttribute('data-tooltip', text);\n    setTimeout(() => this.el.setAttribute('data-tooltip', ''), durationMs);\n  }\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * ToolTipController handles closing tooltips on external clicks.\n */\nexport class ToolTipController {\n  constructor(private el: HTMLDetailsElement) {\n    document.addEventListener('click', e => {\n      const insideTooltip = this.el.contains(e.target as Element);\n      if (!insideTooltip) {\n        this.el.removeAttribute('open');\n      }\n    });\n  }\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { TreeNavController } from './tree.js';\n\nexport class SelectNavController {\n  constructor(private el: Element) {\n    this.el.addEventListener('change', e => {\n      const target = e.target as HTMLSelectElement;\n      let href = target.value;\n      if (!target.value.startsWith('/')) {\n        href = '/' + href;\n      }\n      window.location.href = href;\n    });\n  }\n}\n\nexport function makeSelectNav(tree: TreeNavController): HTMLLabelElement {\n  const label = document.createElement('label');\n  label.classList.add('go-Label');\n  label.setAttribute('aria-label', 'Menu');\n  const select = document.createElement('select');\n  select.classList.add('go-Select', 'js-selectNav');\n  label.appendChild(select);\n  const outline = document.createElement('optgroup');\n  outline.label = 'Outline';\n  select.appendChild(outline);\n  const groupMap: Record<string, HTMLOptGroupElement> = {};\n  let group: HTMLOptGroupElement;\n  for (const t of tree.treeitems) {\n    if (Number(t.depth) > 4) continue;\n    if (t.groupTreeitem) {\n      group = groupMap[t.groupTreeitem.label];\n      if (!group) {\n        group = groupMap[t.groupTreeitem.label] = document.createElement('optgroup');\n        group.label = t.groupTreeitem.label;\n        select.appendChild(group);\n      }\n    } else {\n      group = outline;\n    }\n    const o = document.createElement('option');\n    o.label = t.label;\n    o.textContent = t.label;\n    o.value = (t.el as HTMLAnchorElement).href.replace(window.location.origin, '').replace('/', '');\n    group.appendChild(o);\n  }\n  tree.addObserver(t => {\n    const hash = (t.el as HTMLAnchorElement).hash;\n    const value = select.querySelector<HTMLOptionElement>(`[value$=\"${hash}\"]`)?.value;\n    if (value) {\n      select.value = value;\n    }\n  }, 50);\n  return label;\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\ninterface Window {\n  dialogPolyfill?: {\n    registerDialog: (el: HTMLDialogElement) => void;\n  };\n}\n\ndeclare const window: Window;\n\n/**\n * ModalController registers a dialog element with the polyfill if\n * necessary for the current browser, add adds event listeners to\n * close and open modals.\n */\nexport class ModalController {\n  constructor(private el: HTMLDialogElement) {\n    if (window.dialogPolyfill) {\n      window.dialogPolyfill.registerDialog(el);\n    }\n    this.init();\n  }\n\n  init() {\n    const button = document.querySelector<HTMLButtonElement>(`[aria-controls=\"${this.el.id}\"]`);\n    if (button) {\n      button.addEventListener('click', () => {\n        if (this.el.showModal) {\n          this.el.showModal();\n        } else {\n          this.el.setAttribute('opened', 'true');\n        }\n        this.el.querySelector('input')?.focus();\n      });\n    }\n    for (const btn of this.el.querySelectorAll<HTMLButtonElement>('[data-modal-close]')) {\n      btn.addEventListener('click', () => {\n        if (this.el.close) {\n          this.el.close();\n        } else {\n          this.el.removeAttribute('opened');\n        }\n      });\n    }\n  }\n}\n", "interface TagManagerEvent {\n  /**\n   * event is the name of the event, used to filter events in\n   * Google Analytics.\n   */\n  event: string;\n\n  /**\n   * event_category is a name that you supply as a way to group objects\n   * that to analyze. Typically, you will use the same category name\n   * multiple times over related UI elements (buttons, links, etc).\n   */\n  event_category?: string;\n\n  /**\n   * event_action is used to name the type of event or interaction you\n   * want to measure for a particular web object. For example, with a\n   * single \"form\" category, you can analyze a number of specific events\n   * with this parameter, such as: form entered, form submitted.\n   */\n  event_action?: string;\n\n  /**\n   * event_label provide additional information for events that you want\n   * to analyze, such as the text label of a link.\n   */\n  event_label?: string;\n\n  /**\n   * gtm.start is used to initialize Google Tag Manager.\n   */\n  'gtm.start'?: number;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ndeclare global {\n  interface Window {\n    dataLayer?: (TagManagerEvent | VoidFunction)[];\n    ga?: unknown;\n  }\n}\n\n/**\n * track sends events to Google Tag Manager.\n */\nexport function track(\n  event: string | TagManagerEvent,\n  category?: string,\n  action?: string,\n  label?: string\n): void {\n  window.dataLayer ??= [];\n  if (typeof event === 'string') {\n    window.dataLayer.push({\n      event,\n      event_category: category,\n      event_action: action,\n      event_label: label,\n    });\n  } else {\n    window.dataLayer.push(event);\n  }\n}\n\n/**\n * func adds functions to run sequentionally after\n * Google Tag Manager is ready.\n */\nexport function func(fn: () => void): void {\n  window.dataLayer ??= [];\n  window.dataLayer.push(fn);\n}\n", "/*!\n * @license\n * Copyright 2019-2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { track } from '../analytics/analytics';\n\n/**\n * Options are keyhandler callback options.\n */\ninterface Options {\n  /**\n   * target is the element the key event should filter on. The\n   * default target is the document.\n   */\n  target?: Element;\n\n  /**\n   * withMeta specifies if the event callback should fire when\n   * the key is pressed with a meta key (ctrl, alt, etc). By\n   * default meta keypresses are ignored.\n   */\n  withMeta?: boolean;\n}\n\n/**\n * KeyHandler is the config for a keyboard event callback.\n */\ninterface KeyHandler extends Options {\n  description: string;\n  callback: (e: KeyboardEvent) => void;\n}\n\n/**\n * KeyboardController controls event callbacks for sitewide\n * keyboard events. Multiple callbacks can be registered for\n * a single key and by default the controller ignores events\n * for text input targets.\n */\nclass KeyboardController {\n  handlers: Record<string, Set<KeyHandler>>;\n\n  constructor() {\n    this.handlers = {};\n    document.addEventListener('keydown', e => this.handleKeyPress(e));\n  }\n\n  /**\n   * on registers keyboard event callbacks.\n   * @param key the key to register.\n   * @param description name of the event.\n   * @param callback event callback.\n   * @param options set target and withMeta options to override the default behaviors.\n   */\n  on(key: string, description: string, callback: (e: KeyboardEvent) => void, options?: Options) {\n    this.handlers[key] ??= new Set();\n    this.handlers[key].add({ description, callback, ...options });\n    return this;\n  }\n\n  private handleKeyPress(e: KeyboardEvent) {\n    for (const handler of this.handlers[e.key.toLowerCase()] ?? new Set()) {\n      if (handler.target && handler.target !== e.target) {\n        return;\n      }\n      const t = e.target as HTMLElement | null;\n      if (\n        !handler.target &&\n        (t?.tagName === 'INPUT' || t?.tagName === 'SELECT' || t?.tagName === 'TEXTAREA')\n      ) {\n        return;\n      }\n      if (t?.isContentEditable) {\n        return;\n      }\n      if (\n        (handler.withMeta && !(e.ctrlKey || e.metaKey)) ||\n        (!handler.withMeta && (e.ctrlKey || e.metaKey))\n      ) {\n        return;\n      }\n      track('keypress', 'hotkeys', `${e.key} pressed`, handler.description);\n      handler.callback(e);\n    }\n  }\n}\n\nexport const keyboard = new KeyboardController();\n", "/*!\n * @license\n * Copyright 2019-2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n// This file implements the behavior of the \"jump to symbol\" dialog for Go\n// package documentation, as well as the simple dialog that displays keyboard\n// shortcuts.\n\n// The DOM for the dialogs is at the bottom of static/frontend/unit/main/_modals.tmpl.\n// The CSS is in static/frontend/unit/main/_modals.css.\n\n// The dialog is activated by pressing the 'f' key. It presents a list\n// (#JumpDialog-list) of all Go symbols displayed in the documentation.\n// Entering text in the dialog's text box (#JumpDialog-filter) restricts the\n// list to symbols containing the text. Clicking on an symbol jumps to\n// its documentation.\n\n// This code is based on\n// https://go.googlesource.com/gddo/+/refs/heads/master/gddo-server/assets/site.js.\n// It was modified to remove the dependence on jquery and bootstrap.\n\nimport { keyboard } from '../keyboard/keyboard';\n\nexport function initModals(): void {\n  const jumpDialog = document.querySelector<HTMLDialogElement>('.JumpDialog');\n  const jumpBody = jumpDialog?.querySelector<HTMLDivElement>('.JumpDialog-body');\n  const jumpList = jumpDialog?.querySelector<HTMLDivElement>('.JumpDialog-list');\n  const jumpFilter = jumpDialog?.querySelector<HTMLInputElement>('.JumpDialog-input');\n  const doc = document.querySelector<HTMLDivElement>('.js-documentation');\n\n  interface JumpListItem {\n    link: HTMLAnchorElement;\n    name: string;\n    kind: string;\n    lower: string;\n  }\n\n  let jumpListItems: JumpListItem[] | undefined; // All the symbols in the doc; computed only once.\n\n  // collectJumpListItems returns a list of items, one for each symbol in the\n  // documentation on the current page.\n  //\n  // It uses the data-kind attribute generated in the documentation HTML to find\n  // the symbols and their id attributes.\n  //\n  // If there are no data-kind attributes, then we have older doc; fall back to\n  // a less precise method.\n  function collectJumpListItems() {\n    const items = [];\n    if (!doc) return;\n    for (const el of doc.querySelectorAll('[data-kind]')) {\n      items.push(newJumpListItem(el));\n    }\n\n    // Clicking on any of the links closes the dialog.\n    for (const item of items) {\n      item.link.addEventListener('click', function () {\n        jumpDialog?.close();\n      });\n    }\n    // Sort case-insensitively by symbol name.\n    items.sort(function (a, b) {\n      return a.lower.localeCompare(b.lower);\n    });\n    return items;\n  }\n\n  // newJumpListItem creates a new item for the DOM element el.\n  // An item is an object with:\n  // - name: the element's id (which is the symbol name)\n  // - kind: the element's kind (function, variable, etc.),\n  // - link: a link ('a' tag) to the element\n  // - lower: the name in lower case, just for sorting\n  function newJumpListItem(el: Element): JumpListItem {\n    const a = document.createElement('a');\n    const name = el.getAttribute('id');\n    a.setAttribute('href', '#' + name);\n    a.setAttribute('tabindex', '-1');\n    a.setAttribute('data-gtmc', 'jump to link');\n    const kind = el.getAttribute('data-kind');\n    return {\n      link: a,\n      name: name ?? '',\n      kind: kind ?? '',\n      lower: name?.toLowerCase() ?? '', // for sorting\n    };\n  }\n\n  let lastFilterValue: string; // The last contents of the filter text box.\n  let activeJumpItem = -1; // The index of the currently active item in the list.\n\n  // updateJumpList sets the elements of the dialog list to\n  // everything whose name contains filter.\n  function updateJumpList(filter: string) {\n    lastFilterValue = filter;\n    if (!jumpListItems) {\n      jumpListItems = collectJumpListItems();\n    }\n    setActiveJumpItem(-1);\n\n    // Remove all children from list.\n    while (jumpList?.firstChild) {\n      jumpList.firstChild.remove();\n    }\n\n    if (filter) {\n      // A filter is set. We treat the filter as a substring that can appear in\n      // an item name (case insensitive), and find the following matches - in\n      // order of priority:\n      //\n      // 1. Exact matches (the filter matches the item's name exactly)\n      // 2. Prefix matches (the item's name starts with filter)\n      // 3. Infix matches (the filter is a substring of the item's name)\n      const filterLowerCase = filter.toLowerCase();\n\n      const exactMatches = [];\n      const prefixMatches = [];\n      const infixMatches = [];\n\n      // makeLinkHtml creates the link name HTML for a list item. item is the DOM\n      // item. item.name.substr(boldStart, boldEnd) will be bolded.\n      const makeLinkHtml = (item: JumpListItem, boldStart: number, boldEnd: number) => {\n        return (\n          item.name.substring(0, boldStart) +\n          '<b>' +\n          item.name.substring(boldStart, boldEnd) +\n          '</b>' +\n          item.name.substring(boldEnd)\n        );\n      };\n\n      for (const item of jumpListItems ?? []) {\n        const nameLowerCase = item.name.toLowerCase();\n\n        if (nameLowerCase === filterLowerCase) {\n          item.link.innerHTML = makeLinkHtml(item, 0, item.name.length);\n          exactMatches.push(item);\n        } else if (nameLowerCase.startsWith(filterLowerCase)) {\n          item.link.innerHTML = makeLinkHtml(item, 0, filter.length);\n          prefixMatches.push(item);\n        } else {\n          const index = nameLowerCase.indexOf(filterLowerCase);\n          if (index > -1) {\n            item.link.innerHTML = makeLinkHtml(item, index, index + filter.length);\n            infixMatches.push(item);\n          }\n        }\n      }\n\n      for (const item of exactMatches.concat(prefixMatches).concat(infixMatches)) {\n        jumpList?.appendChild(item.link);\n      }\n    } else {\n      if (!jumpListItems || jumpListItems.length === 0) {\n        const msg = document.createElement('i');\n        msg.innerHTML = 'There are no symbols on this page.';\n        jumpList?.appendChild(msg);\n      }\n      // No filter set; display all items in their existing order.\n      for (const item of jumpListItems ?? []) {\n        item.link.innerHTML = item.name + ' <i>' + item.kind + '</i>';\n        jumpList?.appendChild(item.link);\n      }\n    }\n\n    if (jumpBody) {\n      jumpBody.scrollTop = 0;\n    }\n    if (jumpListItems?.length && jumpList && jumpList.children.length > 0) {\n      setActiveJumpItem(0);\n    }\n  }\n\n  // Set the active jump item to n.\n  function setActiveJumpItem(n: number) {\n    const cs = jumpList?.children as HTMLCollectionOf<HTMLElement> | null | undefined;\n    if (!cs || !jumpBody) {\n      return;\n    }\n    if (activeJumpItem >= 0) {\n      cs[activeJumpItem].classList.remove('JumpDialog-active');\n    }\n    if (n >= cs.length) {\n      n = cs.length - 1;\n    }\n    if (n >= 0) {\n      cs[n].classList.add('JumpDialog-active');\n\n      // Scroll so the active item is visible.\n      // For some reason cs[n].scrollIntoView() doesn't behave as I'd expect:\n      // it moves the entire dialog box in the viewport.\n\n      // Get the top and bottom of the active item relative to jumpBody.\n      const activeTop = cs[n].offsetTop - cs[0].offsetTop;\n      const activeBottom = activeTop + cs[n].clientHeight;\n      if (activeTop < jumpBody.scrollTop) {\n        // Off the top; scroll up.\n        jumpBody.scrollTop = activeTop;\n      } else if (activeBottom > jumpBody.scrollTop + jumpBody.clientHeight) {\n        // Off the bottom; scroll down.\n        jumpBody.scrollTop = activeBottom - jumpBody.clientHeight;\n      }\n    }\n    activeJumpItem = n;\n  }\n\n  // Increment the activeJumpItem by delta.\n  function incActiveJumpItem(delta: number) {\n    if (activeJumpItem < 0) {\n      return;\n    }\n    let n = activeJumpItem + delta;\n    if (n < 0) {\n      n = 0;\n    }\n    setActiveJumpItem(n);\n  }\n\n  // Pressing a key in the filter updates the list (if the filter actually changed).\n  jumpFilter?.addEventListener('keyup', function () {\n    if (jumpFilter.value.toUpperCase() != lastFilterValue.toUpperCase()) {\n      updateJumpList(jumpFilter.value);\n    }\n  });\n\n  // Pressing enter in the filter selects the first element in the list.\n  jumpFilter?.addEventListener('keydown', function (event) {\n    const upArrow = 38;\n    const downArrow = 40;\n    const enterKey = 13;\n    switch (event.which) {\n      case upArrow:\n        incActiveJumpItem(-1);\n        event.preventDefault();\n        break;\n      case downArrow:\n        incActiveJumpItem(1);\n        event.preventDefault();\n        break;\n      case enterKey:\n        if (activeJumpItem >= 0) {\n          if (jumpList) {\n            (jumpList.children[activeJumpItem] as HTMLElement).click();\n            event.preventDefault();\n          }\n        }\n        break;\n    }\n  });\n\n  const shortcutsDialog = document.querySelector<HTMLDialogElement>('.ShortcutsDialog');\n\n  // - Pressing 'f' or 'F' opens the jump-to-symbol dialog.\n  // - Pressing '?' opens up the shortcut dialog.\n  // Ignore a keypress if a dialog is already open, or if it is pressed on a\n  // component that wants to consume it.\n  keyboard\n    .on('f', 'open jump to modal', e => {\n      if (jumpDialog?.open || shortcutsDialog?.open) {\n        return;\n      }\n      e.preventDefault();\n      if (jumpFilter) {\n        jumpFilter.value = '';\n      }\n      jumpDialog?.showModal?.();\n      jumpFilter?.focus();\n      updateJumpList('');\n    })\n    .on('?', 'open shortcuts modal', () => {\n      if (jumpDialog?.open || shortcutsDialog?.open) {\n        return;\n      }\n      shortcutsDialog?.showModal?.();\n    });\n\n  const jumpOutlineInput = document.querySelector('.js-jumpToInput');\n  if (jumpOutlineInput) {\n    jumpOutlineInput.addEventListener('click', () => {\n      if (jumpFilter) {\n        jumpFilter.value = '';\n      }\n      updateJumpList('');\n      if (jumpDialog?.open || shortcutsDialog?.open) {\n        return;\n      }\n      jumpDialog?.showModal?.();\n      jumpFilter?.focus();\n    });\n  }\n\n  document.querySelector('.js-openShortcuts')?.addEventListener('click', () => {\n    shortcutsDialog?.showModal?.();\n  });\n}\n", "/**\n * @license\n * Copyright 2022 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * Left Navigation.\n */\nexport const initJumpLinks = async function () {\n  const pagesWithJumpLinks = ['/about'];\n  if (!pagesWithJumpLinks.includes(window.location.pathname)) {\n    // stop the file from doing anything else if the page doesn't have jumplinks\n    return;\n  }\n\n  // these might be generated or not so don't grab references to the elements until actually need them.\n  const titles = 'h2, h3, h4';\n  const nav = '.LeftNav a';\n  // these are always in the dom so we can get them now and throw errors if they're not.\n  const leftNav = document.querySelector('.LeftNav');\n  const siteContent = document.querySelector('.go-Content');\n  let isObserverDisabled = false;\n\n  /**\n   * El function\n   * @example el('h1', {className: 'title'}, 'Welcome to the site');\n   * @example el('ul', {className: 'list'}, el('li', {}, 'Item one'), el('li', {}, 'Item two'), el('li', {}, 'Item three'));\n   * @example el('img', {src: '/url.svg'});\n   */\n  function el(\n    type = '',\n    props: { [key: string]: string } = {},\n    ...children: (HTMLElement | HTMLElement[] | string | undefined)[]\n  ) {\n    // Error, no type declared.\n    if (!type) {\n      throw new Error('Provide `type` to create document element.');\n    }\n\n    // Create element with optional attribute props\n    const docEl = Object.assign(document.createElement(type), props);\n\n    // Children: array containing strings or elements\n    children.forEach(child => {\n      if (typeof child === 'string') {\n        docEl.appendChild(document.createTextNode(child));\n      } else if (Array.isArray(child)) {\n        child.forEach(c => docEl.appendChild(c));\n      } else if (child instanceof HTMLElement) {\n        docEl.appendChild(child);\n      }\n    });\n\n    return docEl;\n  }\n  /**  Build Nav if data hydrate is present. */\n  function buildNav() {\n    return new Promise((resolve, reject) => {\n      let navItems: { id: string; label: string; subnav?: { id: string; label: string }[] }[] = [];\n      let elements: HTMLElement[] = [];\n\n      if (!siteContent || !leftNav) {\n        return reject('.SiteContent not found.');\n      }\n      if (leftNav instanceof HTMLElement && !leftNav?.dataset?.hydrate) {\n        return resolve(true);\n      }\n\n      for (const title of siteContent.querySelectorAll(titles)) {\n        if (title instanceof HTMLElement && !title?.dataset?.ignore) {\n          switch (title.tagName) {\n            case 'H2':\n              navItems = [\n                ...navItems,\n                {\n                  id: title.id,\n                  label: title?.dataset?.title ? title.dataset.title : title.textContent ?? '',\n                },\n              ];\n              break;\n\n            case 'H3':\n            case 'H4':\n              if (!navItems[navItems.length - 1]?.subnav) {\n                navItems[navItems.length - 1].subnav = [\n                  {\n                    id: title.id,\n                    label: title?.dataset?.title ? title.dataset.title : title.textContent ?? '',\n                  },\n                ];\n              } else if (navItems[navItems.length - 1].subnav) {\n                navItems[navItems.length - 1].subnav?.push({\n                  id: title.id,\n                  label: title?.dataset?.title ? title.dataset.title : title.textContent ?? '',\n                });\n              }\n              break;\n          }\n        }\n      }\n\n      for (const navItem of navItems) {\n        const link = el('a', { href: '#' + navItem.id }, el('span', {}, navItem.label));\n        elements = [...elements, link];\n        if (navItem?.subnav) {\n          let subLinks: HTMLElement[] = [];\n          for (const subnavItem of navItem.subnav) {\n            const subItem = el(\n              'li',\n              {},\n              el(\n                'a',\n                { href: '#' + subnavItem.id },\n                el('img', { src: '/static/frontend/about/dot.svg', width: '5', height: '5' }),\n                el('span', {}, subnavItem.label)\n              )\n            );\n            subLinks = [...subLinks, subItem];\n          }\n          const list = el('ul', { className: 'LeftSubnav' }, subLinks);\n          elements = [...elements, list];\n        }\n      }\n\n      elements.forEach(element => leftNav.appendChild(element));\n\n      return resolve(true);\n    });\n  }\n  /**\n   * Set the correct active element.\n   */\n  function setNav() {\n    return new Promise(resolve => {\n      if (!document.querySelectorAll(nav)) return resolve(true);\n      for (const a of document.querySelectorAll(nav)) {\n        if (a instanceof HTMLAnchorElement && a.href === location.href) {\n          setElementActive(a);\n          break;\n        }\n      }\n      resolve(true);\n    });\n  }\n  /** resetNav: removes all .active from nav elements */\n  function resetNav() {\n    return new Promise(resolve => {\n      if (!document.querySelectorAll(nav)) return resolve(true);\n      for (const a of document.querySelectorAll(nav)) {\n        a.classList.remove('active');\n      }\n      resolve(true);\n    });\n  }\n  /** setElementActive: controls resetting nav and highlighting the appropriate nav items */\n  function setElementActive(element: HTMLAnchorElement) {\n    if (element instanceof HTMLAnchorElement) {\n      resetNav().then(() => {\n        element.classList.add('active');\n        const parent = element?.parentNode?.parentNode;\n        if (parent instanceof HTMLElement && parent?.classList?.contains('LeftSubnav')) {\n          parent.previousElementSibling?.classList.add('active');\n        }\n      });\n    }\n  }\n  /** setLinkManually: disables observer and selects the clicked nav item. */\n  function setLinkManually() {\n    delayObserver();\n    const link = document.querySelector('[href=\"' + location.hash + '\"]');\n    if (link instanceof HTMLAnchorElement) {\n      setElementActive(link);\n    }\n  }\n  /** delayObserver: Quick on off switch for intersection observer. */\n  function delayObserver() {\n    isObserverDisabled = true;\n    setTimeout(() => {\n      isObserverDisabled = false;\n    }, 200);\n  }\n  /** observeSections: kicks off observation of titles as well as manual clicks with hashchange */\n  function observeSections() {\n    window.addEventListener('hashchange', setLinkManually);\n\n    if (siteContent?.querySelectorAll(titles)) {\n      const callback: IntersectionObserverCallback = entries => {\n        if (!isObserverDisabled && Array.isArray(entries) && entries.length > 0) {\n          for (const entry of entries) {\n            if (entry.isIntersecting && entry.target instanceof HTMLElement) {\n              const { id } = entry.target;\n              const link = document.querySelector('[href=\"#' + id + '\"]');\n              if (link instanceof HTMLAnchorElement) {\n                setElementActive(link);\n              }\n              break;\n            }\n          }\n        }\n      };\n      // rootMargin is important when multiple sections are in the observable area **on page load**.\n      // they will still be highlighted on scroll because of the root margin.\n      const ob = new IntersectionObserver(callback, {\n        threshold: 0,\n        rootMargin: '0px 0px -50% 0px',\n      });\n      for (const title of siteContent.querySelectorAll(titles)) {\n        if (title instanceof HTMLElement && !title?.dataset?.ignore) {\n          ob.observe(title);\n        }\n      }\n    }\n  }\n\n  try {\n    await buildNav();\n    await setNav();\n    if (location.hash) {\n      delayObserver();\n    }\n    observeSections();\n  } catch (e) {\n    if (e instanceof Error) {\n      console.error(e.message);\n    } else {\n      console.error(e);\n    }\n  }\n};\n", "/**\n * @license\n * Copyright 2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { registerHeaderListeners, registerSearchFormListeners } from 'static/shared/header/header';\nimport { CarouselController } from 'static/shared/carousel/carousel';\nimport { ClipboardController } from 'static/shared/clipboard/clipboard';\nimport { ToolTipController } from 'static/shared/tooltip/tooltip';\nimport { SelectNavController } from 'static/shared/outline/select';\nimport { ModalController } from 'static/shared/modal/modal';\nimport { initModals } from 'static/shared/jump/jump';\n\nimport { keyboard } from 'static/shared/keyboard/keyboard';\nimport * as analytics from 'static/shared/analytics/analytics';\nimport { initJumpLinks } from './about/index';\n\nwindow.addEventListener('load', () => {\n  for (const el of document.querySelectorAll<HTMLButtonElement>('.js-clipboard')) {\n    new ClipboardController(el);\n  }\n\n  for (const el of document.querySelectorAll<HTMLDialogElement>('.js-modal')) {\n    new ModalController(el);\n  }\n\n  for (const t of document.querySelectorAll<HTMLDetailsElement>('.js-tooltip')) {\n    new ToolTipController(t);\n  }\n\n  for (const el of document.querySelectorAll<HTMLSelectElement>('.js-selectNav')) {\n    new SelectNavController(el);\n  }\n\n  for (const el of document.querySelectorAll<HTMLSelectElement>('.js-carousel')) {\n    new CarouselController(el);\n  }\n\n  for (const el of document.querySelectorAll('.js-toggleTheme')) {\n    el.addEventListener('click', () => {\n      toggleTheme();\n    });\n  }\n\n  if (document.querySelector<HTMLElement>('.js-gtmID')?.dataset.gtmid && window.dataLayer) {\n    analytics.func(function () {\n      removeUTMSource();\n    });\n  } else {\n    removeUTMSource();\n  }\n\n  registerHeaderListeners();\n  registerSearchFormListeners();\n  initModals();\n  initJumpLinks();\n});\n\n// Pressing '/' focuses the search box\nkeyboard.on('/', 'focus search', e => {\n  const searchInput = Array.from(\n    document.querySelectorAll<HTMLInputElement>('.js-searchFocus')\n  ).pop();\n  // Favoring the Firefox quick find feature over search input\n  // focus. See: https://github.com/golang/go/issues/41093.\n  if (searchInput && !window.navigator.userAgent.includes('Firefox')) {\n    e.preventDefault();\n    searchInput.focus();\n  }\n});\n\n// Pressing 'y' changes the browser URL to the canonical URL\n// without triggering a reload.\nkeyboard.on('y', 'set canonical url', () => {\n  let canonicalURLPath = document.querySelector<HTMLDivElement>('.js-canonicalURLPath')?.dataset[\n    'canonicalUrlPath'\n  ];\n  if (canonicalURLPath && canonicalURLPath !== '') {\n    const fragment = window.location.hash;\n    if (fragment) {\n      canonicalURLPath += fragment;\n    }\n    window.history.replaceState(null, '', canonicalURLPath);\n  }\n});\n\n/**\n * setupGoogleTagManager initializes Google Tag Manager.\n */\n(function setupGoogleTagManager() {\n  analytics.track({\n    'gtm.start': new Date().getTime(),\n    event: 'gtm.js',\n  });\n})();\n\n/**\n * removeUTMSource removes the utm_source GET parameter if present.\n * This is done using JavaScript, so that the utm_source is still\n * captured by Google Analytics.\n */\nfunction removeUTMSource() {\n  const urlParams = new URLSearchParams(window.location.search);\n  const utmSource = urlParams.get('utm_source');\n  if (utmSource !== 'gopls' && utmSource !== 'godoc' && utmSource !== 'pkggodev') {\n    return;\n  }\n\n  /** Strip the utm_source query parameter and replace the URL. **/\n  const newURL = new URL(window.location.href);\n  urlParams.delete('utm_source');\n  newURL.search = urlParams.toString();\n  window.history.replaceState(null, '', newURL.toString());\n}\n\n/**\n * toggleTheme switches the preferred color scheme between auto, light, and dark.\n */\nfunction toggleTheme() {\n  let nextTheme = 'dark';\n  const theme = document.documentElement.getAttribute('data-theme');\n  if (theme === 'dark') {\n    nextTheme = 'light';\n  } else if (theme === 'light') {\n    nextTheme = 'auto';\n  }\n  let domain = '';\n  if (location.hostname.endsWith('go.dev')) {\n    domain = 'domain=.go.dev;';\n  }\n  document.documentElement.setAttribute('data-theme', nextTheme);\n  document.cookie = `prefers-color-scheme=${nextTheme};${domain}path=/;max-age=31536000;`;\n}\n"],
+  "mappings": "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",
+  "names": ["registerHeaderListeners", "header", "menuItemHover", "e", "target", "forced", "toggleForcedOpen", "_a", "_b", "isForced", "currentTarget", "event", "headerbuttons", "button", "isActive", "handleNavigationDrawerInactive", "handleNavigationDrawerActive", "scrim", "subnav", "getNavigationDrawerMenuItems", "navigationDrawer", "menuItems", "anchorEl", "getNavigationDrawerIsSubnav", "parentMenuItem", "item", "handleMenuItemTabLeftFactory", "handleMenuItemTabRightFactory", "prepMobileNavigationDrawer", "isSubnav", "parentLi", "submenu", "drawer", "registerSearchFormListeners", "searchForm", "expandSearch", "input", "headerLogo", "menuButton", "CarouselController", "el", "index", "d", "s", "_a", "i", "v", "_b", "arrows", "dots", "li", "button", "ClipboardController", "el", "_a", "_b", "_c", "_d", "_e", "e", "TOOLTIP_SHOW_DURATION_MS", "text", "durationMs", "ToolTipController", "el", "e", "SelectNavController", "el", "e", "target", "href", "ModalController", "el", "button", "_a", "btn", "track", "event", "category", "action", "label", "_a", "func", "fn", "KeyboardController", "key", "description", "callback", "options", "_a", "_b", "handler", "t", "track", "keyboard", "initModals", "_a", "jumpDialog", "jumpBody", "jumpList", "jumpFilter", "doc", "jumpListItems", "collectJumpListItems", "items", "el", "newJumpListItem", "item", "a", "b", "name", "kind", "lastFilterValue", "activeJumpItem", "updateJumpList", "filter", "setActiveJumpItem", "filterLowerCase", "exactMatches", "prefixMatches", "infixMatches", "makeLinkHtml", "boldStart", "boldEnd", "nameLowerCase", "index", "msg", "n", "cs", "activeTop", "activeBottom", "incActiveJumpItem", "delta", "event", "shortcutsDialog", "keyboard", "e", "jumpOutlineInput", "initJumpLinks", "titles", "nav", "leftNav", "siteContent", "isObserverDisabled", "el", "type", "props", "children", "docEl", "child", "c", "buildNav", "resolve", "reject", "_a", "_b", "_c", "_d", "_e", "_f", "_g", "_h", "_i", "_j", "navItems", "elements", "title", "navItem", "link", "subLinks", "subnavItem", "subItem", "list", "element", "setNav", "a", "setElementActive", "resetNav", "parent", "setLinkManually", "delayObserver", "observeSections", "callback", "entries", "entry", "id", "ob", "e", "_a", "el", "ClipboardController", "ModalController", "t", "ToolTipController", "SelectNavController", "CarouselController", "toggleTheme", "func", "removeUTMSource", "registerHeaderListeners", "registerSearchFormListeners", "initModals", "initJumpLinks", "keyboard", "e", "searchInput", "canonicalURLPath", "fragment", "track", "urlParams", "utmSource", "newURL", "nextTheme", "theme", "domain"]
 }
diff --git a/tests/screentest/testdata/about.a.png b/tests/screentest/testdata/about.a.png
index 6dd0a0a..76b3be4 100644
--- a/tests/screentest/testdata/about.a.png
+++ b/tests/screentest/testdata/about.a.png
Binary files differ