[object Object]

← back to Ventura Claw

/services + /legal-notice + /how-it-works: dark/light theme toggle (sun/moon button) per CLAUDE.md rule — anti-flash inline script + light CSS vars + topbar button + localStorage persistence

b2a4b3b51ada962cbe7c4a50e6164dc332366034 · 2026-05-07 09:34:20 -0700 · Steve

Files touched

Diff

commit b2a4b3b51ada962cbe7c4a50e6164dc332366034
Author: Steve <steve@designerwallcoverings.com>
Date:   Thu May 7 09:34:20 2026 -0700

    /services + /legal-notice + /how-it-works: dark/light theme toggle (sun/moon button) per CLAUDE.md rule — anti-flash inline script + light CSS vars + topbar button + localStorage persistence
---
 server/public/how-it-works.html | 34 +++++++++++++++++++++++++++++++++-
 server/public/legal-notice.html | 34 +++++++++++++++++++++++++++++++++-
 server/public/services.html     | 36 +++++++++++++++++++++++++++++++++++-
 3 files changed, 101 insertions(+), 3 deletions(-)

diff --git a/server/public/how-it-works.html b/server/public/how-it-works.html
index ad3ba44..1a88719 100644
--- a/server/public/how-it-works.html
+++ b/server/public/how-it-works.html
@@ -11,6 +11,9 @@
 <meta property="og:url" content="https://venturaclaw.com/how-it-works" />
 <meta property="og:site_name" content="VenturaClaw" />
 <link rel="canonical" href="https://venturaclaw.com/how-it-works" />
+<script>
+  (function () { try { if (localStorage.getItem('vc-theme') === 'light') document.documentElement.setAttribute('data-theme', 'light'); } catch (e) {} })();
+</script>
 <style>
   :root {
     --bg: #0e0e10; --bg-2: #15151a; --bg-3: #1c1c22;
@@ -23,8 +26,27 @@
     --sans: -apple-system, "SF Pro Text", system-ui, sans-serif;
     --max: 1100px;
   }
+  html[data-theme="light"] {
+    --bg: #faf8f3; --bg-2: #f1ece1; --bg-3: #e8e0cf;
+    --rule: #d6cfbd; --rule-2: #c3b9a2;
+    --ink: #1a1a1a; --ink-soft: #383530; --ink-mute: #6a655a; --ink-faint: #908a7d;
+    --gold: #8a6520; --gold-glow: #ad8333; --gold-soft: rgba(138,101,32,0.14);
+    --good: #3d7a4a; --bad: #a04a32;
+  }
+  .theme-toggle {
+    background: var(--bg-3); color: var(--ink-mute); border: 1px solid var(--rule);
+    width: 30px; height: 30px; border-radius: 50%; cursor: pointer;
+    display: inline-flex; align-items: center; justify-content: center;
+    font-size: 14px; line-height: 1; padding: 0; margin-left: 14px;
+    transition: all 200ms;
+  }
+  .theme-toggle:hover { color: var(--gold); border-color: var(--gold); transform: rotate(20deg); }
+  .theme-toggle .moon { display: inline; }
+  .theme-toggle .sun  { display: none; }
+  html[data-theme="light"] .theme-toggle .moon { display: none; }
+  html[data-theme="light"] .theme-toggle .sun  { display: inline; }
   *, *::before, *::after { box-sizing: border-box; }
-  html, body { margin: 0; background: var(--bg); color: var(--ink); font-family: var(--sans); font-weight: 300; line-height: 1.65; }
+  html, body { margin: 0; background: var(--bg); color: var(--ink); font-family: var(--sans); font-weight: 300; line-height: 1.65; transition: background-color 200ms ease, color 200ms ease; }
   ::selection { background: var(--gold); color: var(--bg); }
   a { color: var(--gold); text-decoration: none; }
   a:hover { color: var(--gold-glow); }
@@ -186,7 +208,17 @@
     <a href="/services">Services</a>
     <a href="/legal-notice">Legal</a>
     <a href="/login">Sign in</a>
+    <button class="theme-toggle" id="themeToggle" type="button" title="Toggle light/dark" aria-label="Toggle theme"><span class="moon">☾</span><span class="sun">☀︎</span></button>
   </nav>
+  <script>
+    document.getElementById('themeToggle').addEventListener('click', () => {
+      const cur = document.documentElement.getAttribute('data-theme') === 'light' ? 'light' : 'dark';
+      const next = cur === 'light' ? 'dark' : 'light';
+      if (next === 'light') document.documentElement.setAttribute('data-theme', 'light');
+      else document.documentElement.removeAttribute('data-theme');
+      try { localStorage.setItem('vc-theme', next); } catch {}
+    });
+  </script>
 </header>
 
 <main>
diff --git a/server/public/legal-notice.html b/server/public/legal-notice.html
index 182e41f..dbb8334 100644
--- a/server/public/legal-notice.html
+++ b/server/public/legal-notice.html
@@ -6,6 +6,9 @@
 <title>Legal Notice — VenturaClaw is NOT a Law Firm</title>
 <meta name="description" content="VenturaClaw is an API-orchestration service that helps small businesses set up Stripe, accounting, banking, insurance, payroll, contracts, and domains via vetted partners. Not a law firm, not your attorney. Read the full legal notice." />
 <meta name="robots" content="index,follow" />
+<script>
+  (function () { try { if (localStorage.getItem('vc-theme') === 'light') document.documentElement.setAttribute('data-theme', 'light'); } catch (e) {} })();
+</script>
 <style>
   :root {
     --bg: #0e0e10; --bg-2: #15151a; --bg-3: #1c1c22; --bg-4: #25252e;
@@ -17,8 +20,27 @@
     --mono: "JetBrains Mono", "SFMono-Regular", Menlo, monospace;
     --sans: -apple-system, "SF Pro Text", system-ui, sans-serif;
   }
+  html[data-theme="light"] {
+    --bg: #faf8f3; --bg-2: #f1ece1; --bg-3: #e8e0cf;
+    --rule: #d6cfbd; --rule-2: #c3b9a2;
+    --ink: #1a1a1a; --ink-soft: #383530; --ink-mute: #6a655a; --ink-faint: #908a7d;
+    --gold: #8a6520; --gold-glow: #ad8333;
+    --bad: #a04a32;
+  }
+  .theme-toggle {
+    background: var(--bg-3); color: var(--ink-mute); border: 1px solid var(--rule);
+    width: 30px; height: 30px; border-radius: 50%; cursor: pointer;
+    display: inline-flex; align-items: center; justify-content: center;
+    font-size: 14px; line-height: 1; padding: 0; margin-left: 14px;
+    transition: all 200ms;
+  }
+  .theme-toggle:hover { color: var(--gold); border-color: var(--gold); transform: rotate(20deg); }
+  .theme-toggle .moon { display: inline; }
+  .theme-toggle .sun  { display: none; }
+  html[data-theme="light"] .theme-toggle .moon { display: none; }
+  html[data-theme="light"] .theme-toggle .sun  { display: inline; }
   *, *::before, *::after { box-sizing: border-box; }
-  html, body { margin: 0; background: var(--bg); color: var(--ink); font-family: var(--sans); font-weight: 300; line-height: 1.7; }
+  html, body { margin: 0; background: var(--bg); color: var(--ink); font-family: var(--sans); font-weight: 300; line-height: 1.7; transition: background-color 200ms ease, color 200ms ease; }
   ::selection { background: var(--gold); color: var(--bg); }
   a { color: var(--gold); text-underline-offset: 2px; }
 
@@ -174,7 +196,17 @@
     <a href="/services">Services</a>
     <a href="/privacy">Privacy</a>
     <a href="/terms">Terms</a>
+    <button class="theme-toggle" id="themeToggle" type="button" title="Toggle light/dark" aria-label="Toggle theme"><span class="moon">☾</span><span class="sun">☀︎</span></button>
   </nav>
+  <script>
+    document.getElementById('themeToggle').addEventListener('click', () => {
+      const cur = document.documentElement.getAttribute('data-theme') === 'light' ? 'light' : 'dark';
+      const next = cur === 'light' ? 'dark' : 'light';
+      if (next === 'light') document.documentElement.setAttribute('data-theme', 'light');
+      else document.documentElement.removeAttribute('data-theme');
+      try { localStorage.setItem('vc-theme', next); } catch {}
+    });
+  </script>
 </header>
 
 <section class="alarm">
diff --git a/server/public/services.html b/server/public/services.html
index ecc1c50..a105498 100644
--- a/server/public/services.html
+++ b/server/public/services.html
@@ -46,6 +46,10 @@
   }
 }
 </script>
+<script>
+  // Anti-flash theme apply (before paint)
+  (function () { try { if (localStorage.getItem('vc-theme') === 'light') document.documentElement.setAttribute('data-theme', 'light'); } catch (e) {} })();
+</script>
 <style>
   :root {
     --bg: #0e0e10; --bg-2: #15151a; --bg-3: #1c1c22; --bg-4: #25252e;
@@ -59,8 +63,28 @@
     --chat-w: 360px;
     --chat-w-collapsed: 44px;
   }
+  html[data-theme="light"] {
+    --bg: #faf8f3; --bg-2: #f1ece1; --bg-3: #e8e0cf; --bg-4: #d6cfbd;
+    --rule: #d6cfbd; --rule-2: #c3b9a2;
+    --ink: #1a1a1a; --ink-soft: #383530; --ink-mute: #6a655a; --ink-faint: #908a7d;
+    --gold: #8a6520; --gold-glow: #ad8333; --gold-soft: rgba(138,101,32,0.14);
+    --good: #3d7a4a; --bad: #a04a32;
+  }
+  /* sun/moon toggle in topbar */
+  .theme-toggle {
+    background: var(--bg-3); color: var(--ink-mute); border: 1px solid var(--rule);
+    width: 30px; height: 30px; border-radius: 50%; cursor: pointer;
+    display: inline-flex; align-items: center; justify-content: center;
+    font-size: 14px; line-height: 1; padding: 0; margin-left: 14px;
+    transition: all 200ms;
+  }
+  .theme-toggle:hover { color: var(--gold); border-color: var(--gold); transform: rotate(20deg); }
+  .theme-toggle .moon { display: inline; }
+  .theme-toggle .sun  { display: none; }
+  html[data-theme="light"] .theme-toggle .moon { display: none; }
+  html[data-theme="light"] .theme-toggle .sun  { display: inline; }
   *, *::before, *::after { box-sizing: border-box; }
-  html, body { margin: 0; background: var(--bg); color: var(--ink); font-family: var(--sans); font-weight: 300; line-height: 1.6; min-height: 100vh; }
+  html, body { margin: 0; background: var(--bg); color: var(--ink); font-family: var(--sans); font-weight: 300; line-height: 1.6; min-height: 100vh; transition: background-color 200ms ease, color 200ms ease; }
   ::selection { background: var(--gold); color: var(--bg); }
   a { color: var(--gold); text-decoration: none; }
   a:hover { color: var(--gold-glow); }
@@ -703,6 +727,7 @@
     <a href="/connectors">Connectors</a>
     <a href="/pricing">Pricing</a>
     <a href="/login">Sign in</a>
+    <button class="theme-toggle" id="themeToggle" type="button" title="Toggle light/dark" aria-label="Toggle theme"><span class="moon">☾</span><span class="sun">☀︎</span></button>
   </nav>
 </header>
 
@@ -1096,6 +1121,15 @@
     }
   });
 
+  // ----- theme toggle wiring -----
+  document.getElementById('themeToggle').addEventListener('click', () => {
+    const cur = document.documentElement.getAttribute('data-theme') === 'light' ? 'light' : 'dark';
+    const next = cur === 'light' ? 'dark' : 'light';
+    if (next === 'light') document.documentElement.setAttribute('data-theme', 'light');
+    else document.documentElement.removeAttribute('data-theme');
+    try { localStorage.setItem('vc-theme', next); } catch {}
+  });
+
   // ----- chat panel state -----
   const panel  = document.getElementById('chatPanel');
   const toggle = document.getElementById('chatToggle');

← 2461005 /services + /legal-notice + /how-it-works: emit real Last-Mo  ·  back to Ventura Claw  ·  teaser footer: add /connectors + /docs links (alongside /ser 7151c1c →