[object Object]

โ† back to Butlr

rebrand: HoldForMe โ†’ Butlr (mass swap across 27 files: brand mark โฑโ†’๐ŸŽฉ, all titles/wordmarks/email-placeholders/SMS-body strings updated to Butlr; legal page emails now @butlr.ai; project directory name kept as 'holdforme' to preserve pm2 process refs + git remotes; TM-collision risk with butlr.com sensor-tech firm noted and accepted by Steve)

54497d0c7900d2bcf451f1e81b4099f3a3f40820 ยท 2026-05-12 13:09:12 -0700 ยท SteveStudio2

Files touched

Diff

commit 54497d0c7900d2bcf451f1e81b4099f3a3f40820
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Tue May 12 13:09:12 2026 -0700

    rebrand: HoldForMe โ†’ Butlr (mass swap across 27 files: brand mark โฑโ†’๐ŸŽฉ, all titles/wordmarks/email-placeholders/SMS-body strings updated to Butlr; legal page emails now @butlr.ai; project directory name kept as 'holdforme' to preserve pm2 process refs + git remotes; TM-collision risk with butlr.com sensor-tech firm noted and accepted by Steve)
---
 README.md                          |  2 +-
 lib/twilio.js                      | 10 ++++-----
 package.json                       |  2 +-
 public/css/theme.css               |  2 +-
 routes/listen.js                   |  6 ++---
 routes/public.js                   | 46 +++++++++++++++++++-------------------
 routes/twilio-webhooks.js          |  2 +-
 server.js                          |  4 ++--
 views/partials/footer.ejs          |  2 +-
 views/partials/header.ejs          |  6 ++---
 views/public/accessibility.ejs     |  6 ++---
 views/public/home.ejs              |  2 +-
 views/public/how.ejs               |  2 +-
 views/public/new.ejs               |  2 +-
 views/public/privacy.ejs           | 10 ++++-----
 views/public/terms.ejs             | 16 ++++++-------
 views/public/wizard-4-callback.ejs |  2 +-
 17 files changed, 61 insertions(+), 61 deletions(-)

diff --git a/README.md b/README.md
index 50de64c..7233a26 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# HoldForMe
+# Butlr
 
 We wait on hold so you don't have to. Credit cards, hospitals, restaurants, anywhere a queue stands between you and a human.
 
diff --git a/lib/twilio.js b/lib/twilio.js
index 6e592ec..28d7b1c 100644
--- a/lib/twilio.js
+++ b/lib/twilio.js
@@ -40,7 +40,7 @@ function log(...args) { console.log('[twilio]', new Date().toISOString(), ...arg
 // California Cal. Penal Code ยง 632 + 10 other two-party states. No exceptions.
 // See ~/.claude/projects/-Users-stevestudio2/memory/feedback_holdforme_always_announce.md
 function buildAnnouncement(call) {
-  const onBehalfOf = call.callback_name || 'a HoldForMe customer';
+  const onBehalfOf = call.callback_name || 'a Butlr customer';
   return [
     `Hello. This is an automated assistant calling on behalf of ${onBehalfOf}.`,
     `This call may be recorded for quality and accuracy.`,
@@ -96,10 +96,10 @@ async function sendSms({ to, body }) {
 async function notifyOnStageChange(call, fromStatus, toStatus) {
   if (!call.notify_sms || !call.callback_phone) return;
   let body = null;
-  if (toStatus === 'on_hold')   body = `HoldForMe: we're now on hold with ${call.business_name}. We'll text again when an agent picks up.`;
-  if (toStatus === 'connected') body = `HoldForMe: an agent at ${call.business_name} just picked up. Calling you now โ€” pick up to be bridged.`;
-  if (toStatus === 'done')      body = `HoldForMe: your call to ${call.business_name} is complete. Open the app for the summary.`;
-  if (toStatus === 'failed')    body = `HoldForMe: your call to ${call.business_name} couldn't complete. Open the app for details.`;
+  if (toStatus === 'on_hold')   body = `Butlr: we're now on hold with ${call.business_name}. We'll text again when an agent picks up.`;
+  if (toStatus === 'connected') body = `Butlr: an agent at ${call.business_name} just picked up. Calling you now โ€” pick up to be bridged.`;
+  if (toStatus === 'done')      body = `Butlr: your call to ${call.business_name} is complete. Open the app for the summary.`;
+  if (toStatus === 'failed')    body = `Butlr: your call to ${call.business_name} couldn't complete. Open the app for details.`;
   if (body) await sendSms({ to: call.callback_phone, body });
 }
 
diff --git a/package.json b/package.json
index e9aad0f..ae085f3 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
   "name": "holdforme",
   "version": "0.1.0",
   "private": true,
-  "description": "HoldForMe โ€” we wait on hold so you don't have to. Customer service complaints, credit limit increases, restaurant reservations, anywhere you'd otherwise burn 47 minutes on hold music.",
+  "description": "Butlr โ€” we wait on hold so you don't have to. Customer service complaints, credit limit increases, restaurant reservations, anywhere you'd otherwise burn 47 minutes on hold music.",
   "main": "server.js",
   "scripts": {
     "start": "node server.js",
diff --git a/public/css/theme.css b/public/css/theme.css
index 80384fa..8649b24 100644
--- a/public/css/theme.css
+++ b/public/css/theme.css
@@ -1,4 +1,4 @@
-/* HoldForMe palette โ€” calm cobalt + warm ivory + alert amber.
+/* Butlr palette โ€” calm cobalt + warm ivory + alert amber.
    Sense: medical-waiting-room serenity with one sharp accent. */
 
 :root {
diff --git a/routes/listen.js b/routes/listen.js
index e6719cb..49f0c45 100644
--- a/routes/listen.js
+++ b/routes/listen.js
@@ -14,14 +14,14 @@ const router = express.Router();
 router.get('/listen/:call_id', (req, res) => {
   const callId = req.params.call_id;
   if (!/^[A-Za-z0-9_-]{6,16}$/.test(callId)) {
-    return res.status(404).render('public/404', { title: 'Not found โ€” HoldForMe' });
+    return res.status(404).render('public/404', { title: 'Not found โ€” Butlr' });
   }
   const call = data.getCall(callId, false);
   if (!call) {
-    return res.status(404).render('public/404', { title: 'Not found โ€” HoldForMe' });
+    return res.status(404).render('public/404', { title: 'Not found โ€” Butlr' });
   }
   res.render('public/listen', {
-    title: `Listen in โ€” ${call.business_name} โ€” HoldForMe`,
+    title: `Listen in โ€” ${call.business_name} โ€” Butlr`,
     meta_desc: 'Live audio listen-in.',
     call,
   });
diff --git a/routes/public.js b/routes/public.js
index 759f3b5..b303608 100644
--- a/routes/public.js
+++ b/routes/public.js
@@ -3,14 +3,14 @@ const router = express.Router();
 const data = require('../lib/data');
 
 router.use((req, res, next) => {
-  res.locals.site_title = 'HoldForMe';
+  res.locals.site_title = 'Butlr';
   res.locals.path = req.path;
   next();
 });
 
 router.get('/', (req, res) => {
   res.render('public/home', {
-    title: 'HoldForMe โ€” We wait on hold so you don\'t have to',
+    title: 'Butlr โ€” We wait on hold so you don\'t have to',
     meta_desc: 'Skip the hold music. Submit who to call and what you need done; we wait, you live your life. Credit cards, hospitals, restaurants, anywhere there\'s a queue.',
   });
 });
@@ -57,7 +57,7 @@ router.get('/new', (req, res) => {
   const state = pickState(req.query);
   if (req.query.category) state.category = req.query.category;
   res.render('public/wizard-1-category', {
-    title: 'Start a call โ€” Step 1 of 4 โ€” HoldForMe',
+    title: 'Start a call โ€” Step 1 of 4 โ€” Butlr',
     meta_desc: 'Step 1: pick the kind of call.',
     categories: data.CATEGORIES,
     state, step: 1,
@@ -72,7 +72,7 @@ router.post('/new/business', (req, res) => {
   }
   const businesses = data.businessesForCategory(state.category);
   res.render('public/wizard-2-business', {
-    title: 'Start a call โ€” Step 2 of 4 โ€” HoldForMe',
+    title: 'Start a call โ€” Step 2 of 4 โ€” Butlr',
     meta_desc: 'Step 2: who to call.',
     categories: data.CATEGORIES,
     businesses,
@@ -98,7 +98,7 @@ router.post('/new/details', (req, res) => {
   if (!state.business_name || !state.business_phone) {
     const businesses = data.businessesForCategory(state.category);
     return res.render('public/wizard-2-business', {
-      title: 'Start a call โ€” Step 2 of 4 โ€” HoldForMe',
+      title: 'Start a call โ€” Step 2 of 4 โ€” Butlr',
       meta_desc: 'Step 2: who to call.',
       categories: data.CATEGORIES,
       businesses,
@@ -109,7 +109,7 @@ router.post('/new/details', (req, res) => {
   }
 
   res.render('public/wizard-3-details', {
-    title: 'Start a call โ€” Step 3 of 4 โ€” HoldForMe',
+    title: 'Start a call โ€” Step 3 of 4 โ€” Butlr',
     meta_desc: 'Step 3: what you need done.',
     state, step: 3,
     preset: data.categoryById(state.category),
@@ -122,7 +122,7 @@ router.post('/new/callback', (req, res) => {
   if (!state.category) return res.redirect('/new');
   if (!state.goal || state.goal.trim().length < 8) {
     return res.render('public/wizard-3-details', {
-      title: 'Start a call โ€” Step 3 of 4 โ€” HoldForMe',
+      title: 'Start a call โ€” Step 3 of 4 โ€” Butlr',
       meta_desc: 'Step 3: what you need done.',
       state, step: 3,
       preset: data.categoryById(state.category),
@@ -130,7 +130,7 @@ router.post('/new/callback', (req, res) => {
     });
   }
   res.render('public/wizard-4-callback', {
-    title: 'Start a call โ€” Step 4 of 4 โ€” HoldForMe',
+    title: 'Start a call โ€” Step 4 of 4 โ€” Butlr',
     meta_desc: 'Step 4: how to reach you back.',
     state, step: 4,
   });
@@ -142,7 +142,7 @@ router.post('/new/submit', (req, res) => {
   if (!r.ok) {
     const state = pickState(req.body);
     return res.status(400).render('public/wizard-4-callback', {
-      title: 'Start a call โ€” Step 4 of 4 โ€” HoldForMe',
+      title: 'Start a call โ€” Step 4 of 4 โ€” Butlr',
       meta_desc: 'Step 4: how to reach you back.',
       state, step: 4,
       errors: r.errors,
@@ -153,7 +153,7 @@ router.post('/new/submit', (req, res) => {
 
 router.get('/calls', (req, res) => {
   res.render('public/calls', {
-    title: 'Your call queue โ€” HoldForMe',
+    title: 'Your call queue โ€” Butlr',
     meta_desc: 'Calls you\'ve queued up.',
     calls: data.listCalls(),
   });
@@ -161,11 +161,11 @@ router.get('/calls', (req, res) => {
 
 router.get('/calls/:id', (req, res) => {
   const id = req.params.id;
-  if (!/^[A-Za-z0-9_-]{6,16}$/.test(id)) return res.status(404).render('public/404', { title: 'Not found โ€” HoldForMe' });
+  if (!/^[A-Za-z0-9_-]{6,16}$/.test(id)) return res.status(404).render('public/404', { title: 'Not found โ€” Butlr' });
   const c = data.getCall(id, req.query.reveal === '1');
-  if (!c) return res.status(404).render('public/404', { title: 'Not found โ€” HoldForMe' });
+  if (!c) return res.status(404).render('public/404', { title: 'Not found โ€” Butlr' });
   res.render('public/call', {
-    title: c.business_name + ' โ€” call detail โ€” HoldForMe',
+    title: c.business_name + ' โ€” call detail โ€” Butlr',
     meta_desc: 'Call status and submitted details.',
     call: c,
     revealed: req.query.reveal === '1',
@@ -179,27 +179,27 @@ router.get('/api/category/:id', (req, res) => {
 });
 
 router.get('/how-it-works', (req, res) => {
-  res.render('public/how', { title: 'How it works โ€” HoldForMe', meta_desc: 'How HoldForMe waits on hold for you.' });
+  res.render('public/how', { title: 'How it works โ€” Butlr', meta_desc: 'How Butlr waits on hold for you.' });
 });
 
 // โ”€โ”€ Legal pages โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
 router.get('/privacy', (req, res) => {
   res.render('public/privacy', {
-    title: 'Privacy Policy โ€” HoldForMe',
-    meta_desc: 'How HoldForMe handles your account information, call data, and personal info. No sale. Encryption at rest. Deletion on request.',
+    title: 'Privacy Policy โ€” Butlr',
+    meta_desc: 'How Butlr handles your account information, call data, and personal info. No sale. Encryption at rest. Deletion on request.',
     updated: '2026-05-12',
   });
 });
 router.get('/terms', (req, res) => {
   res.render('public/terms', {
-    title: 'Terms of Service โ€” HoldForMe',
-    meta_desc: 'Terms governing your use of HoldForMe.',
+    title: 'Terms of Service โ€” Butlr',
+    meta_desc: 'Terms governing your use of Butlr.',
     updated: '2026-05-12',
   });
 });
 router.get('/accessibility', (req, res) => {
   res.render('public/accessibility', {
-    title: 'Accessibility โ€” HoldForMe',
+    title: 'Accessibility โ€” Butlr',
     meta_desc: 'Our WCAG 2.1 AA accessibility commitments, known gaps, and how to report a barrier.',
     updated: '2026-05-12',
   });
@@ -223,7 +223,7 @@ const PLANS = [
 
 router.get('/pricing', (req, res) => {
   res.render('public/pricing', {
-    title: 'Pricing โ€” HoldForMe',
+    title: 'Pricing โ€” Butlr',
     meta_desc: 'Free, Pro $9/mo, Concierge $29/mo. All plans include encryption at rest, TCPA-compliant dialing, and CCPA deletion-on-request.',
     plans: PLANS,
   });
@@ -232,7 +232,7 @@ router.get('/pricing', (req, res) => {
 router.post('/checkout', (req, res) => {
   const planId = String(req.body.plan || '').slice(0, 20);
   const plan = PLANS.find(p => p.id === planId);
-  if (!plan) return res.status(400).render('public/error', { title: 'Invalid plan โ€” HoldForMe', message: 'That plan does not exist.' });
+  if (!plan) return res.status(400).render('public/error', { title: 'Invalid plan โ€” Butlr', message: 'That plan does not exist.' });
 
   if (plan.id === 'free') {
     // Free tier: just redirect to /new (no checkout needed)
@@ -243,7 +243,7 @@ router.post('/checkout', (req, res) => {
   if (stripeDryRun) {
     console.log(`[stripe] DRY-RUN  plan=${plan.id} price=${plan.price} โ€” would create Checkout Session via stripe.checkout.sessions.create()`);
     return res.render('public/checkout-stub', {
-      title: 'Checkout โ€” HoldForMe',
+      title: 'Checkout โ€” Butlr',
       meta_desc: 'Phase 1 checkout stub.',
       plan,
     });
@@ -258,7 +258,7 @@ router.post('/checkout', (req, res) => {
 router.get('/social-claim', (req, res) => {
   const name = String(req.query.name || '').replace(/[^a-zA-Z0-9_]/g, '').slice(0, 30).toLowerCase();
   res.render('public/social-claim', {
-    title: name ? `Claim sheet for @${name} โ€” HoldForMe` : 'Social-Claim Sheet โ€” HoldForMe',
+    title: name ? `Claim sheet for @${name} โ€” Butlr` : 'Social-Claim Sheet โ€” Butlr',
     meta_desc: 'Generate direct-signup URLs for every major social platform when you lock a brand name.',
     name,
   });
diff --git a/routes/twilio-webhooks.js b/routes/twilio-webhooks.js
index 1f20cc4..4897b5f 100644
--- a/routes/twilio-webhooks.js
+++ b/routes/twilio-webhooks.js
@@ -83,7 +83,7 @@ router.get('/twiml/:call_id', async (req, res) => {
 });
 
 // โ”€โ”€ POST /twilio/status/:call_id โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
-// Maps Twilio call lifecycle to HoldForMe internal status.
+// Maps Twilio call lifecycle to Butlr internal status.
 router.post('/status/:call_id', (req, res) => {
   const callId = req.params.call_id;
   const cs = String(req.body.CallStatus || '').toLowerCase();
diff --git a/server.js b/server.js
index ad611ce..e4dd0d9 100644
--- a/server.js
+++ b/server.js
@@ -77,13 +77,13 @@ app.use('/', listenRoutes);
 app.use('/', publicRoutes);
 
 app.use((req, res) => {
-  res.status(404).render('public/404', { title: 'Not found โ€” HoldForMe' });
+  res.status(404).render('public/404', { title: 'Not found โ€” Butlr' });
 });
 
 app.use((err, req, res, next) => {
   console.error('[error]', err && err.stack ? err.stack : err);
   res.status(500).render('public/error', {
-    title: 'Server error โ€” HoldForMe',
+    title: 'Server error โ€” Butlr',
     message: 'Something went wrong.',
   });
 });
diff --git a/views/partials/footer.ejs b/views/partials/footer.ejs
index b5bafaa..8dab920 100644
--- a/views/partials/footer.ejs
+++ b/views/partials/footer.ejs
@@ -1,7 +1,7 @@
 <footer class="site-footer">
   <div class="wrap">
     <p class="muted small">
-      ยฉ <span id="yr"></span> HoldForMe ยท
+      ยฉ <span id="yr"></span> Butlr ยท
       <a href="/how-it-works">How it works</a> ยท
       <a href="/pricing">Pricing</a> ยท
       <a href="/calls">Your calls</a> ยท
diff --git a/views/partials/header.ejs b/views/partials/header.ejs
index 851d957..544a6c0 100644
--- a/views/partials/header.ejs
+++ b/views/partials/header.ejs
@@ -1,7 +1,7 @@
 <header class="site-header" data-transparent="true">
-  <a class="brand" href="/" aria-label="HoldForMe home">
-    <span class="brand-mark" aria-hidden="true">โฑ</span>
-    <span class="brand-name">HoldForMe</span>
+  <a class="brand" href="/" aria-label="Butlr home">
+    <span class="brand-mark" aria-hidden="true">๐ŸŽฉ</span>
+    <span class="brand-name">Butlr</span>
   </a>
 
   <button id="hamburger" class="hamburger" type="button"
diff --git a/views/public/accessibility.ejs b/views/public/accessibility.ejs
index 9c29dc7..5ed83a7 100644
--- a/views/public/accessibility.ejs
+++ b/views/public/accessibility.ejs
@@ -9,7 +9,7 @@
       <p class="muted">Last updated: <%= updated %></p>
 
       <h2>Our commitment</h2>
-      <p class="prose">HoldForMe is built to be usable by people with a wide range of disabilities โ€” vision, hearing, motor, cognitive. We target conformance with <strong>WCAG 2.1 Level AA</strong> across every public-facing page. Where we fall short, we list it openly below and commit to specific fixes.</p>
+      <p class="prose">Butlr is built to be usable by people with a wide range of disabilities โ€” vision, hearing, motor, cognitive. We target conformance with <strong>WCAG 2.1 Level AA</strong> across every public-facing page. Where we fall short, we list it openly below and commit to specific fixes.</p>
 
       <h2>What's been built for accessibility</h2>
       <ul class="prose">
@@ -33,10 +33,10 @@
       </ul>
 
       <h2>Need help or found a problem?</h2>
-      <p class="prose">If you can't use part of HoldForMe because of an accessibility barrier, email <a href="mailto:accessibility@holdforme.local">accessibility@holdforme.local</a> with: the page URL, the browser + screen reader (if any), and a description of what didn't work. We aim to respond within 2 business days and fix the issue within 30 days for WCAG-AA-level barriers.</p>
+      <p class="prose">If you can't use part of Butlr because of an accessibility barrier, email <a href="mailto:accessibility@butlr.ai">accessibility@butlr.ai</a> with: the page URL, the browser + screen reader (if any), and a description of what didn't work. We aim to respond within 2 business days and fix the issue within 30 days for WCAG-AA-level barriers.</p>
 
       <h2>Alternate ways to use the service</h2>
-      <p class="prose">If filling out the web wizard is not accessible to you for any reason, email <a href="mailto:hello@holdforme.local">hello@holdforme.local</a> with the same information the form asks for (business name, business phone, the goal of the call, your callback number) and we will queue the call manually.</p>
+      <p class="prose">If filling out the web wizard is not accessible to you for any reason, email <a href="mailto:hello@butlr.ai">hello@butlr.ai</a> with the same information the form asks for (business name, business phone, the goal of the call, your callback number) and we will queue the call manually.</p>
     </div>
   </section>
 </main>
diff --git a/views/public/home.ejs b/views/public/home.ejs
index 461255e..727410e 100644
--- a/views/public/home.ejs
+++ b/views/public/home.ejs
@@ -6,7 +6,7 @@
     <div class="hero-gucci-bg" role="img" aria-label="Phone-hold abstract ground"></div>
     <div class="hero-gucci-waves" aria-hidden="true"></div>
     <div class="hero-gucci-stack">
-      <h1 id="hero-wordmark" class="hero-gucci-wordmark">HoldForMe</h1>
+      <h1 id="hero-wordmark" class="hero-gucci-wordmark">Butlr</h1>
       <p class="hero-gucci-tagline"><em>Skip the hold music. We wait โ€” you live your life.</em></p>
       <div class="hero-gucci-cta">
         <a class="btn primary" href="/new">Start a call โ†’</a>
diff --git a/views/public/how.ejs b/views/public/how.ejs
index 9190cd3..f436333 100644
--- a/views/public/how.ejs
+++ b/views/public/how.ejs
@@ -40,7 +40,7 @@
       </ul>
 
       <h2>Legal</h2>
-      <p>You authorize HoldForMe to place outbound calls on your behalf to the specific number you submit, for the specific purpose you describe. We follow TCPA, CAN-SPAM, applicable two-party-recording laws, and the business's own rules around third-party callers. We never share your account info with anyone except the business you ask us to call, and only when the rep asks for it.</p>
+      <p>You authorize Butlr to place outbound calls on your behalf to the specific number you submit, for the specific purpose you describe. We follow TCPA, CAN-SPAM, applicable two-party-recording laws, and the business's own rules around third-party callers. We never share your account info with anyone except the business you ask us to call, and only when the rep asks for it.</p>
     </div>
   </section>
 </main>
diff --git a/views/public/new.ejs b/views/public/new.ejs
index a56ad96..0ae371c 100644
--- a/views/public/new.ejs
+++ b/views/public/new.ejs
@@ -145,7 +145,7 @@
           <label class="check"><input type="checkbox" name="notify_sms"   <%= form.notify_sms === 'on' ? 'checked' : 'checked' %>>     Text me when an agent picks up</label>
           <label class="check"><input type="checkbox" name="notify_email" <%= form.notify_email === 'on' ? 'checked' : '' %>>          Email me the call summary afterwards</label>
           <label class="check"><input type="checkbox" name="consent_recording" <%= form.consent_recording === 'on' ? 'checked' : '' %>>I consent to recording the call (recording laws vary by state; we follow two-party-consent where required)</label>
-          <label class="check req"><input type="checkbox" name="consent_terms" <%= form.consent_terms === 'on' ? 'checked' : '' %> required> I authorize HoldForMe to dial the business number on my behalf and bridge me when a human answers <em>required</em></label>
+          <label class="check req"><input type="checkbox" name="consent_terms" <%= form.consent_terms === 'on' ? 'checked' : '' %> required> I authorize Butlr to dial the business number on my behalf and bridge me when a human answers <em>required</em></label>
         </fieldset>
 
         <div class="form-actions">
diff --git a/views/public/privacy.ejs b/views/public/privacy.ejs
index d019076..f737024 100644
--- a/views/public/privacy.ejs
+++ b/views/public/privacy.ejs
@@ -42,25 +42,25 @@
       </ul>
 
       <h2>6. Retention &amp; deletion</h2>
-      <p class="prose">Call submissions are retained for 90 days after the call's status reaches "done" or "failed", then automatically purged. You can request immediate deletion of any call by emailing <a href="mailto:privacy@holdforme.local">privacy@holdforme.local</a> with the call ID; we will purge within 7 days and confirm in writing. Account information is wiped from our records at the same time.</p>
+      <p class="prose">Call submissions are retained for 90 days after the call's status reaches "done" or "failed", then automatically purged. You can request immediate deletion of any call by emailing <a href="mailto:privacy@butlr.ai">privacy@butlr.ai</a> with the call ID; we will purge within 7 days and confirm in writing. Account information is wiped from our records at the same time.</p>
 
       <h2>7. Call recording</h2>
       <p class="prose">Recording happens only when you check the "I consent to recording the call" box on the submission form. In two-party-consent states (CA, FL, MA, MT, PA, WA, and several others), our call-bridge plays a brief audible "this call may be recorded" disclosure to the rep at the start of the call. You can revoke recording consent at any time before the call connects by emailing the address above with the call ID.</p>
 
       <h2>8. TCPA + telemarketing law</h2>
-      <p class="prose">HoldForMe is not a telemarketer. We do not initiate calls for commercial solicitation. We dial only the specific business number you submit, for the specific purpose you describe, on your behalf. We do not maintain a calling list, do not auto-dial multiple numbers, and do not contact you for purposes unrelated to the call you submitted.</p>
+      <p class="prose">Butlr is not a telemarketer. We do not initiate calls for commercial solicitation. We dial only the specific business number you submit, for the specific purpose you describe, on your behalf. We do not maintain a calling list, do not auto-dial multiple numbers, and do not contact you for purposes unrelated to the call you submitted.</p>
 
       <h2>9. Children</h2>
-      <p class="prose">HoldForMe is not intended for users under 18. We do not knowingly collect data from minors. If you believe a minor has submitted a call, email <a href="mailto:privacy@holdforme.local">privacy@holdforme.local</a> and we will purge the submission within 7 days.</p>
+      <p class="prose">Butlr is not intended for users under 18. We do not knowingly collect data from minors. If you believe a minor has submitted a call, email <a href="mailto:privacy@butlr.ai">privacy@butlr.ai</a> and we will purge the submission within 7 days.</p>
 
       <h2>10. California residents (CCPA / CPRA)</h2>
-      <p class="prose">You have the right to: (a) know what we collect, (b) request deletion, (c) opt out of any sale of your data (we do not sell data), (d) non-discrimination for exercising these rights. Email <a href="mailto:privacy@holdforme.local">privacy@holdforme.local</a> from the address associated with your call submissions; we verify by sending a confirmation link back to the same address.</p>
+      <p class="prose">You have the right to: (a) know what we collect, (b) request deletion, (c) opt out of any sale of your data (we do not sell data), (d) non-discrimination for exercising these rights. Email <a href="mailto:privacy@butlr.ai">privacy@butlr.ai</a> from the address associated with your call submissions; we verify by sending a confirmation link back to the same address.</p>
 
       <h2>11. Changes to this policy</h2>
       <p class="prose">If we change this policy materially, we will post the new version with a new "Last updated" date and email past submitters at least 14 days before it takes effect.</p>
 
       <h2>12. Contact</h2>
-      <p class="prose">Privacy questions / deletion requests: <a href="mailto:privacy@holdforme.local">privacy@holdforme.local</a>. Operator: HoldForMe (operating under the parent business listed in the <a href="/terms">Terms</a>).</p>
+      <p class="prose">Privacy questions / deletion requests: <a href="mailto:privacy@butlr.ai">privacy@butlr.ai</a>. Operator: Butlr (operating under the parent business listed in the <a href="/terms">Terms</a>).</p>
     </div>
   </section>
 </main>
diff --git a/views/public/terms.ejs b/views/public/terms.ejs
index 492439b..0033997 100644
--- a/views/public/terms.ejs
+++ b/views/public/terms.ejs
@@ -8,12 +8,12 @@
       <h1>Terms of Service</h1>
       <p class="muted">Last updated: <%= updated %></p>
 
-      <h2>1. What HoldForMe does</h2>
-      <p class="prose">HoldForMe places outbound phone calls on your behalf to businesses you specify, waits through their hold queue, and bridges you onto the call when a live human representative picks up. You authorize each call by submitting it through our form. We do not impersonate you. We do not authorize transactions on your behalf. We do not initiate calls without your specific per-call submission.</p>
+      <h2>1. What Butlr does</h2>
+      <p class="prose">Butlr places outbound phone calls on your behalf to businesses you specify, waits through their hold queue, and bridges you onto the call when a live human representative picks up. You authorize each call by submitting it through our form. We do not impersonate you. We do not authorize transactions on your behalf. We do not initiate calls without your specific per-call submission.</p>
 
       <h2>2. Your responsibilities</h2>
       <ul class="prose">
-        <li>You will submit only legitimate, lawful call goals. You will not use HoldForMe to harass, defraud, or impersonate anyone.</li>
+        <li>You will submit only legitimate, lawful call goals. You will not use Butlr to harass, defraud, or impersonate anyone.</li>
         <li>You will not submit calls to phone numbers that do not belong to the business you describe.</li>
         <li>You will not submit calls to emergency services (911, suicide hotlines, etc.). Use those services directly.</li>
         <li>You will not submit calls to numbers on the National Do Not Call Registry or to wireless numbers in bulk-marketing contexts (TCPA).</li>
@@ -28,7 +28,7 @@
       </ul>
 
       <h2>4. Pricing &amp; refunds</h2>
-      <p class="prose">During the MVP / phase-1 testing period, HoldForMe is provided free of charge. When billing launches:</p>
+      <p class="prose">During the MVP / phase-1 testing period, Butlr is provided free of charge. When billing launches:</p>
       <ul class="prose">
         <li>Pricing is published on the <a href="/pricing">pricing page</a> and updated there with at least 14 days' notice before changes.</li>
         <li>You set a per-call max-spend cap on the submission form. We never bill above that cap.</li>
@@ -37,13 +37,13 @@
       </ul>
 
       <h2>5. Acceptable use</h2>
-      <p class="prose">You agree not to: (a) reverse-engineer our call-routing logic to evade fair-use limits, (b) use HoldForMe to circumvent business policies that explicitly bar third-party callers (some banks require account-holder voice authentication for certain transactions; we cannot impersonate you for those), (c) submit the same call to multiple instances to evade per-account rate limits.</p>
+      <p class="prose">You agree not to: (a) reverse-engineer our call-routing logic to evade fair-use limits, (b) use Butlr to circumvent business policies that explicitly bar third-party callers (some banks require account-holder voice authentication for certain transactions; we cannot impersonate you for those), (c) submit the same call to multiple instances to evade per-account rate limits.</p>
 
       <h2>6. Disclaimer of warranties</h2>
-      <p class="prose">HoldForMe is provided "as is" without warranty of any kind, express or implied, including but not limited to merchantability, fitness for a particular purpose, or non-infringement. Some jurisdictions don't allow such limitations; in those jurisdictions, the limitation applies to the maximum extent permitted by law.</p>
+      <p class="prose">Butlr is provided "as is" without warranty of any kind, express or implied, including but not limited to merchantability, fitness for a particular purpose, or non-infringement. Some jurisdictions don't allow such limitations; in those jurisdictions, the limitation applies to the maximum extent permitted by law.</p>
 
       <h2>7. Limitation of liability</h2>
-      <p class="prose">To the maximum extent permitted by law, HoldForMe's aggregate liability for any claim arising from your use of the service is limited to the total amount you paid us in the 12 months preceding the claim, or $100, whichever is greater. We are not liable for indirect, consequential, or punitive damages.</p>
+      <p class="prose">To the maximum extent permitted by law, Butlr's aggregate liability for any claim arising from your use of the service is limited to the total amount you paid us in the 12 months preceding the claim, or $100, whichever is greater. We are not liable for indirect, consequential, or punitive damages.</p>
 
       <h2>8. Governing law &amp; venue</h2>
       <p class="prose">These Terms are governed by California law. Any dispute will be resolved in the state or federal courts located in Los Angeles County, California, except that small-claims actions may be filed in your local jurisdiction.</p>
@@ -52,7 +52,7 @@
       <p class="prose">We may update these Terms by posting a new version with a new "Last updated" date. Material changes will be announced 14 days in advance via email to past submitters. Continued use of the service after the effective date constitutes acceptance.</p>
 
       <h2>10. Contact</h2>
-      <p class="prose">Questions about these Terms: <a href="mailto:legal@holdforme.local">legal@holdforme.local</a>.</p>
+      <p class="prose">Questions about these Terms: <a href="mailto:legal@butlr.ai">legal@butlr.ai</a>.</p>
     </div>
   </section>
 </main>
diff --git a/views/public/wizard-4-callback.ejs b/views/public/wizard-4-callback.ejs
index e4b1b62..15e4c4f 100644
--- a/views/public/wizard-4-callback.ejs
+++ b/views/public/wizard-4-callback.ejs
@@ -70,7 +70,7 @@
           <label class="check"><input type="checkbox" name="notify_sms"   <%= state.notify_sms ? 'checked' : 'checked' %>> Text me when an agent picks up</label>
           <label class="check"><input type="checkbox" name="notify_email" <%= state.notify_email ? 'checked' : '' %>>          Email me the call summary afterwards</label>
           <label class="check"><input type="checkbox" name="consent_recording" <%= state.consent_recording ? 'checked' : '' %>> Record the call (two-party-consent states get an in-call disclosure)</label>
-          <label class="check req"><input type="checkbox" name="consent_terms" <%= state.consent_terms ? 'checked' : '' %> required> I authorize HoldForMe to dial the business on my behalf and bridge me when a human picks up <em>required</em></label>
+          <label class="check req"><input type="checkbox" name="consent_terms" <%= state.consent_terms ? 'checked' : '' %> required> I authorize Butlr to dial the business on my behalf and bridge me when a human picks up <em>required</em></label>
         </fieldset>
 
         <div class="review-card">

โ† 9846567 live-audio bridge + recording + Whisper transcript on finish  ยท  back to Butlr  ยท  API-Key auth preferred over Auth Token for Twilio f463de5 โ†’