docs: Use Furo Sphinx theme

- Switch Sphinx theme to https://github.com/pradyunsg/furo
- Apply some custom colors
- Add css styling for audodoc signatures similar to default
  sphinx_rtd_theme
- Remove .. contents:: :local: blocks since this theme has
  a right side local table of contents.
- New pigweed-code-light Pygments theme for use in the
  pw_console and the docs website. Syntax highlighting for
  both matches now.

Change-Id: Iea5daec01d431c0ddffbf11c461493e76dccb710
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/57064
Pigweed-Auto-Submit: Anthony DiGirolamo <tonymd@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
Reviewed-by: Rob Mohr <mohrr@google.com>
diff --git a/docs/BUILD.gn b/docs/BUILD.gn
index b2342bf..872c525 100644
--- a/docs/BUILD.gn
+++ b/docs/BUILD.gn
@@ -177,9 +177,20 @@
   output_directory = target_gen_dir
   deps = [
     ":core_docs",
+    ":install_sphinx_themes",
     ":module_docs",
     ":target_docs",
     ":third_party_docs",
     "$dir_pw_env_setup:python.install",
   ]
 }
+
+# Install Pigweed specific sphinx themes.
+pw_python_action("install_sphinx_themes") {
+  module = "pip"
+  args = [
+    "install",
+    "furo",
+  ]
+  stamp = true
+}
diff --git a/docs/_static/css/pigweed.css b/docs/_static/css/pigweed.css
index 030b89a..8293e88 100644
--- a/docs/_static/css/pigweed.css
+++ b/docs/_static/css/pigweed.css
@@ -16,39 +16,66 @@
 
 /********** Top left logo & search bar ***********/
 
-/* Hide the version string since we're not yet using it. */
-.wy-side-nav-search div.version {
-  display: none;
-}
-
-/* Hide the little house icon */
-.wy-side-nav-search a.icon.icon-home::before {
-  display: none;
-}
-
 /* Make the "Pigweed" logo text. One day, this will be an image. */
-.wy-side-nav-search a {
+.sidebar-brand {
   font-size: 2em;
   font-family: 'Inconsolata', monospace;
+  font-weight: bold;
   letter-spacing: 0.1em;
   text-transform: uppercase;
 }
-
-/* Make the logo background more amaranth-like */
-.wy-side-nav-search {
-  background-color: #e815a5;
-}
-
-/* The input box has a subtle outline; make it match the background */
-.wy-side-nav-search input[type=text] {
-  border-color: #b529aa;
+.sidebar-brand-text {
+    font-size: 2.5rem;
 }
 
 /********** General document coloring ***********/
 
-/* Re-color the fixed width text away from the red color to something more
- * gentle, that aligns with the Pigweed colored theme. */
-.rst-content code.literal, .rst-content tt.literal {
-    color: #b756bd;
+/* Code blocks inside block quotes end up getting italicized. */
+blockquote {
+  font-style: normal;
 }
 
+/* Update description list (dl) > description titles (dt) styles for autodoc */
+
+/* Function signatures are gray */
+dl.c>dt, dl.cpp>dt, dl.js>dt, dl.py>dt {
+  border: none;
+  border-left: 3px solid var(--color-api-function-border);
+  background: var(--color-api-function-background);
+  padding-top: 6px;
+  padding-bottom: 6px;
+  padding-left: 0.5em;
+  font-family: var(--font-stack--monospace);
+}
+
+/* Adjust indentation for all list types */
+dl.class>dt, dl.enum-class>dt, dl.enum-struct>dt, dl.enum>dt, dl.exception>dt, dl.function>dt, dl.method>dt, dl.type>dt {
+  padding-left: 3em;
+  text-indent: -2.5em;
+}
+
+/* Class and describe signatures are blue */
+dl.class>dt, dl.describe>dt {
+  background: var(--color-api-class-background);
+  color: var(--color-api-class-foreground);
+  border: none;
+  border-top: 3px solid var(--color-api-class-border);
+  font-family: var(--font-stack--monospace);
+}
+/* Adjust .. describe:: block padding */
+dl.describe>dt {
+  display: table;
+  padding-top: 6px;
+  padding-bottom: 6px;
+  padding-left: 0.5em;
+  padding-right: 0.5em;
+}
+
+/* Diagram backgrounds should always be light */
+div>svg {
+  background: #ffffff;
+}
+
+code.literal {
+  border: 1px solid var(--color-inline-code-border);
+}
diff --git a/docs/conf.py b/docs/conf.py
index 05da973..37d5471 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -44,7 +44,8 @@
 release = '0.1.0'
 
 # The name of the Pygments (syntax highlighting) style to use.
-pygm = 'sphinx'
+pygments_style = 'pigweed-code-light'
+pygments_dark_style = 'pigweed-code'
 
 extensions = [
     'sphinx.ext.autodoc',  # Automatic documentation for Python code
@@ -73,14 +74,7 @@
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
-html_theme = 'sphinx_rtd_theme'
-
-# Add any paths that contain custom themes here, relative to this directory.
-html_theme_path = [
-    '_themes',
-]
-
-html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
+html_theme = 'furo'
 
 # The name for this set of Sphinx documents.  If None, it defaults to
 # "<project> v<release> documentation".
@@ -117,6 +111,42 @@
     'https://fonts.googleapis.com/css2?family=Inconsolata&display=swap',
 ]
 
+html_theme_options = {
+    'light_css_variables': {
+        # Make the logo text more amaranth-like
+        'color-sidebar-brand-text': '#b529aa',
+        'color-sidebar-search-border': '#b529aa',
+        'color-sidebar-link-text--top-level': '#85004d',
+        'color-sidebar-link-text': '#016074',
+        'color-sidebar-item-background--current': '#f0f0f0',
+        'color-sidebar-item-background--hover': '#ffe2f3',
+        'color-sidebar-item-expander-background--hover': '#ffe2f3',
+        'color-api-function-border': '#cccccc',
+        'color-api-function-background': '#f0f0f0',
+        'color-api-class-background': '#e7f2fa',
+        'color-api-class-foreground': '#2980b9',
+        'color-api-class-border': '#6ab0de',
+        'color-inline-code-background': '#fafafa',
+        'color-inline-code-border': '#cccccc',
+    },
+    'dark_css_variables': {
+        'color-sidebar-brand-text': '#e815a5',
+        'color-sidebar-search-border': '#e815a5',
+        'color-sidebar-link-text--top-level': '#ff79c6',
+        'color-sidebar-link-text': '#8be9fd',
+        'color-sidebar-item-background--current': '#575757',
+        'color-sidebar-item-background--hover': '#4c333f',
+        'color-sidebar-item-expander-background--hover': '#4c333f',
+        'color-api-function-border': '#575757',
+        'color-api-function-background': '#2b2b2b',
+        'color-api-class-background': '#222c35',
+        'color-api-class-foreground': '#87c1e5',
+        'color-api-class-border': '#5288be',
+        'color-inline-code-background': '#2b2b2b',
+        'color-inline-code-border': '#575757',
+    },
+}
+
 # Output file base name for HTML help builder.
 htmlhelp_basename = 'Pigweeddoc'
 
diff --git a/pw_console/py/pw_console/docs/user_guide.rst b/pw_console/py/pw_console/docs/user_guide.rst
index 7bed351..7f3a299 100644
--- a/pw_console/py/pw_console/docs/user_guide.rst
+++ b/pw_console/py/pw_console/docs/user_guide.rst
@@ -10,9 +10,6 @@
 The Pigweed Console provides a Python repl (read eval print loop) and log viewer
 in a single-window terminal based interface.
 
-.. contents::
-   :local:
-
 
 Starting the Console
 --------------------
diff --git a/pw_console/py/pw_console/pigweed_code_style.py b/pw_console/py/pw_console/pigweed_code_style.py
index dd115e2..361a0ab 100644
--- a/pw_console/py/pw_console/pigweed_code_style.py
+++ b/pw_console/py/pw_console/pigweed_code_style.py
@@ -14,16 +14,28 @@
 """Brighter PigweedCode pygments style."""
 
 import copy
+import re
+
+from prompt_toolkit.styles.style_transformation import get_opposite_color
+
 from pygments.style import Style  # type: ignore
-from pygments.token import Keyword, Name, Generic  # type: ignore
+from pygments.token import Comment, Keyword, Name, Generic  # type: ignore
 from pygments_style_dracula.dracula import DraculaStyle  # type: ignore
 
 _style_list = copy.copy(DraculaStyle.styles)
 
 # Darker Prompt
 _style_list[Generic.Prompt] = '#bfbfbf'
+# Lighter comments
+_style_list[Comment] = '#778899'
+_style_list[Comment.Hashbang] = '#778899'
+_style_list[Comment.Multiline] = '#778899'
+_style_list[Comment.Preproc] = '#ff79c6'
+_style_list[Comment.Single] = '#778899'
+_style_list[Comment.Special] = '#778899'
 # Lighter output
 _style_list[Generic.Output] = '#f8f8f2'
+_style_list[Generic.Emph] = '#f8f8f2'
 # Remove 'italic' from these
 _style_list[Keyword.Declaration] = '#8be9fd'
 _style_list[Name.Builtin] = '#8be9fd'
@@ -33,10 +45,37 @@
 _style_list[Name.Variable.Global] = '#8be9fd'
 _style_list[Name.Variable.Instance] = '#8be9fd'
 
+_color_regex = re.compile(r'#(?P<hex>[0-9a-fA-F]{6}) *(?P<rest>.*?)$')
+
+
+def swap_light_dark(color: str) -> str:
+    if not color:
+        return color
+    match = _color_regex.search(color)
+    if not match:
+        return color
+    match_groups = match.groupdict()
+    opposite_color = get_opposite_color(match_groups['hex'])
+    if not opposite_color:
+        return color
+    rest = match_groups.get('rest', '')
+    return '#' + ' '.join([opposite_color, rest])
+
 
 class PigweedCodeStyle(Style):
 
-    background_color = "#2e2e2e"
-    default_style = ""
+    background_color = '#2e2e2e'
+    default_style = ''
 
     styles = _style_list
+
+
+class PigweedCodeLightStyle(Style):
+
+    background_color = '#f8f8f8'
+    default_style = ''
+
+    styles = {
+        key: swap_light_dark(value)
+        for key, value in _style_list.items()
+    }
diff --git a/pw_console/py/setup.py b/pw_console/py/setup.py
index 3b06852..669192c 100644
--- a/pw_console/py/setup.py
+++ b/pw_console/py/setup.py
@@ -38,6 +38,8 @@
         'pygments.styles': [
             'pigweed-code = '
             'pw_console.pigweed_code_style:PigweedCodeStyle',
+            'pigweed-code-light = '
+            'pw_console.pigweed_code_style:PigweedCodeLightStyle',
         ],
     },
     install_requires=[
diff --git a/pw_console/testing.rst b/pw_console/testing.rst
index 6b61581..e4a959b 100644
--- a/pw_console/testing.rst
+++ b/pw_console/testing.rst
@@ -8,9 +8,6 @@
 user interface are preferred but not always possible. For those situations
 manual tests should be added here to validate expected behavior.
 
-.. contents::
-  :local:
-
 Run in Test Mode
 ----------------