← back to Butlr

views/public/home.ejs

235 lines

<%- include('../partials/head', { title, meta_desc }) %>
<%- include('../partials/header') %>

<main class="home">
  <section class="hero-gucci" aria-labelledby="hero-wordmark">
    <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">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>
        <a class="btn ghost"   href="/how-it-works">How it works</a>
      </div>
    </div>
    <a class="hero-gucci-scroll" href="#use-cases" aria-label="Scroll for use cases">↓</a>
  </section>


  <% if (locals.user) { %>
  <section class="section" id="ez-call" style="background:linear-gradient(180deg,rgba(0,0,0,.02),transparent);padding:32px 0 24px;">
    <div class="wrap" style="max-width:780px;margin:0 auto;padding:0 18px;">
      <div style="background:var(--bg,#fff);border:1px solid var(--line,#d2cdc3);border-radius:12px;padding:26px 28px;box-shadow:0 8px 28px -22px rgba(0,0,0,.18)">
        <header style="display:flex;align-items:baseline;justify-content:space-between;flex-wrap:wrap;gap:8px;margin-bottom:18px">
          <h2 style="margin:0;font:500 22px/1 var(--serif,'Cormorant Garamond',Georgia,serif)">EZ Call</h2>
          <span style="font:11px var(--sans,system-ui);color:var(--ink-faint,#7a6e5a);letter-spacing:.04em">4 questions. We dial.</span>
        </header>

        <form id="ez-form" method="POST" action="/api/quick-dial" autocomplete="off" style="display:flex;flex-direction:column;gap:14px">

          <!-- 1. Who -->
          <label style="display:flex;flex-direction:column;gap:5px">
            <span style="font:600 10px var(--sans,system-ui);letter-spacing:.18em;text-transform:uppercase;color:var(--ink-faint,#7a6e5a)">1 · Who are we calling?</span>
            <div style="display:flex;gap:8px;flex-wrap:wrap">
              <input type="text" name="business_name" placeholder="Business name (e.g. AT&T customer service)" required
                     style="flex:1;min-width:180px;padding:10px 12px;font:14px var(--sans,system-ui);border:1px solid var(--line,#d2cdc3);border-radius:6px;background:transparent">
              <input type="tel" name="business_phone" placeholder="Phone (E.164: +1...)" required
                     style="width:180px;padding:10px 12px;font:14px ui-monospace,Menlo,monospace;border:1px solid var(--line,#d2cdc3);border-radius:6px;background:transparent">
            </div>
          </label>

          <!-- 2. Where (Steve's location, optional context) -->
          <label style="display:flex;flex-direction:column;gap:5px">
            <span style="font:600 10px var(--sans,system-ui);letter-spacing:.18em;text-transform:uppercase;color:var(--ink-faint,#7a6e5a)">2 · Where are you located?</span>
            <input type="text" name="caller_location" placeholder="City, state, or zip (helps if you only gave a chain name)"
                   style="padding:10px 12px;font:14px var(--sans,system-ui);border:1px solid var(--line,#d2cdc3);border-radius:6px;background:transparent">
          </label>

          <!-- 3. What -->
          <label style="display:flex;flex-direction:column;gap:5px">
            <span style="font:600 10px var(--sans,system-ui);letter-spacing:.18em;text-transform:uppercase;color:var(--ink-faint,#7a6e5a)">3 · What do you need?</span>
            <textarea name="goal" required rows="3" placeholder="The goal of the call. E.g. 'Ask if Sony WH-1000XM5 is in stock and the price. Hang up after they answer.'"
                      style="padding:10px 12px;font:14px var(--sans,system-ui);border:1px solid var(--line,#d2cdc3);border-radius:6px;background:transparent;resize:vertical;min-height:72px"></textarea>
          </label>

          <!-- 4. When -->
          <fieldset style="border:0;padding:0;margin:0">
            <legend style="font:600 10px var(--sans,system-ui);letter-spacing:.18em;text-transform:uppercase;color:var(--ink-faint,#7a6e5a);margin-bottom:6px">4 · When?</legend>
            <div style="display:flex;gap:14px;flex-wrap:wrap;align-items:center">
              <label style="display:flex;gap:5px;align-items:center;cursor:pointer;font:14px var(--sans,system-ui)">
                <input type="radio" name="when_mode" value="now" checked> Right now
              </label>
              <label style="display:flex;gap:5px;align-items:center;cursor:pointer;font:14px var(--sans,system-ui)">
                <input type="radio" name="when_mode" value="later"> Later
              </label>
              <label style="display:flex;gap:5px;align-items:center;cursor:pointer;font:14px var(--sans,system-ui)">
                <input type="radio" name="when_mode" value="recurring"> Recurring
              </label>
            </div>
            <input type="datetime-local" name="schedule_at" id="ez-when-dt" style="display:none;margin-top:8px;padding:8px;font:14px var(--sans,system-ui);border:1px solid var(--line,#d2cdc3);border-radius:6px">
            <input type="text" name="cron_expr" id="ez-when-cron" placeholder="cron — e.g. 0 17 * * 5 (every Friday 5 PM)" style="display:none;margin-top:8px;padding:8px;font:13px ui-monospace,Menlo,monospace;border:1px solid var(--line,#d2cdc3);border-radius:6px;width:100%;max-width:380px">
          </fieldset>

          <div style="display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-top:6px">
            <button type="submit" class="btn primary" style="padding:12px 24px;font:600 14px var(--sans,system-ui);background:var(--ink,#1a1816);color:var(--bg,#f7f3eb);border:0;border-radius:6px;cursor:pointer;letter-spacing:.04em">
              <span id="ez-btn-now">📞 Dial now</span>
              <span id="ez-btn-later" style="display:none">⏰ Schedule call</span>
            </button>
            <span id="ez-status" style="font:12px var(--sans,system-ui);color:var(--ink-faint,#7a6e5a)"></span>
          </div>

          <p style="margin:14px 0 0;font:11px var(--sans,system-ui);color:var(--ink-faint,#7a6e5a);line-height:1.5">
            Calls run ~$0.01–0.05 each. We respect DNC + the 4-call-per-number cap. Audio recorded for quality if consent_recording is on.
          </p>
        </form>
      </div>
    </div>

    <script>
      (function(){
        var form = document.getElementById('ez-form');
        var dt   = document.getElementById('ez-when-dt');
        var cron = document.getElementById('ez-when-cron');
        var btnNow   = document.getElementById('ez-btn-now');
        var btnLater = document.getElementById('ez-btn-later');
        var status   = document.getElementById('ez-status');

        document.querySelectorAll('input[name=when_mode]').forEach(function(r){
          r.addEventListener('change', function(){
            dt.style.display   = (r.value === 'later'     && r.checked) ? 'block' : 'none';
            cron.style.display = (r.value === 'recurring' && r.checked) ? 'block' : 'none';
            // If radio changed but its visibility wasn't matched above, force-hide
            if (r.checked && r.value !== 'later')     dt.style.display = 'none';
            if (r.checked && r.value !== 'recurring') cron.style.display = 'none';
            btnNow.style.display   = (r.value === 'now'   && r.checked) ? '' : 'none';
            btnLater.style.display = (r.value !== 'now'   && r.checked) ? '' : 'none';
          });
        });

        form.addEventListener('submit', async function(e){
          e.preventDefault();
          status.textContent = 'Submitting…';
          var fd = new FormData(form);
          var when = fd.get('when_mode') || 'now';
          try {
            if (when === 'later' || when === 'recurring') {
              // POST to /api/scheduled (JSON)
              var body = {
                business_name:  fd.get('business_name'),
                business_phone: fd.get('business_phone'),
                goal:           fd.get('goal'),
                callback_phone: '',  // server falls back to req.user.callback_phone
                schedule_at:    when === 'later'     ? new Date(fd.get('schedule_at')).toISOString() : null,
                cron_expr:      when === 'recurring' ? fd.get('cron_expr') : null,
                consent_recording: true,
              };
              var r = await fetch('/api/scheduled', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(body) });
              var j = await r.json();
              if (j.ok) { status.textContent = '✓ Scheduled. Redirecting to /calendar…'; setTimeout(()=>location.href='/calendar', 600); }
              else      { status.textContent = '✗ ' + (j.error || 'schedule failed'); }
            } else {
              // POST to /api/quick-dial (form-urlencoded, immediate)
              var r2 = await fetch('/api/quick-dial', { method:'POST', body: fd });
              var j2 = await r2.json();
              if (j2.ok) { status.textContent = '✓ Dialing. Redirecting to live view…'; setTimeout(()=>location.href='/calls/'+j2.call_id+'/live', 600); }
              else       { status.textContent = '✗ ' + (j2.error || j2.errors && j2.errors.join('; ') || 'dial failed'); }
            }
          } catch (err) { status.textContent = '✗ ' + err.message; }
        });
      })();
    </script>
  </section>
  <% } %>

  <section class="section" id="use-cases">
    <div class="wrap">
      <div class="section-head">
        <h2>Pick a use case</h2>
        <a class="muted" href="/new">Start any call →</a>
      </div>
      <p class="muted" style="max-width:760px;margin:.25rem 0 1.5rem">
        The most common queues we wait on. Pick one and we'll preset the right fields for you — or pick "Something else" and tell us yourself.
      </p>

      <div class="category-grid">
        <a class="category-card" href="/new?category=credit-card-increase">
          <span class="category-icon">💳</span>
          <strong>Credit card</strong>
          <span class="muted small">Limit increase, dispute a charge</span>
        </a>
        <a class="category-card" href="/new?category=hospital-billing">
          <span class="category-icon">🏥</span>
          <strong>Hospital</strong>
          <span class="muted small">Billing dispute, schedule appointment</span>
        </a>
        <a class="category-card" href="/new?category=restaurant-reservation">
          <span class="category-icon">🍽️</span>
          <strong>Restaurant</strong>
          <span class="muted small">Reservation at a hard-to-book spot</span>
        </a>
        <a class="category-card" href="/new?category=airline-change">
          <span class="category-icon">✈️</span>
          <strong>Airline</strong>
          <span class="muted small">Change a flight, request refund</span>
        </a>
        <a class="category-card" href="/new?category=cable-cancel">
          <span class="category-icon">📡</span>
          <strong>Cable / wireless</strong>
          <span class="muted small">Cancel, dispute, retention call</span>
        </a>
        <a class="category-card" href="/new?category=insurance-claim">
          <span class="category-icon">🛡️</span>
          <strong>Insurance</strong>
          <span class="muted small">Claim status, denial appeal</span>
        </a>
        <a class="category-card" href="/new?category=utility-dispute">
          <span class="category-icon">⚡</span>
          <strong>Utility</strong>
          <span class="muted small">Dispute a bill, set up service</span>
        </a>
        <a class="category-card" href="/new?category=warranty-claim">
          <span class="category-icon">🔧</span>
          <strong>Warranty</strong>
          <span class="muted small">File a claim, schedule repair</span>
        </a>
        <a class="category-card" href="/new?category=mortgage-loan">
          <span class="category-icon">🏦</span>
          <strong>Mortgage / loan</strong>
          <span class="muted small">Payoff, hardship, refi questions</span>
        </a>
        <a class="category-card" href="/new?category=subscription-cancel">
          <span class="category-icon">🔁</span>
          <strong>Subscription</strong>
          <span class="muted small">Cancel, get a refund</span>
        </a>
        <a class="category-card" href="/new?category=other">
          <span class="category-icon">☎️</span>
          <strong>Something else</strong>
          <span class="muted small">Anywhere there's a queue</span>
        </a>
      </div>
    </div>
  </section>

  <section class="section alt">
    <div class="wrap two-col">
      <div>
        <h2>The deal</h2>
        <ol class="prose">
          <li><strong>You submit one form.</strong> Who to call, what you need, account info if the rep will ask.</li>
          <li><strong>We dial and wait.</strong> Our system holds through the queue — could be 5 minutes, could be 47. Hold music doesn't bother us.</li>
          <li><strong>When a human answers, your phone rings.</strong> You jump in fresh, with your goal and account info on screen. No 90-second context dump required.</li>
        </ol>
      </div>
      <div>
        <h2>What this is not</h2>
        <p>We don't impersonate you. We don't read your password to a stranger. We don't promise to fix what only you can authorize.</p>
        <p class="muted">For calls where you'd rather not be on the line at all (low-stakes reservations, simple cancellations), Phase 2 will support an AI voice agent that speaks your script — opt-in only, with full transcript.</p>
      </div>
    </div>
  </section>
</main>

<%- include('../partials/footer') %>