my fixes
diff --git a/docs/toc.md b/docs/toc.md
index edadf75..a1938ad 100644
--- a/docs/toc.md
+++ b/docs/toc.md
@@ -8,160 +8,160 @@
 
   - [Tutorials](#)
 
-    - [System Tracing](getting-started/system-tracing.md) `android linux`
-    - [In-App Tracing](getting-started/in-app-tracing.md) `cpp`
-    - [Memory Profiling](getting-started/memory-profiling.md) `android linux`
-    - [CPU Profiling](getting-started/cpu-profiling.md) `android linux`
-    - [Instrumenting with atrace](getting-started/atrace.md) `android`
-    - [Linux ftrace](getting-started/ftrace.md) `linux`
-    - [Recording Chrome Traces](getting-started/chrome-tracing.md) `chrome`
-    - [Importing Other Formats](getting-started/other-formats.md) `perf`
-    - [Converting Data to Perfetto](getting-started/converting.md) `perf`
+    - [System Tracing](getting-started/system-tracing.md) {.tag-android .tag-linux}
+    - [In-App Tracing](getting-started/in-app-tracing.md) {.tag-cpp}
+    - [Memory Profiling](getting-started/memory-profiling.md) {.tag-android .tag-linux}
+    - [CPU Profiling](getting-started/cpu-profiling.md) {.tag-android .tag-linux}
+    - [Instrumenting with atrace](getting-started/atrace.md) {.tag-android}
+    - [Linux ftrace](getting-started/ftrace.md) {.tag-linux}
+    - [Recording Chrome Traces](getting-started/chrome-tracing.md) {.tag-chrome}
+    - [Importing Other Formats](getting-started/other-formats.md) {.tag-perf}
+    - [Converting Data to Perfetto](getting-started/converting.md) {.tag-perf}
 
   - [Cookbooks](#)
 
-    - [Analysing Android Traces](getting-started/android-trace-analysis.md) `android`
-    - [Periodic Trace Snapshots](getting-started/periodic-trace-snapshots.md) `android`
+    - [Analysing Android Traces](getting-started/android-trace-analysis.md) {.tag-android}
+    - [Periodic Trace Snapshots](getting-started/periodic-trace-snapshots.md) {.tag-android}
 
   - [Case Studies](#)
 
-    - [Debugging Memory Usage](case-studies/memory.md) `android`
-    - [Scheduling Blockages](case-studies/scheduling-blockages.md) `android linux`
-    - [Boot Tracing](case-studies/android-boot-tracing.md) `android`
-    - [OutOfMemoryError](case-studies/android-outofmemoryerror.md) `android`
+    - [Debugging Memory Usage](case-studies/memory.md) {.tag-android}
+    - [Scheduling Blockages](case-studies/scheduling-blockages.md) {.tag-android .tag-linux}
+    - [Boot Tracing](case-studies/android-boot-tracing.md) {.tag-android}
+    - [OutOfMemoryError](case-studies/android-outofmemoryerror.md) {.tag-android}
 
   - [Contributing](#)
 
-    - [Getting Started](contributing/getting-started.md) `contrib`
-    - [Common Tasks](contributing/common-tasks.md) `contrib`
+    - [Getting Started](contributing/getting-started.md) {.tag-contrib}
+    - [Common Tasks](contributing/common-tasks.md) {.tag-contrib}
 
 - [Learning More](#)
 
   - [Concepts](#)
 
-    - [Trace Configuration](concepts/config.md) `android linux cpp chrome`
-    - [Buffers and Dataflow](concepts/buffers.md) `android linux cpp`
-    - [Service Model](concepts/service-model.md) `android linux cpp`
-    - [Clock Synchronization](concepts/clock-sync.md) `android linux cpp chrome`
-    - [Concurrent Sessions](concepts/concurrent-tracing-sessions.md) `android linux cpp`
-    - [Tracing in Background](learning-more/tracing-in-background.md) `android linux`
-    - [More Android Tracing](learning-more/android.md) `android`
-    - [Symbolization and Deobfuscation](learning-more/symbolization.md) `android linux`
+    - [Trace Configuration](concepts/config.md) {.tag-android .tag-linux .tag-cpp .tag-chrome}
+    - [Buffers and Dataflow](concepts/buffers.md) {.tag-android .tag-linux .tag-cpp}
+    - [Service Model](concepts/service-model.md) {.tag-android .tag-linux .tag-cpp}
+    - [Clock Synchronization](concepts/clock-sync.md) {.tag-android .tag-linux .tag-cpp .tag-chrome}
+    - [Concurrent Sessions](concepts/concurrent-tracing-sessions.md) {.tag-android .tag-linux .tag-cpp}
+    - [Tracing in Background](learning-more/tracing-in-background.md) {.tag-android .tag-linux}
+    - [More Android Tracing](learning-more/android.md) {.tag-android}
+    - [Symbolization and Deobfuscation](learning-more/symbolization.md) {.tag-android .tag-linux}
 
   - [Tracing SDK](#)
 
-    - [Tracing SDK](instrumentation/tracing-sdk.md) `cpp`
-    - [Track Events](instrumentation/track-events.md) `cpp`
+    - [Tracing SDK](instrumentation/tracing-sdk.md) {.tag-cpp}
+    - [Track Events](instrumentation/track-events.md) {.tag-cpp}
 
   - [Trace Analysis](#)
 
-    - [Getting Started](analysis/getting-started.md) `android linux cpp chrome perf`
-    - [PerfettoSQL Getting Started](analysis/perfetto-sql-getting-started.md) `android linux cpp chrome perf`
-    - [PerfettoSQL Syntax](analysis/perfetto-sql-syntax.md) `android linux cpp chrome perf`
-    - [PerfettoSQL Style Guide](analysis/style-guide.md) `android linux cpp chrome perf`
-    - [PerfettoSQL Backwards Compatibility](analysis/perfetto-sql-backcompat.md) `android linux cpp chrome perf`
-    - [Trace Processor (C++)](analysis/trace-processor.md) `android linux cpp chrome perf`
-    - [Trace Processor (Python)](analysis/trace-processor-python.md) `android linux cpp chrome perf`
-    - [Trace Summarization](analysis/trace-summary.md) `android linux cpp chrome perf`
-    - [Converting from Perfetto](quickstart/traceconv.md) `android linux cpp chrome perf`
+    - [Getting Started](analysis/getting-started.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [PerfettoSQL Getting Started](analysis/perfetto-sql-getting-started.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [PerfettoSQL Syntax](analysis/perfetto-sql-syntax.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [PerfettoSQL Style Guide](analysis/style-guide.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [PerfettoSQL Backwards Compatibility](analysis/perfetto-sql-backcompat.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Trace Processor (C++)](analysis/trace-processor.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Trace Processor (Python)](analysis/trace-processor-python.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Trace Summarization](analysis/trace-summary.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Converting from Perfetto](quickstart/traceconv.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
 
   - [Visualization](#)
 
-    - [Perfetto UI](visualization/perfetto-ui.md) `android linux cpp chrome perf`
-    - [Opening Large Traces](visualization/large-traces.md) `android linux cpp chrome perf`
-    - [Deep Linking](visualization/deep-linking-to-perfetto-ui.md) `android linux cpp chrome perf`
-    - [Debug Tracks](analysis/debug-tracks.md) `android linux cpp chrome perf`
-    - [UI Automation](visualization/ui-automation.md) `android linux cpp chrome perf`
-    - [Extending the UI](visualization/extending-the-ui.md) `android linux cpp chrome perf`
-    - [Extension Servers](visualization/extension-servers.md) `android linux cpp chrome perf`
+    - [Perfetto UI](visualization/perfetto-ui.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Opening Large Traces](visualization/large-traces.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Deep Linking](visualization/deep-linking-to-perfetto-ui.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Debug Tracks](analysis/debug-tracks.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [UI Automation](visualization/ui-automation.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Extending the UI](visualization/extending-the-ui.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Extension Servers](visualization/extension-servers.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
 
   - [UI Development](#)
 
-    - [Getting Started](contributing/ui-getting-started.md) `contrib`
-    - [Plugins](contributing/ui-plugins.md) `contrib`
+    - [Getting Started](contributing/ui-getting-started.md) {.tag-contrib}
+    - [Plugins](contributing/ui-plugins.md) {.tag-contrib}
 
-  - [FAQ](faq.md) `android linux cpp chrome perf`
+  - [FAQ](faq.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
 
 - [Diving Deep](#)
 
   - [Data Sources](#)
 
-    - [CPU Scheduling](data-sources/cpu-scheduling.md) `android linux`
-    - [System Calls](data-sources/syscalls.md) `linux`
-    - [CPU Frequency](data-sources/cpu-freq.md) `linux`
-    - [ATrace](data-sources/atrace.md) `android`
-    - [Logcat](data-sources/android-log.md) `android`
-    - [Frame Timeline](data-sources/frametimeline.md) `android`
-    - [Memory Counters](data-sources/memory-counters.md) `android linux`
-    - [Native Heap Profiler](data-sources/native-heap-profiler.md) `android linux`
-    - [Java Heap Dumps](data-sources/java-heap-profiler.md) `android`
-    - [Battery & Power](data-sources/battery-counters.md) `android`
-    - [GPU & Game Data](data-sources/android-game-intervention-list.md) `android`
-    - [Tracing across Reboots](data-sources/previous-boot-trace.md) `linux`
+    - [CPU Scheduling](data-sources/cpu-scheduling.md) {.tag-android .tag-linux}
+    - [System Calls](data-sources/syscalls.md) {.tag-linux}
+    - [CPU Frequency](data-sources/cpu-freq.md) {.tag-linux}
+    - [ATrace](data-sources/atrace.md) {.tag-android}
+    - [Logcat](data-sources/android-log.md) {.tag-android}
+    - [Frame Timeline](data-sources/frametimeline.md) {.tag-android}
+    - [Memory Counters](data-sources/memory-counters.md) {.tag-android .tag-linux}
+    - [Native Heap Profiler](data-sources/native-heap-profiler.md) {.tag-android .tag-linux}
+    - [Java Heap Dumps](data-sources/java-heap-profiler.md) {.tag-android}
+    - [Battery & Power](data-sources/battery-counters.md) {.tag-android}
+    - [GPU & Game Data](data-sources/android-game-intervention-list.md) {.tag-android}
+    - [Tracing across Reboots](data-sources/previous-boot-trace.md) {.tag-linux}
 
   - [CLI Tools](#)
 
-    - [perfetto](reference/perfetto-cli.md) `android linux`
-    - [traced](reference/traced.md) `android linux`
-    - [traced_probes](reference/traced_probes.md) `android linux`
-    - [heap_profile](reference/heap_profile-cli.md) `android linux`
-    - [tracebox](reference/tracebox.md) `android linux`
+    - [perfetto](reference/perfetto-cli.md) {.tag-android .tag-linux}
+    - [traced](reference/traced.md) {.tag-android .tag-linux}
+    - [traced_probes](reference/traced_probes.md) {.tag-android .tag-linux}
+    - [heap_profile](reference/heap_profile-cli.md) {.tag-android .tag-linux}
+    - [tracebox](reference/tracebox.md) {.tag-android .tag-linux}
 
   - [PerfettoSQL Reference](#)
 
-    - [Standard Library](analysis/stdlib-docs.autogen) `android linux cpp chrome perf`
-    - [Prelude Tables](analysis/sql-tables.autogen) `android linux cpp chrome perf`
-    - [Built-in Functions](analysis/builtin.md) `android linux cpp chrome perf`
-    - [Stats Table](analysis/sql-stats.autogen) `android linux cpp chrome perf`
+    - [Standard Library](analysis/stdlib-docs.autogen) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Prelude Tables](analysis/sql-tables.autogen) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Built-in Functions](analysis/builtin.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Stats Table](analysis/sql-stats.autogen) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
 
   - [References](#)
 
-    - [Trace Config Proto](reference/trace-config-proto.autogen) `android linux cpp chrome perf`
-    - [Trace Packet Proto](reference/trace-packet-proto.autogen) `android linux cpp chrome perf`
-    - [Synthetic Track Events](reference/synthetic-track-event.md) `android linux cpp chrome perf`
-    - [Commands Reference](visualization/commands-automation-reference.md) `android linux cpp chrome perf`
-    - [Extension Server Protocol](visualization/extension-server-protocol.md) `cpp`
-    - [Android Version Notes](reference/android-version-notes.md) `android`
-    - [Kernel Track Events](reference/kernel-track-event.md) `linux`
+    - [Trace Config Proto](reference/trace-config-proto.autogen) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Trace Packet Proto](reference/trace-packet-proto.autogen) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Synthetic Track Events](reference/synthetic-track-event.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Commands Reference](visualization/commands-automation-reference.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Extension Server Protocol](visualization/extension-server-protocol.md) {.tag-cpp}
+    - [Android Version Notes](reference/android-version-notes.md) {.tag-android}
+    - [Kernel Track Events](reference/kernel-track-event.md) {.tag-linux}
 
   - [Advanced Recording](#)
 
-    - [Detached Mode](concepts/detached-mode.md) `android`
-    - [Interceptors](instrumentation/interceptors.md) `cpp`
+    - [Detached Mode](concepts/detached-mode.md) {.tag-android}
+    - [Interceptors](instrumentation/interceptors.md) {.tag-cpp}
 
   - [Advanced Analysis](#)
 
-    - [Legacy (v1) Metrics](analysis/metrics.md) `android linux cpp chrome perf`
-    - [Batch Trace Processor](analysis/batch-trace-processor.md) `android linux perf`
-    - [BigTrace (Single Machine)](deployment/deploying-bigtrace-on-a-single-machine.md) `android linux perf`
-    - [BigTrace on Kubernetes](deployment/deploying-bigtrace-on-kubernetes.md) `android linux perf`
+    - [Legacy (v1) Metrics](analysis/metrics.md) {.tag-android .tag-linux .tag-cpp .tag-chrome .tag-perf}
+    - [Batch Trace Processor](analysis/batch-trace-processor.md) {.tag-android .tag-linux .tag-perf}
+    - [BigTrace (Single Machine)](deployment/deploying-bigtrace-on-a-single-machine.md) {.tag-android .tag-linux .tag-perf}
+    - [BigTrace on Kubernetes](deployment/deploying-bigtrace-on-kubernetes.md) {.tag-android .tag-linux .tag-perf}
 
   - [Contributor Reference](#)
 
-    - [Building](contributing/build-instructions.md) `contrib`
-    - [Testing](contributing/testing.md) `contrib`
-    - [Developer Tools](contributing/developer-tools.md) `contrib`
-    - [Become a Committer](contributing/become-a-committer.md) `contrib`
+    - [Building](contributing/build-instructions.md) {.tag-contrib}
+    - [Testing](contributing/testing.md) {.tag-contrib}
+    - [Developer Tools](contributing/developer-tools.md) {.tag-contrib}
+    - [Become a Committer](contributing/become-a-committer.md) {.tag-contrib}
 
   - [Releases](#)
 
-    - [SDK Release](contributing/sdk-releasing.md) `contrib`
-    - [Python Release](contributing/python-releasing.md) `contrib`
-    - [UI Release](visualization/perfetto-ui-release-process.md) `contrib`
-    - [Chrome Branches](contributing/chrome-branches.md) `contrib`
-    - [SQLite Upgrade](contributing/sqlite-upgrade-guide.md) `contrib`
+    - [SDK Release](contributing/sdk-releasing.md) {.tag-contrib}
+    - [Python Release](contributing/python-releasing.md) {.tag-contrib}
+    - [UI Release](visualization/perfetto-ui-release-process.md) {.tag-contrib}
+    - [Chrome Branches](contributing/chrome-branches.md) {.tag-contrib}
+    - [SQLite Upgrade](contributing/sqlite-upgrade-guide.md) {.tag-contrib}
 
   - [Design Documents](#)
 
-    - [API and ABI Surface](design-docs/api-and-abi.md) `contrib`
-    - [Life of a Tracing Session](design-docs/life-of-a-tracing-session.md) `contrib`
-    - [ProtoZero](design-docs/protozero.md) `contrib`
-    - [Security Model](design-docs/security-model.md) `contrib`
-    - [Trace Processor Architecture](design-docs/trace-processor-architecture.md) `contrib`
-    - [Heapprofd Design](design-docs/heapprofd-design.md) `contrib`
-    - [Heapprofd Wire Protocol](design-docs/heapprofd-wire-protocol.md) `contrib`
-    - [Heapprofd Sampling](design-docs/heapprofd-sampling.md) `contrib`
-    - [Batch Trace Processor](design-docs/batch-trace-processor.md) `contrib`
-    - [Statsd Checkpoint Atoms](design-docs/checkpoint-atoms.md) `contrib`
-    - [Perfetto CI](design-docs/continuous-integration.md) `contrib`
-    - [LockFreeTaskRunner](design-docs/lock-free-task-runner.md) `contrib`
+    - [API and ABI Surface](design-docs/api-and-abi.md) {.tag-contrib}
+    - [Life of a Tracing Session](design-docs/life-of-a-tracing-session.md) {.tag-contrib}
+    - [ProtoZero](design-docs/protozero.md) {.tag-contrib}
+    - [Security Model](design-docs/security-model.md) {.tag-contrib}
+    - [Trace Processor Architecture](design-docs/trace-processor-architecture.md) {.tag-contrib}
+    - [Heapprofd Design](design-docs/heapprofd-design.md) {.tag-contrib}
+    - [Heapprofd Wire Protocol](design-docs/heapprofd-wire-protocol.md) {.tag-contrib}
+    - [Heapprofd Sampling](design-docs/heapprofd-sampling.md) {.tag-contrib}
+    - [Batch Trace Processor](design-docs/batch-trace-processor.md) {.tag-contrib}
+    - [Statsd Checkpoint Atoms](design-docs/checkpoint-atoms.md) {.tag-contrib}
+    - [Perfetto CI](design-docs/continuous-integration.md) {.tag-contrib}
+    - [LockFreeTaskRunner](design-docs/lock-free-task-runner.md) {.tag-contrib}
diff --git a/infra/perfetto.dev/build.js b/infra/perfetto.dev/build.js
index 62461da..4a07ffd 100644
--- a/infra/perfetto.dev/build.js
+++ b/infra/perfetto.dev/build.js
@@ -124,7 +124,7 @@
           res.end(data);
         });
       })
-      .listen(port, 'localhost');
+      .listen(port, '0.0.0.0');
 }
 
 function watchDir(dir) {
diff --git a/infra/perfetto.dev/src/assets/script.js b/infra/perfetto.dev/src/assets/script.js
index 96e011a..da1ab4f 100644
--- a/infra/perfetto.dev/src/assets/script.js
+++ b/infra/perfetto.dev/src/assets/script.js
@@ -141,17 +141,13 @@
   }
 }
 
-// Audiences shown in the nav tag bar. Tags here must match the backtick
-// tags attached to leaf entries in docs/toc.md.
-const NAV_AUDIENCES = [
-  { tag: 'android', label: 'Android' },
-  { tag: 'linux', label: 'Linux' },
-  { tag: 'cpp', label: 'C++ dev' },
-  { tag: 'chrome', label: 'Chrome' },
-  { tag: 'perf', label: 'Perf dev' },
-  { tag: 'contrib', label: 'Contributors' },
-];
-const NAV_DEFAULT_TAGS = ['android'];
+const TAG_PREFIX = 'tag-';
+const TAG_LABELS = {cpp: 'C++'};
+const NAV_DEFAULT_TAG = 'android';
+
+function tagLabel(tag) {
+  return TAG_LABELS[tag] || tag.charAt(0).toUpperCase() + tag.slice(1);
+}
 
 // This function needs to be idempotent as it is called more than once (on every
 // resize).
@@ -165,21 +161,30 @@
   const rootUl = nav.querySelector(':scope > ul');
   if (!rootUl) return;
 
-  // --- Step 1: Load the set of active audience tags. ---
-  const validTags = new Set(NAV_AUDIENCES.map((a) => a.tag));
-  let activeTags = null;
-  try {
-    const raw = sessionStorage.getItem('docs.nav.activeTags');
-    if (raw) activeTags = JSON.parse(raw).filter((t) => validTags.has(t));
-  } catch (e) {
-    activeTags = null;
+  // --- Step 1: Discover available tags from CSS classes on <li> elements. ---
+  const tagOrder = [];
+  const tagSeen = new Set();
+  for (const li of rootUl.querySelectorAll('li')) {
+    for (const cls of li.classList) {
+      if (cls.startsWith(TAG_PREFIX)) {
+        const tag = cls.slice(TAG_PREFIX.length);
+        if (!tagSeen.has(tag)) {
+          tagSeen.add(tag);
+          tagOrder.push(tag);
+        }
+      }
+    }
   }
-  if (!activeTags) activeTags = NAV_DEFAULT_TAGS.slice();
-  const activeSet = new Set(activeTags);
-  sessionStorage.setItem(
-    'docs.nav.activeTags', JSON.stringify([...activeSet]));
 
-  // --- Step 2: Build/refresh the audience chip bar. ---
+  // --- Step 2: Load single active tag from session ('' = show all). ---
+  let activeTag = sessionStorage.getItem('docs.nav.activeTag');
+  if (activeTag === null) {
+    activeTag = NAV_DEFAULT_TAG;
+  } else if (activeTag !== '' && !tagSeen.has(activeTag)) {
+    activeTag = NAV_DEFAULT_TAG;
+  }
+
+  // --- Step 3: Build/refresh the audience chip bar (single-select + All). ---
   let filterBox = nav.querySelector(':scope > .audience-filter');
   if (!filterBox) {
     filterBox = document.createElement('div');
@@ -195,71 +200,44 @@
   }
   const chipBar = filterBox.querySelector(':scope > .audience-tags');
   chipBar.innerHTML = '';
-  for (const a of NAV_AUDIENCES) {
+
+  const makeChip = (label, tag) => {
     const btn = document.createElement('button');
     btn.type = 'button';
     btn.className = 'audience-tag';
-    btn.textContent = a.label;
-    if (activeSet.has(a.tag)) btn.classList.add('active');
+    btn.textContent = label;
+    if (tag === activeTag) btn.classList.add('active');
     btn.addEventListener('click', () => {
-      const next = new Set(activeSet);
-      if (next.has(a.tag)) next.delete(a.tag);
-      else next.add(a.tag);
-      sessionStorage.setItem(
-        'docs.nav.activeTags', JSON.stringify([...next]));
+      sessionStorage.setItem('docs.nav.activeTag', tag);
       updateNav();
     });
     chipBar.appendChild(btn);
-  }
-
-  // --- Step 3: Parse per-leaf audience tags from <code> markers. ---
-  // Each leaf's tags come from a trailing `tag1 tag2` in the markdown,
-  // rendered by marked.js as a <code> child of the <li> (or its <p>).
-  const allLis = rootUl.querySelectorAll('li');
-  for (const li of allLis) {
-    if (li.dataset.navTagsParsed) continue;
-    const code = li.querySelector(':scope > code') ||
-                 li.querySelector(':scope > p > code');
-    if (code) {
-      li.dataset.navTags = code.textContent.trim();
-    }
-    li.dataset.navTagsParsed = '1';
-  }
-
-  // --- Step 4: Filter leaves by active audience, then collapse empty
-  // ancestors. Visibility is decided bottom-up. ---
-  const showAll = activeSet.size === 0;
-  const hasTag = (li) => {
-    if (!li.dataset.navTags) return null;
-    if (showAll) return true;
-    return li.dataset.navTags.split(/\s+/).some((t) => activeSet.has(t));
   };
+  for (const tag of tagOrder) makeChip(tagLabel(tag), tag);
+  makeChip('All', '');
 
-  const isVisible = new Map();
-  const setVisible = (li, v) => {
-    isVisible.set(li, v);
-    li.style.display = v ? '' : 'none';
+  // --- Step 4: Filter leaves by active tag, then collapse empty ancestors.
+  // Visibility is decided bottom-up so parents with no visible children hide. ---
+  const activeCls = activeTag ? TAG_PREFIX + activeTag : '';
+  const isTagged = (li) => {
+    for (const c of li.classList) if (c.startsWith(TAG_PREFIX)) return true;
+    return false;
   };
-
-  // Bottom-up pass: leaf visibility from tags; parent visible if any child is.
   const process = (li) => {
     const childUl = li.querySelector(':scope > ul');
     if (!childUl) {
-      // Leaf: visible iff untagged (universal) or tag set includes active tag.
-      const match = hasTag(li);
-      setVisible(li, match === null ? true : match);
-      return isVisible.get(li);
+      const vis = !isTagged(li) || !activeCls || li.classList.contains(activeCls);
+      li.style.display = vis ? '' : 'none';
+      return vis;
     }
-    let anyChildVisible = false;
+    let any = false;
     for (const child of childUl.querySelectorAll(':scope > li')) {
-      if (process(child)) anyChildVisible = true;
+      if (process(child)) any = true;
     }
-    setVisible(li, anyChildVisible);
-    return anyChildVisible;
+    li.style.display = any ? '' : 'none';
+    return any;
   };
-  for (const li of rootUl.querySelectorAll(':scope > li')) {
-    process(li);
-  }
+  for (const li of rootUl.querySelectorAll(':scope > li')) process(li);
 
   // --- Step 5: Make inner sections (categories) compressible. ---
   for (const sec of rootUl.querySelectorAll('li')) {
diff --git a/infra/perfetto.dev/src/assets/style.scss b/infra/perfetto.dev/src/assets/style.scss
index c664e6e..1b2ef85 100644
--- a/infra/perfetto.dev/src/assets/style.scss
+++ b/infra/perfetto.dev/src/assets/style.scss
@@ -133,7 +133,7 @@
   }
   > *:not(:first-child) {
     line-height: calc(var(--site-header-height) - var(--sh-padding-y) * 2);
-    font-family: Roboto, sans-serif;
+    font-family: "Source Sans Pro", sans-serif;
     font-weight: 400;
     font-size: 1.1rem;
     margin: 0 20px;
@@ -324,8 +324,7 @@
   color: var(--color-text-muted);
   text-align: left;
   margin: 0 20px;
-  padding: 16px 0;
-  font-size: 13px;
+  padding: 12px 0;
 
   .docs-footer-notice {
     padding: 0;
@@ -374,7 +373,7 @@
     h1,
     h2 {
       margin: auto;
-      font-family: Roboto, sans-serif;
+      font-family: "Source Sans Pro", sans-serif;
       text-align: center;
       color: var(--color-text);
       span {
@@ -423,11 +422,11 @@
     }
     > a {
       color: var(--color-text);
-      font-size: 20px;
-      font-weight: 500;
+      font-size: 22px;
+      font-weight: 400;
       text-align: center;
       padding: 20px 0;
-      font-family: Roboto, sans-serif;
+      font-family: "Source Sans Pro", sans-serif;
       text-decoration: none;
       transition: background-color ease 0.15s;
       .icon {
@@ -478,7 +477,7 @@
       grid-area: content;
     }
     h2 {
-      font-family: Roboto, sans-serif;
+      font-family: "Source Sans Pro", sans-serif;
       font-weight: 600;
       font-size: 2.5rem;
       color: var(--color-text);
@@ -523,9 +522,9 @@
         background: var(--color-link);
         font-weight: 500;
         color: #fff;
-        border-radius: 8px;
-        font-size: 16px;
-        padding: 10px 20px;
+        border-radius: 6px;
+        font-size: 18px;
+        padding: 10px 16px;
         transition: background-color ease 0.15s, transform ease 0.15s;
         text-decoration: none;
         &:hover {
@@ -542,7 +541,7 @@
       grid-column-gap: 20px;
       padding: 20px 30px;
       margin: 10px 0;
-      font-family: Roboto, sans-serif;
+      font-family: "Source Sans Pro", sans-serif;
       color: var(--color-text);
       transition:
         filter var(--anim-ease) var(--anim-time),
@@ -642,8 +641,6 @@
     height: calc(100vh - var(--site-header-height));
     overflow-y: auto;
     @include minimal-scrollbar;
-    font-family: Roboto, sans-serif;
-    font-size: 0.9rem;
 
     // ---- Audience filter (caption + chips) ----
     .audience-filter {
@@ -691,20 +688,22 @@
       }
     }
 
-    // Per-leaf tag markers in toc.md (e.g. `android linux`) are parsed by
-    // JS and should not be displayed.
-    code {
-      display: none;
-    }
-
     // ---- Base reset for all lists and links ----
     ul {
       list-style: none;
       margin: 0;
       padding: 0;
       overflow: hidden;
+      li {
+        font-size: 1rem;
+        font-weight: 400;
+        font-family: "Source Sans Pro", sans-serif;
+        color: #4a4a4a;
+        max-width: 100%;
+        margin: 0;
+      }
+      p { margin: 0; }
     }
-    p { margin: 0; }
 
     a {
       display: flex;
@@ -736,7 +735,6 @@
 
       > p > a {
         font-weight: 700;
-        font-size: 0.95rem;
         color: var(--color-link);
         padding: 4px 16px;
         letter-spacing: 0.01em;
@@ -749,7 +747,6 @@
     .compressible > p > a,
     a:not([href]) {
       font-weight: 600;
-      font-size: 0.85rem;
       color: var(--color-text);
       text-transform: uppercase;
       letter-spacing: 0.03em;
@@ -759,13 +756,13 @@
     // ---- Expand/collapse chevron ----
     .compressible {
       > p > a::after {
-        content: "\25B4"; // ▴ small up triangle
+        content: "\25B4";
         font-size: 0.7em;
         flex-shrink: 0;
         width: 20px;
         text-align: center;
         margin-left: auto;
-        color: var(--color-text-muted);
+        color: #666;
         transition: transform var(--anim-ease) var(--anim-time);
       }
       > ul {
@@ -832,8 +829,7 @@
           text-decoration: none;
           margin-left: 2px;
           margin-right: 4px;
-          font-size: 0.85em;
-          vertical-align: middle;
+          vertical-align: bottom;
         }
       }
     }
@@ -848,23 +844,19 @@
     }
     h1 {
       font-size: 2.25rem;
-      line-height: 1.2;
+      line-height: 2.25rem;
       margin: 0;
       padding: 0;
       margin-bottom: 1.5rem;
-      font-family: Roboto, sans-serif;
-      font-weight: 700;
-      letter-spacing: -0.02em;
+      font-family: "Source Sans Pro", sans-serif;
     }
     h2 {
       font-size: 1.5rem;
-      font-weight: 600;
-      border-bottom: 2px solid var(--color-border-light);
-      padding-bottom: 8px;
+      border-bottom: 1px solid #e8eaed;
+      padding-bottom: 6px;
     }
     h3 {
       font-size: 1.25rem;
-      font-weight: 600;
     }
     * {
       max-width: 100%;
@@ -877,10 +869,9 @@
 
     code:not(.code-block) {
       background: #f1f5f9;
-      border: 1px solid var(--color-border);
-      border-radius: 4px;
-      padding: 1px 6px;
-      font-size: 0.88em;
+      border: 1px solid #e8eaed;
+      border-radius: 6px;
+      padding: 1px 4px;
     }
     .code-block {
       overflow-x: auto;
@@ -910,8 +901,8 @@
       &::before {
         content: "insert_link";
         font-family: "Material Icons Round";
-        color: var(--color-text-muted);
-        font-size: 22px;
+        color: #333;
+        font-size: 24px;
       }
     }
     *:hover .anchor {
@@ -1010,9 +1001,9 @@
       &:before {
         font-family: "Material Icons Round";
         position: absolute;
-        font-size: 1.3rem;
-        margin-left: -2rem;
-        margin-top: 0;
+        font-size: 1.5rem;
+        margin-left: -1.75rem;
+        margin-top: -2px;
       }
 
       &.note {
@@ -1078,9 +1069,8 @@
       border: none;
       background: transparent;
       font-family: Roboto, sans-serif;
-      font-size: 0.95rem;
-      padding: 10px 16px;
-      font-weight: 500;
+      font-size: 1rem;
+      padding: 8px;
       color: var(--color-text-secondary);
       transition: color ease 0.1s, border-color ease 0.1s;
       &:hover {
@@ -1113,7 +1103,7 @@
     overflow-y: auto;
     @include minimal-scrollbar;
 
-    font-family: Roboto, sans-serif;
+    font-family: "Source Sans Pro", sans-serif;
     word-break: break-word;
     a {
       text-decoration: none;
@@ -1130,7 +1120,7 @@
       font-weight: 600;
       color: #b8860b;
     }
-    font-size: 0.85rem;
+    font-size: 0.875rem;
     ul {
       list-style: none;
       margin: 0;
diff --git a/infra/perfetto.dev/src/markdown_render.js b/infra/perfetto.dev/src/markdown_render.js
index 273de4d..4184990 100644
--- a/infra/perfetto.dev/src/markdown_render.js
+++ b/infra/perfetto.dev/src/markdown_render.js
@@ -142,6 +142,20 @@
   return originalImgFn(href, title, text);
 }
 
+function renderListItem(text) {
+  // Detect a trailing {.class1 .class2} attribute block (used in toc.md to
+  // annotate audience, e.g. {.tag-android .tag-linux}).  Hoist the classes
+  // onto the <li> so the sidebar can filter with pure CSS.
+  const m = text.match(
+    /\s*\{(\.[a-z][a-z0-9-]*(?:\s+\.[a-z][a-z0-9-]*)*)\}(\s*<\/p>)?\s*$/);
+  if (m) {
+    const cls = m[1].split(/\s+/).map(c => c.slice(1)).join(' ');
+    const tail = m[2] || '';
+    return `<li class="${cls}">${text.slice(0, m.index)}${tail}</li>\n`;
+  }
+  return `<li>${text}</li>\n`;
+}
+
 function renderParagraph(text) {
   let cssClass = "";
   if (text.startsWith("NOTE:")) {
@@ -209,6 +223,7 @@
   renderer.code = renderCode;
   renderer.heading = renderHeading;
   renderer.paragraph = renderParagraph;
+  renderer.listitem = renderListItem;
   const originalHtmlFn = renderer.html.bind(renderer);
   renderer.html = (html) => renderHtml(originalHtmlFn, html);