<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Stephen Lloyd Webber — Writer</title>
  <meta name="description" content="A physical writing practice built on pen, paper, and fifteen minutes of undivided attention. Books, courses, events, and typewriter workshops.">
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Newsreader:ital,opsz,wght@0,6..72,300;0,6..72,400;0,6..72,500;1,6..72,300;1,6..72,400&family=Lexend+Deca:wght@300;400;500&family=Courier+Prime:wght@400;700&display=swap">
  <link rel="stylesheet" href="css/style.css">
  <link rel="icon" type="image/x-icon" href="/favicon.ico">
  <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
  <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
</head>
<body>

  <nav class="nav">
    <div class="nav__inner">
      <a href="/" class="nav__logo">Stephen Lloyd Webber</a>
      <ul class="nav__links" id="navLinks">
                <li><a href="/books">Books</a></li>
        <li><a href="/practice">Practice</a></li>
        <li><a href="/events">Events</a></li>
        <li><a href="/yourstory">Your Story</a></li>
        <li><a href="/about">About</a></li>
        <li><a href="https://shop.stephenlloydwebber.com" target="_blank" rel="noopener">Shop</a></li>
        <li><a href="/typewriter-buying/">Typewriter Finder</a></li>
      </ul>
      <button class="nav__search-toggle" id="searchToggle" aria-label="Search">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" width="18" height="18">
          <circle cx="11" cy="11" r="8"/>
          <line x1="21" y1="21" x2="16.65" y2="16.65"/>
        </svg>
      </button>
      <button class="nav__toggle" id="navToggle" aria-label="Menu">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round">
          <line x1="4" y1="7" x2="20" y2="7"/>
          <line x1="4" y1="12" x2="20" y2="12"/>
          <line x1="4" y1="17" x2="20" y2="17"/>
        </svg>
      </button>
    </div>
  </nav>

  <section class="hero hero--split">
    <div class="container">
      <div class="hero__grid">
        <div>
          <p class="label fade-in fade-in--d1" style="margin-bottom: var(--space-sm);">Writing retreats, books, courses.</p>
          <h1 class="fade-in fade-in--d1" style="font-size:
          2.8rem;">Fifteen minutes with a pen or a typewriter can accomplish what
          nothing else can.</h1>
          <p class="hero__sub fade-in fade-in--d2" style="margin: 0 0
          var(--space-lg);"><span class="hl">Try
          it for five days.</span> Each day you get a short prompt
          and fifteen minutes of your own undivided attention.</p>
          <div class="hero-signup fade-in fade-in--d3">
            <p class="hero-signup__label">Start with five free exercises delivered over five days.</p>
            <form class="hero-signup__form" id="heroKitForm" onsubmit="return submitHeroKit(event)">
              <div style="position:absolute;left:-9999px;" aria-hidden="true"><input type="text" name="hp_field" tabindex="-1" autocomplete="off"></div>
              <input type="email" id="heroKitEmail" placeholder="Your email" required>
              <button type="submit" class="btn btn--primary" id="heroKitBtn">Start the five days</button>
            </form>
            <p class="hero-signup__note" id="heroKitNote">Unsubscribe anytime.</p>
          </div>
        </div>
        <div class="fade-in fade-in--d2">
          <img src="img/hero.jpg" alt="Hermes 3000 typewriter" class="site-img" style="aspect-ratio: 3/4; object-fit: cover;">
        </div>
      </div>
    </div>
  </section>

  <hr class="rule">

  <section>
    <div class="testimonial">
      <p class="testimonial__text">"My novel was literally transformed in a day. I expected the block I had been feeling to go away, but I didn't expect the floodgates of creativity to open as they did."</p>
      <p class="testimonial__attr">Jennifer Sage</p>
    </div>
  </section>

  <hr class="rule">


  <section>
    <div class="container" style="max-width: var(--content-width); margin: 0 auto;">
      <h2 style="margin-bottom: var(--space-md);">How to start</h2>
      <p class="text-light">The practice starts with a question — something you're genuinely curious about. You
	open your awareness, then write without stopping. The question
	gives you a compass, and the peripheral awareness settles
	something in the body without you having to try. <br /> <br />When writing feels good physically, it becomes something you return to.</p>
    </div>
  </section>

  <hr class="rule">



<section>
  <div class="container">
    <div class="about-split" style="max-width: var(--content-width); margin: 0 auto;">
      <div>
        <img src="img/notebookpages.jpg" alt="Pages from a writing session" class="site-img" style="aspect-ratio: 3/4; object-fit: cover; max-width: 320px;">
      </div>
      <div style="display: flex; flex-direction: column; justify-content: center;">
        <p class="text-light" style="font-size: 1.1rem; line-height: 1.7; margin-bottom: var(--space-sm);">Attention is fragmented and AI writes for everyone now. The less you use your own voice, the harder it is to find.</p><p class="text-light" style="font-size: 1.1rem; line-height: 1.7;
    margin-bottom: var(--space-md);">
Five mornings, fifteen minutes
    each. Enough to start a writing practice and see if it sticks.</p>
        <div class="hero-signup">
          <form class="hero-signup__form" id="btmKitForm" onsubmit="return submitBtmKit(event)">
            <div style="position:absolute;left:-9999px;" aria-hidden="true"><input type="text" name="hp_field" tabindex="-1" autocomplete="off"></div>
            <input type="email" id="btmKitEmail" placeholder="Your email" required>
            <button type="submit" class="btn btn--primary" id="btmKitBtn">Five days, free</button>
          </form>
          <p class="hero-signup__note" id="btmKitNote">Unsubscribe anytime.</p>
        </div>
      </div>
    </div>
  </div>
</section>


  <script>
async function submitBtmKit(e) {
  e.preventDefault();
  if (!_spamCheck(e.target)) { return false; }
  var btn = document.getElementById('btmKitBtn');
  var email = document.getElementById('btmKitEmail');
  var note = document.getElementById('btmKitNote');
  btn.textContent = 'Sending\u2026';
  btn.disabled = true;
  try {
    var res = await fetch('https://app.kit.com/forms/9285477/subscriptions', {
      method: 'POST',
      headers: {'Content-Type': 'application/json', 'Accept': 'application/json'},
      body: JSON.stringify({email_address: email.value})
    });
    if (res.ok) {
      email.style.display = 'none';
      btn.style.display = 'none';
      note.textContent = "You're in. Check your email to confirm.";
      note.style.color = 'var(--accent)';
    } else { throw new Error(); }
  } catch(err) {
    btn.textContent = 'Five days, free';
    btn.disabled = false;
    note.textContent = 'Something went wrong. Try again or email stephen@tmmw.io';
    note.style.color = 'var(--accent)';
  }
  return false;
}
</script>
  <script>
  var _pageLoadTime = Date.now();
  function _spamCheck(form) {
    // Honeypot: if filled, it's a bot
    var hp = form.querySelector('[name="hp_field"]');
    if (hp && hp.value) return false;
    // Too fast: less than 2s after page load
    if (Date.now() - _pageLoadTime < 2000) return false;
    // Rate limit: no resubmit within 10s
    if (form._lastSubmit && Date.now() - form._lastSubmit < 10000) return false;
    form._lastSubmit = Date.now();
    return true;
  }
  </script>
<script>
  async function submitHeroKit(e) {
    e.preventDefault();
    if (!_spamCheck(e.target)) { return false; }
    var btn = document.getElementById('heroKitBtn');
    var email = document.getElementById('heroKitEmail');
    var note = document.getElementById('heroKitNote');
    btn.textContent = 'Sending\u2026';
    btn.disabled = true;
    try {
      var res = await fetch('https://app.kit.com/forms/9285477/subscriptions', {
        method: 'POST',
        headers: {'Content-Type': 'application/json', 'Accept': 'application/json'},
        body: JSON.stringify({email_address: email.value})
      });
      if (res.ok) {
        email.style.display = 'none';
        btn.style.display = 'none';
        note.textContent = 'You\'re in. Check your email to confirm.';
        note.style.color = 'var(--accent)';
      } else { throw new Error(); }
    } catch(err) {
      btn.textContent = 'Start the five days';
      btn.disabled = false;
      note.textContent = 'Something went wrong. Try again or email stephen@tmmw.io';
      note.style.color = 'var(--accent)';
    }
    return false;
  }
  </script>

    <footer class="footer">
    <div class="container">
      <div class="footer__inner">
        <div class="footer__left">
          <p class="footer__name">Stephen Lloyd Webber</p>
          <p class="footer__tagline">Writer. Austin, TX.</p>
          <div class="footer__subscribe">
            <p class="footer__subscribe-heading">Stay close to the work</p>
            <p class="footer__subscribe-note">I send out very occasional updates on upcoming books and events. Unsubscribe anytime.</p>
            <form class="footer__subscribe-form" id="footerKitForm" onsubmit="return submitFooterKit(event)">
              <div style="position:absolute;left:-9999px;" aria-hidden="true"><input type="text" name="hp_field" tabindex="-1" autocomplete="off"></div>
              <input type="email" id="footerKitEmail" placeholder="Your email" required>
              <button type="submit" class="btn btn--primary btn--sm" id="footerKitBtn">Subscribe</button>
            </form>
            <p class="footer__subscribe-status" id="footerKitNote"></p>
          </div>
        </div>
        <div class="footer__links">
          <div class="footer__col">
            <h4>Work</h4>
            <ul>
                            <li><a href="/books">Books</a></li>
              <li><a href="/practice">Practice</a></li>
              <li><a href="/events">Events</a></li>
              <li><a href="/yourstory">Your Story</a></li>
              <li><a href="/ghostwriting">Ghostwriting</a></li>
              <li><a href="/about">About</a></li>
              <li><a href="https://shop.stephenlloydwebber.com" target="_blank" rel="noopener">Shop</a></li>
              <li><a href="/typewriter-buying/">Typewriter Finder</a></li>
            </ul>
          </div>
          <div class="footer__col">
            <h4>Connect</h4>
            <ul>
              <li><a href="https://tmmw.substack.com" target="_blank" rel="noopener">Substack</a></li>
              <li><a href="https://youtube.com/@tmmwio" target="_blank" rel="noopener">YouTube</a></li>
              <li><a href="https://www.instagram.com/stephenlloydwebber/" target="_blank" rel="noopener">Instagram</a></li>
              <li><a href="mailto:stephen@tmmw.io">Email</a></li>
            </ul>
          </div>
        </div>
      </div>
      <div class="footer__bottom">
        <p class="footer__copy">&copy; 2026 Stephen Lloyd Webber</p>
        <p class="footer__email"><a href="mailto:stephen@tmmw.io">stephen@tmmw.io</a></p>
      </div>
    </div>
  </footer>

  <script>
    const toggle = document.getElementById('navToggle');
    const links = document.getElementById('navLinks');
    toggle.addEventListener('click', () => links.classList.toggle('open'));
    links.querySelectorAll('a').forEach(a => {
      a.addEventListener('click', () => links.classList.remove('open'));
    });
  </script>


  <div class="search-overlay" id="searchOverlay">
    <div class="search-overlay__inner">
      <input type="text" class="search-overlay__input" id="searchInput" placeholder="Search this site…" autocomplete="off">
      <div class="search-overlay__results" id="searchResults"></div>
      <button class="search-overlay__close" id="searchClose" aria-label="Close search">&times;</button>
    </div>
  </div>

  <script>
  async function submitFooterKit(e) {
    e.preventDefault();
    if (!_spamCheck(e.target)) { return false; }
    var btn = document.getElementById('footerKitBtn');
    var email = document.getElementById('footerKitEmail');
    var note = document.getElementById('footerKitNote');
    btn.textContent = 'Sending\u2026';
    btn.disabled = true;
    try {
      var res = await fetch('https://app.convertkit.com/forms/8903458/subscriptions', {
        method: 'POST',
        headers: {'Content-Type': 'application/json', 'Accept': 'application/json'},
        body: JSON.stringify({email_address: email.value})
      });
      if (res.ok) {
        email.style.display = 'none';
        btn.style.display = 'none';
        note.textContent = 'You\'re in. Check your email to confirm.';
        note.style.color = 'var(--accent)';
      } else { throw new Error(); }
    } catch(err) {
      btn.textContent = 'Subscribe';
      btn.disabled = false;
      note.textContent = 'Something went wrong. Try again or email stephen@tmmw.io';
      note.style.color = 'var(--accent)';
    }
    return false;
  }
  </script>

<script>
  (function() {
    var searchIndex = null;
    var toggle = document.getElementById('searchToggle');
    var overlay = document.getElementById('searchOverlay');
    var input = document.getElementById('searchInput');
    var results = document.getElementById('searchResults');
    var close = document.getElementById('searchClose');

    function loadIndex() {
      if (searchIndex) return Promise.resolve();
      return fetch('/search-index.json')
        .then(function(r) { return r.json(); })
        .then(function(data) { searchIndex = data; });
    }

    function escapeRe(s) {
      return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    }

    function highlight(text, terms) {
      if (!terms.length) return text;
      var pattern = new RegExp('(' + terms.map(escapeRe).join('|') + ')', 'gi');
      return text.replace(pattern, '<mark>$1</mark>');
    }

    function getExcerpt(text, terms, len) {
      len = len || 140;
      var lower = text.toLowerCase();
      var best = -1;
      var bestScore = 0;
      for (var i = 0; i < text.length - 40; i += 20) {
        var window = lower.substring(i, i + len);
        var score = 0;
        for (var t = 0; t < terms.length; t++) {
          var idx = 0;
          while ((idx = window.indexOf(terms[t], idx)) !== -1) {
            score++;
            idx += terms[t].length;
          }
        }
        if (score > bestScore) {
          bestScore = score;
          best = i;
        }
      }
      if (best <= 0) return text.substring(0, len) + (text.length > len ? '\u2026' : '');
      var start = best;
      var end = Math.min(text.length, start + len);
      var excerpt = '';
      if (start > 0) excerpt += '\u2026';
      excerpt += text.substring(start, end);
      if (end < text.length) excerpt += '\u2026';
      return excerpt;
    }

    function search(query) {
      if (!searchIndex || !query.trim()) {
        results.innerHTML = '<p class="search-empty">Type to search across all pages.</p>';
        return;
      }
      var terms = query.toLowerCase().split(/\s+/).filter(function(t) { return t.length > 1; });
      if (!terms.length) {
        results.innerHTML = '<p class="search-empty">Type to search across all pages.</p>';
        return;
      }

      var scored = [];
      for (var i = 0; i < searchIndex.length; i++) {
        var item = searchIndex[i];
        var haystack = (item.title + ' ' + item.text).toLowerCase();
        var score = 0;
        for (var t = 0; t < terms.length; t++) {
          var idx = 0;
          while ((idx = haystack.indexOf(terms[t], idx)) !== -1) {
            score++;
            idx += terms[t].length;
          }
          if (item.title.toLowerCase().indexOf(terms[t]) !== -1) score += 3;
        }
        if (score > 0) {
          scored.push({ item: item, score: score });
        }
      }

      scored.sort(function(a, b) { return b.score - a.score; });
      var top = scored.slice(0, 12);

      if (!top.length) {
        results.innerHTML = '<p class="search-empty">No results for \u201c' + query + '\u201d</p>';
        return;
      }

      results.innerHTML = top.map(function(r) {
        var excerpt = getExcerpt(r.item.text, terms);
        var titleHl = highlight(r.item.title, terms);
        var excerptHl = highlight(excerpt, terms);
        var pageBadge = r.item.page !== r.item.title
          ? '<span class="search-result__page">' + r.item.page + '</span>' : '';
        return '<a href="' + r.item.url + '" class="search-result">'
          + '<strong>' + titleHl + '</strong>' + pageBadge
          + '<span class="search-result__excerpt">' + excerptHl + '</span></a>';
      }).join('');
    }

    toggle.addEventListener('click', function() {
      loadIndex().then(function() {
        overlay.classList.add('open');
        input.value = '';
        search('');
        setTimeout(function() { input.focus(); }, 100);
      });
    });

    close.addEventListener('click', function() { overlay.classList.remove('open'); });
    overlay.addEventListener('click', function(e) { if (e.target === overlay) overlay.classList.remove('open'); });
    document.addEventListener('keydown', function(e) {
      if (e.key === 'Escape') overlay.classList.remove('open');
      if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
        e.preventDefault();
        toggle.click();
      }
    });

    var debounceTimer;
    input.addEventListener('input', function() {
      clearTimeout(debounceTimer);
      debounceTimer = setTimeout(function() { search(input.value); }, 150);
    });
  })();
  </script>
</body>
</html>
