_content: add dark mode to go.dev/tour

Change-Id: I8fe87632b3f863fc80290537a428c884a232f280
Reviewed-on: https://go-review.googlesource.com/c/website/+/509116
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: Jamal Carvalho <jamal@golang.org>
Run-TryBot: Jamal Carvalho <jamal@golang.org>
Auto-Submit: Jamal Carvalho <jamal@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/_content/tour/static/css/app.css b/_content/tour/static/css/app.css
index 901c532..909c7d0 100755
--- a/_content/tour/static/css/app.css
+++ b/_content/tour/static/css/app.css
@@ -12,6 +12,9 @@
     -webkit-text-size-adjust: none;
     -webkit-font-smoothing: antialiased;
 }
+[data-theme='dark'] body {
+    background-color: #2B2D2F;
+}
 * {
     outline: none;
 }
@@ -19,6 +22,15 @@
     color: #375eab;
     text-decoration: none;
 }
+[data-theme='dark'] a {
+    color: #53B4DB;
+}
+[data-theme='dark'] a:hover {
+    text-decoration: underline;
+}
+[data-theme='dark'] p {
+    color: #F0F1F2;
+}
 .gopherlogo {
   height: 2rem;
   margin-right: 2.25rem;
@@ -32,12 +44,19 @@
     line-height: 32px;
     margin: 0;
 }
+[data-theme='dark'] h1, [data-theme='dark'] h2, [data-theme='dark'] h3, [data-theme='dark'] h4 {
+    color: #F0F1F2;
+}
 pre, code {
     font-family: 'Inconsolata', monospace;
     border-radius: 4px;
     color: #333;
     background-color: #fafafa;
 }
+[data-theme='dark'] code, [data-theme='dark'] .info {
+    background-color: #2B2D2F !important;
+    color: #BABABA;
+}
 pre {
     padding: 10px;
 }
@@ -50,10 +69,13 @@
     margin-right: 10px;
 }
 .right {
-    display: block;
+    display: flex;
     float: right;
     margin-left: 10px;
 }
+.right * {
+    vertical-align: middle;
+}
 .bar {
     display: block;
     overflow: hidden;
@@ -70,6 +92,9 @@
     left: 0;
     right: 0;
 }
+[data-theme='dark'] .wrapper {
+    background: #171717;
+}
 .container {
     max-width: 800px;
     width: 90%;
@@ -77,9 +102,18 @@
     padding: 16px 5%;
     background: #ffffff;
 }
+[data-theme='dark'] .container {
+    background: #171717;
+}
 .container a {
     color: #375eab;
 }
+[data-theme='dark'] .container a {
+    color: #53B4DB;
+}
+[data-theme='dark'] .container p {
+    color: #F0F1F2;
+}
 .relative-content {
     display: block;
     position: relative;
@@ -98,6 +132,9 @@
 li {
     margin: 8px 0;
 }
+[data-theme='dark'] li {
+    color: #F0F1F2;
+}
 ul {
     list-style: none;
     margin: 0;
@@ -156,6 +193,9 @@
     margin: 16px 0;
     position: relative;
 }
+[data-theme='dark'] .lesson {
+    background: #202224;
+}
 .lesson-title {
     display: inline-block;
     font-size: 1.2em;
@@ -168,6 +208,9 @@
     padding: 16px;
     background: #fff;
 }
+[data-theme='dark'] .slide-content {
+    background: #202224;
+}
 .module-bar {
     font-size: 1.5em;
     padding: 8px 0;
@@ -175,12 +218,19 @@
     line-height: 24px;
     font-size: 24px;
 }
+[data-theme='dark'] .module-bar {
+    background: #202224;
+    color: #F0F1F2;
+}
 .module-bar a {
     color: #375eab;
     position: relative;
     font-weight: bold;
     margin: 5px;
 }
+[data-theme='dark'] .module-bar a {
+    color: #53B4DB;
+}
 .menu-button {
     display: inline-block;
     text-decoration: none;
@@ -203,9 +253,21 @@
     border: 1px solid #C6C6C6;
     background-color: #fafafa;
 }
+[data-theme='dark'] .menu-button:hover {
+    background-color: #D9D9D9;
+    color: #53B4DB;
+    text-decoration: none;
+}
+[data-theme='dark'] .menu-button:active {
+    background-color: #202224;
+}
 .menu-button.active {
     background: #fff;
 }
+[data-theme='dark'] .menu-button {
+    background: #3D3D3E;
+    color: #BABABA;
+}
 .menu-button[imports-checkbox]:after {
     content: ' off';
 }
@@ -221,12 +283,29 @@
 #file-menu .menu-button {
     float: right;
 }
+[data-theme='dark'] #file-menu .menu-button {
+    border: 1px solid #202224;
+    color: #53B4DB;
+}
 a#run, a#kill {
     background-color: #375eab;
     color: #fff;
     width: 40px;
     text-align: center;
 }
+[data-theme='dark'] a#run, [data-theme='dark'] a#kill {
+    background-color: #007F9F;
+}
+[data-theme='dark'] a#run:hover, [data-theme='dark'] a#kill:hover {
+    background: #1A5D8359;
+    border: 1px solid #53B4DB;
+    color: #53B4DB;
+}
+[data-theme='dark'] a#run:active, [data-theme='dark'] a#kill:active {
+    background: #1A5D8326;
+    border: 1px solid #007F9F;
+    color: #007F9F;
+}
 #run:hover:not(:active), #kill:hover:not(:active) {
     background-color: #fff;
     color: #375eab;
@@ -242,6 +321,9 @@
 .output .system {
     color: #888;
 }
+[data-theme='dark'] .output .system {
+    color: #F0F1F2;
+}
 .output .stderr {
     color: #D00A0A;
 }
@@ -256,6 +338,9 @@
     padding-left: 30px;
     background: #fafafa;
 }
+[data-theme='dark'] #explorer {
+    background: #171717;
+}
 #explorer .imports-checkbox {
     float: right;
 }
@@ -282,6 +367,10 @@
     font-family: 'Inconsolata', monospace;
     line-height: 1.2em;
 }
+[data-theme='dark'] #file-editor, [data-theme='dark'] #file-editor .CodeMirror, [data-theme='dark'] #file-editor .CodeMirror-lines, [data-theme='dark'] #file-editor .CodeMirror-gutters {
+    background: #253443;
+    color: #BABABA;
+}
 .CodeMirror-code > .line-error {
     background: #FF8080;
 }
@@ -292,6 +381,15 @@
 #file-editor .CodeMirror-gutters {
     width: 32px;
 }
+[data-theme='dark'] .cm-s-default .cm-keyword {
+    color: #B984FF;
+}
+[data-theme='dark'] .cm-s-default .cm-number {
+    color: #63EC8C;
+}
+[data-theme='dark'] .cm-s-default .cm-string {
+    color: #F585C0;
+}
 @media (min-width: 601px) {
     #editor-container {
         position: fixed;
@@ -316,6 +414,9 @@
         background-position: bottom;
         background-color: #fff;
     }
+    [data-theme='dark'] .output {
+        background-color: #202224;
+    }
     div[vertical-slide] {
         position: absolute;
         top: 0px;
@@ -327,6 +428,9 @@
         z-index: 100;
         cursor: move;
     }
+    [data-theme='dark'] div[vertical-slide] {
+        background: #171717;
+    }
     #right-side {
         position: absolute;
         top: 0;
@@ -335,6 +439,9 @@
         left: 50%;
         background: #fff;
     }
+    [data-theme='dark'] #right-side {
+        background: #202224;
+    }
     .slide-content {
         position: absolute;
         left: 0;
@@ -376,6 +483,9 @@
         z-index: 100;
         cursor: move;
     }
+    [data-theme='dark'] div[horizontal-slide] {
+        background: #171717;
+    }
     #bottom-part {
         position: absolute;
         left: 0;
@@ -401,9 +511,12 @@
         left: 0;
         background: #fafafa;
     }
+    [data-theme='dark'] #file-menu {
+        background: #171717;
+    }
     .output {
         position: absolute;
-        top: 34px;
+        top: 32px;
         bottom: 0;
         left: 0;
         right: 0;
@@ -477,6 +590,11 @@
     -ms-user-select: none;
     user-select: none;
 }
+[data-theme='dark'] .toc {
+    background: #171717;
+    border-left: 4px solid #171717;
+    border-bottom: 4px solid #171717;
+}
 .click-catcher {
     position: fixed;
     z-index: -100;
@@ -499,6 +617,14 @@
     color: #375eab;
     background: #e0ebf5;
 }
+[data-theme='dark'] .toc-module {
+    color: #53B4DB;
+    background: #171717;
+}
+[data-theme='dark'] .toc-module li {
+    color: #F0F1F2;
+    background: #2B2D2F;
+}
 .toc-lesson {
     background: #fafafa;
     color: #333;
@@ -534,3 +660,36 @@
         display: none;
     }
 }
+
+.header-toggleTheme [data-value] {
+    display: none;
+}
+
+[data-theme='auto'] .header-toggleTheme [data-value='auto'] {
+    display: block;
+}
+
+[data-theme='dark'] .header-toggleTheme [data-value='dark'] {
+    display: block;
+}
+
+[data-theme='light'] .header-toggleTheme [data-value='light'] {
+    display: block;
+}
+
+.header-toggleTheme {
+    background-color: transparent;
+    border: none;
+    cursor: pointer;
+    font-size: 16px;
+}
+
+.go-Icon {
+    height: 1.125em;
+    vertical-align: text-bottom;
+    width: auto;
+}
+.go-Icon--inverted {
+    filter: brightness(0) saturate(100%) invert(100%) sepia(97%) saturate(13%)
+    hue-rotate(245deg) brightness(103%) contrast(107%);
+}
diff --git a/_content/tour/static/js/page.js b/_content/tour/static/js/page.js
index f4df9b6..dce9189 100644
--- a/_content/tour/static/js/page.js
+++ b/_content/tour/static/js/page.js
@@ -21,3 +21,35 @@
 function click(selector) {
     $(selector)[0].click();
 }
+
+/**
+ * toggleTheme switches the preferred color scheme between auto, light, and dark.
+ */
+function toggleTheme() {
+    let nextTheme = 'dark';
+    const theme = document.documentElement.getAttribute('data-theme');
+    if (theme === 'dark') {
+      nextTheme = 'light';
+    } else if (theme === 'light') {
+      nextTheme = 'auto';
+    }
+    let domain = '';
+    if (location.hostname === 'go.dev') {
+      // Include subdomains to apply the setting to pkg.go.dev.
+      domain = 'domain=.go.dev;';
+    }
+    document.documentElement.setAttribute('data-theme', nextTheme);
+    document.cookie =
+    `prefers-color-scheme=${nextTheme};${domain}path=/;max-age=31536000;`;
+  }
+
+
+function setThemeButtons() {
+    for (const el of document.querySelectorAll('.js-toggleTheme')) {
+      el.addEventListener('click', () => {
+        toggleTheme();
+      });
+    }
+}
+
+setThemeButtons();
diff --git a/_content/tour/static/lib/codemirror/lib/codemirror.css b/_content/tour/static/lib/codemirror/lib/codemirror.css
index b962b38..1bfe006 100644
--- a/_content/tour/static/lib/codemirror/lib/codemirror.css
+++ b/_content/tour/static/lib/codemirror/lib/codemirror.css
@@ -109,7 +109,6 @@
 .cm-em {font-style: italic;}
 .cm-link {text-decoration: underline;}
 .cm-strikethrough {text-decoration: line-through;}
-
 .cm-s-default .cm-keyword {color: #708;}
 .cm-s-default .cm-atom {color: #219;}
 .cm-s-default .cm-number {color: #164;}
diff --git a/_content/tour/template/index.tmpl b/_content/tour/template/index.tmpl
index e72ce27..d8b9261 100755
--- a/_content/tour/template/index.tmpl
+++ b/_content/tour/template/index.tmpl
@@ -1,5 +1,5 @@
 <!doctype html>
-<html lang="en" ng-app="tour">
+<html lang="en" ng-app="tour" data-theme="auto">
 
 <head>
 {{.AnalyticsHTML}}    <meta charset="utf-8">
@@ -7,6 +7,14 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
     <meta name="apple-mobile-web-app-capable" content="yes">
     <meta name="mobile-web-app-capable" content="yes">
+    <script>
+      (function() {
+        const theme = document.cookie.match(/prefers-color-scheme=(light|dark|auto)/)?.[1]
+        if (theme) {
+          document.querySelector('html').setAttribute('data-theme', theme);
+        }
+      }())
+    </script>
     <link rel="stylesheet" href="/tour/static/css/app.css" />
     <link rel="stylesheet" href="/tour/static/lib/codemirror/lib/codemirror.css">
     <link href='https://fonts.googleapis.com/css?family=Inconsolata' rel='stylesheet' type='text/css'>
@@ -21,8 +29,33 @@
         <a href="/"><img src="/images/go-logo-white.svg" class="gopherlogo"></a>
         <a class="logo" href="/tour/list">A Tour of Go</a>
         </div>
-        <div table-of-contents-button=".toc"></div>
-        <div feedback-button></div>
+        <div class="right">
+            <button class="header-toggleTheme js-toggleTheme" aria-label="Toggle theme">
+              <img
+                data-value="auto"
+                class="go-Icon go-Icon--inverted"
+                height="24"
+                width="24"
+                src="/images/icons/brightness_6_gm_grey_24dp.svg"
+                alt="System theme">
+              <img
+                data-value="dark"
+                class="go-Icon go-Icon--inverted"
+                height="24"
+                width="24"
+                src="/images/icons/brightness_2_gm_grey_24dp.svg"
+                alt="Dark theme">
+              <img
+                data-value="light"
+                class="go-Icon go-Icon--inverted"
+                height="24"
+                width="24"
+                src="/images/icons/light_mode_gm_grey_24dp.svg"
+                alt="Light theme">
+            </button>
+            <div table-of-contents-button=".toc"></div>
+            <div feedback-button></div>
+        </div>
     </div>
 
     <div table-of-contents></div>