1<!DOCTYPE html><html lang="en-CA"> <head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>A free lunch-hour session for your members | Reclaim Your Time with AI</title><meta name="description" content="For co-working and business-centre managers in Ottawa-Gatineau: a free one-hour lunch-and-learn where each member hands off one of their own tasks to AI. Everyone learns to connect their AI agent to 1,500 tools at no cost, and leaves with a free book. English or French."><link rel="canonical" href="https://claudeacademy.ca/host"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate" hreflang="en-CA" href="https://claudeacademy.ca/host"><link rel="alternate" hreflang="fr-CA" href="https://claudeacademy.ca/fr/accueillir"><link rel="alternate" hreflang="x-default" href="https://claudeacademy.ca/host"><meta property="og:type" content="website"><meta property="og:site_name" content="Reclaim Your Time with AI"><meta property="og:title" content="A free lunch-hour session for your members | Reclaim Your Time with AI"><meta property="og:description" content="For co-working and business-centre managers in Ottawa-Gatineau: a free one-hour lunch-and-learn where each member hands off one of their own tasks to AI. Everyone learns to connect their AI agent to 1,500 tools at no cost, and leaves with a free book. English or French."><meta property="og:url" content="https://claudeacademy.ca/host"><meta property="og:locale" content="en_CA"><meta name="twitter:card" content="summary_large_image"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Oswald:wght@400;500;600&family=Inter:wght@400;500;600;700&family=Caveat:wght@500;700&display=swap" rel="stylesheet"><style>*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html{scroll-behavior:smooth;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media (prefers-reduced-motion: reduce){html{scroll-behavior:auto}*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}img,svg,video{display:block;max-width:100%}a{color:inherit}button,input,textarea,select{font:inherit;color:inherit}.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.skip-link{position:absolute;left:-9999px;top:0;z-index:999;padding:.7rem 1.1rem;background:#2e6fb5;color:#10151b;border-radius:0 0 10px;font-weight:600;text-decoration:none}.skip-link:focus{left:0}:focus-visible{outline:2px solid #a8d4f5;outline-offset:3px;border-radius:4px}.apply{display:flex;flex-direction:column;gap:2rem;max-width:620px}.apply fieldset{border:none;padding:0;margin:0;display:flex;flex-direction:column;gap:1.1rem}.apply legend{font-family:var(--mono);font-size:.78rem;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-2);padding:0 0 .9rem;border-bottom:1px solid var(--line);width:100%;display:flex;align-items:baseline;gap:.7rem}.apply .step-n{color:var(--hot)}.field{display:flex;flex-direction:column;gap:.42rem}.field-row{display:grid;grid-template-columns:1fr;gap:1.1rem}@media (min-width: 620px){.field-row{grid-template-columns:1.4fr 1fr}}.field label{font-size:.94rem;font-weight:500;line-height:1.45}.field input,.field select,.field textarea{font:inherit;font-size:1rem;color:var(--ink-1);background:var(--bg-2);border:1px solid var(--line);border-radius:10px;padding:.72rem .85rem;width:100%;transition:border-color .15s ease,box-shadow .15s ease}.field textarea{resize:vertical;line-height:1.6}.field input::placeholder,.field textarea::placeholder{color:var(--ink-3)}.field input:focus-visible,.field select:focus-visible,.field textarea:focus-visible{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px #7eb8e833}.field input[aria-invalid=true],.field select[aria-invalid=true],.field textarea[aria-invalid=true]{border-color:var(--red)}.hint{font-size:.82rem;color:var(--ink-3);margin:0;line-height:1.5}.apply .micro{margin-top:.2rem}.applied{max-width:620px}.applied h2{margin-top:.3rem}.applied .btn{margin-top:1rem}@media (prefers-reduced-motion: reduce){.field input,.field select,.field textarea{transition:none}}.nav-actions{display:flex;align-items:center;gap:.75rem}.lang-switch{font-size:.78rem;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-soft, #536072);text-decoration:none;padding:.35rem .6rem;border:1px solid var(--line, #d3dce6);border-radius:999px;white-space:nowrap;transition:color .15s ease,border-color .15s ease}.lang-switch:hover,.lang-switch:focus-visible{color:var(--ink, #0d1b2a);border-color:var(--ink-soft, #536072)}@media (max-width: 560px){.lang-switch{border-color:transparent;padding-left:.25rem;padding-right:.25rem}}.book-band{display:grid;grid-template-columns:240px 1fr;gap:clamp(2rem,5vw,4rem);align-items:center}.book-cover{display:block;line-height:0;border-radius:6px;transition:transform .2s ease,box-shadow .2s ease;box-shadow:0 24px 48px -18px #000000a6}.book-cover img{width:100%;height:auto;border-radius:6px}.book-cover:hover{transform:translateY(-4px) rotate(-.6deg);box-shadow:0 30px 56px -18px #000000bf}@media (max-width: 720px){.book-band{grid-template-columns:1fr}
1.book-cover{max-width:200px;margin:0 auto}} 2</style> 3<link rel="stylesheet" href="/_astro/book.CzdAyAfc.css"> 4<link rel="stylesheet" href="/_astro/accueillir.P4yuLrYB.css"> 5<style>.chooser-band[data-astro-cid-w4bfa2eq]{padding-top:1.5rem;padding-bottom:1.5rem}.chooser[data-astro-cid-w4bfa2eq]{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem;margin-top:.6rem}.chooser-card[data-astro-cid-w4bfa2eq]{background:var(--paper-warm);border:1px solid var(--border);border-radius:4px;padding:1.1rem 1.2rem;display:flex;flex-direction:column;gap:.45rem}.chooser-card[data-astro-cid-w4bfa2eq].current{border:2px solid var(--red-pen)}.chooser-card[data-astro-cid-w4bfa2eq] p[data-astro-cid-w4bfa2eq]{margin:0}.chooser-tag[data-astro-cid-w4bfa2eq]{font-weight:700;color:var(--red-pen);text-transform:uppercase;letter-spacing:.06em;font-size:.8rem;display:flex;gap:.5rem;align-items:center;flex-wrap:wrap}.chooser-here[data-astro-cid-w4bfa2eq]{background:var(--red-pen);color:var(--paper-warm);border-radius:3px;padding:.05rem .4rem;font-size:.7rem}.chooser-who[data-astro-cid-w4bfa2eq]{font-weight:700;color:var(--ink)}.chooser-what[data-astro-cid-w4bfa2eq]{font-size:.94rem;flex:1}.chooser-card[data-astro-cid-w4bfa2eq] .btn[data-astro-cid-w4bfa2eq]{align-self:flex-start;margin-top:.3rem}.chooser-more[data-astro-cid-w4bfa2eq]{font-size:.85rem}@media (max-width: 760px){.chooser[data-astro-cid-w4bfa2eq]{grid-template-columns:1fr}} 6</style> 7<link rel="stylesheet" href="/_astro/host.Cuu4_RFN.css"> 8<link rel="stylesheet" href="/_astro/host.DgV8SrVK.css"> 9<style>.wordmark-warm{font-family:var(--f-display);font-weight:900;font-size:1.15rem;color:var(--ink);text-decoration:none;letter-spacing:-.01em}.wordmark-warm em{font-style:italic;color:var(--red-pen)}.links-warm{display:flex;gap:1.5rem;font-family:var(--f-type);font-size:.76rem;letter-spacing:.05em;text-transform:uppercase}.links-warm a{color:var(--muted-fg);text-decoration:none}.links-warm a:hover{color:var(--red-pen)}.btn-sm{padding:.55rem 1rem;font-size:.85rem}.nav-actions{display:flex;align-items:center;gap:.75rem}.lang-switch-warm{font-family:var(--f-type);font-size:.72rem;letter-spacing:.05em;text-transform:uppercase;color:var(--muted-fg);text-decoration:none;border-bottom:1px dashed var(--border);white-space:nowrap}.lang-switch-warm:hover{color:var(--red-pen)}@media (max-width: 780px){.links-warm{display:none}} 10</style>
10<script type="module" src="/_astro/hoisted.CO0E25on.js"></script>
10</head> <body> <a class="skip-link" href="#main">Skip to content</a> <header class="nav"> <div class="nav-inner"> <a class="wordmark-warm" href="/">Claude <em>Academy</em></a> <nav class="links-warm" aria-label="Primary"> <a href="https://www.skool.com/claudeacademy">Community</a><a href="/#audit">AI Audit</a><a href="/skills">Skills Pack</a><a href="/workshops">Workshops</a><a href="/host">In person</a> </nav> <span class="nav-actions"> <a href="/fr/accueillir" class="lang-switch-warm" hreflang="fr-CA" lang="fr" aria-label="Voir ce site en français"> 11Français 12</a> <a href="https://www.skool.com/claudeacademy" class="btn btn-light btn-sm">Join free</a> </span> </div> </header> <main id="main"> <div class="host-page"> <!-- HERO --> <section class="hero pad"> <div class="wrap"> <div class="host-hero"> <div> <p class="kicker hot">For community managers · free · one hour · Ottawa-Gatineau</p> <h1>A free lunch-hour session <em>for your members.</em></h1> <p class="lede"> 13Thank you for taking a look. I'm Denis from Claude Academy. We help people and 14 companies reclaim their time using Claude skills, plugins and off-the-shelf AI tools. 15</p> <p> 16The offer is a free lunch-and-learn for your members. In one hour, each person takes 17 one of their own tasks and sees how to hand it off to AI, with the right workflow and 18 skills set up for it. 19</p> <p class="cta-row">
19 <a href="#request" class="btn btn-accent btn-lg">Request a lunch at my space</a> <a href="#hour" class="btn btn-light btn-lg">See the hour</a> </p> <p class="lang-badge"> <span class="lang-tag">EN</span><span class="lang-tag fr">FR</span> 20Runs in English, French, or the mix your members speak 21</p> </div> <div class="handoff" aria-label="Three tasks going from done by hand to handed off"> <p class="handoff-title">Over lunch, on the screen</p> <div class="job"> <div class="job-head"> <p class="job-name">The quote</p> <span class="job-state"><span class="from">By hand</span><span class="to">Handed off</span></span> </div> <p class="job-note">Written from their own price list while they watch.</p> <div class="job-bar"><i></i></div> </div><div class="job"> <div class="job-head"> <p class="job-name">The follow-up</p> <span class="job-state"><span class="from">By hand</span><span class="to">Handed off</span></span> </div> <p class="job-note">Sent the same day, not next week.</p> <div class="job-bar"><i></i></div> </div><div class="job"> <div class="job-head"> <p class="job-name">The inbox</p> <span class="job-state"><span class="from">By hand</span><span class="to">Handed off</span></span> </div> <p class="job-note">Sorted and drafted before the first coffee.</p> <div class="job-bar"><i></i></div> </div> </div> </div> </div> </section> <!-- WHICH ONE IS FOR YOU (Denis, 2026-09-25) --> <section class="pad chooser-band" aria-labelledby="chooser-title" data-astro-cid-w4bfa2eq> <div class="wrap" data-astro-cid-w4bfa2eq> <p class="kicker" id="chooser-title" data-astro-cid-w4bfa2eq>Which one is for you?</p> <div class="chooser" data-astro-cid-w4bfa2eq> <div class="chooser-card" data-astro-cid-w4bfa2eq> <p class="chooser-tag" data-astro-cid-w4bfa2eq> Online </p> <p class="chooser-who" data-astro-cid-w4bfa2eq>Just me.</p> <p class="chooser-what" data-astro-cid-w4bfa2eq>Every second Thursday, 1:00pm Eastern. Sixty minutes, on my screen.</p> <a href="https://cal.com/claudeacademy.ca/reclaim-your-hours-workshop" class="btn btn-light" data-astro-cid-w4bfa2eq>Save my online seat</a> <a href="/workshops" class="chooser-more" data-astro-cid-w4bfa2eq>Learn more</a> </div><div class="chooser-card current" data-astro-cid-w4bfa2eq> <p class="chooser-tag" data-astro-cid-w4bfa2eq> At your space <span class="chooser-here" data-astro-cid-w4bfa2eq>You are here</span> </p> <p class="chooser-who" data-astro-cid-w4bfa2eq>I run a co-working space or centre.</p> <p class="chooser-what" data-astro-cid-w4bfa2eq>A free lunch hour for your members. We set the date together.</p> <a href="/host#request" class="btn btn-accent" data-astro-cid-w4bfa2eq>Request a lunch at my space</a> </div><div class="chooser-card" data-astro-cid-w4bfa2eq> <p class="chooser-tag" data-astro-cid-w4bfa2eq> At your company </p> <p class="chooser-who" data-astro-cid-w4bfa2eq>My team, at our office.</p> <p class="chooser-what" data-astro-cid-w4bfa2eq>The same hour, at lunch, for one company.</p> <a href="/lunch-and-learn#request" class="btn btn-light" data-astro-cid-w4bfa2eq>Request a lunch at my office</a> <a href="/lunch-and-learn" class="chooser-more" data-astro-cid-w4bfa2eq>Learn more</a> </div> </div> </div> </section> <!-- GUARANTEE --> <section class="pad guarantee" id="guarantee"> <div class="wrap" style="max-width:980px"> <div class="guarantee-grid" data-reveal> <div class="g-badge" aria-hidden="true"> <div> <span class="g-num" data-count="1500">1,500</span> <span class="g-unit">tools · no cost</span> </div> </div> <div> <p class="kicker">Our guarantee</p> <p class="g-line"> 22Everyone who comes learns how to connect their AI agent, whichever one they use, to 23 1,500 tools at no cost. 24</p> <p>Nothing to buy, and it works with the agent they already have.</p> </div> </div> </div> </section> <!-- TRUST --> <section class="pad band-letter"> <div class="wrap"> <div class="tiles trust-tiles"> <div class="tile" data-reveal style="--i:0"> <p class="kicker">Free</p> <p>No fee to the space, no fee to members, no upsell from the front.</p> </div> <div class="tile" data-reveal style="--i:1"> <p class="kicker">60 minutes</p> <p>11:30 to 12:30, on the clock. Members are back at their desks by 12:31.</p> </div> <div class="tile" data-reveal style="--i:2"> <p class="kicker">Live</p> <p>Nothing pre-recorded. Real tasks get handed off on the screen while the room watches.</p> </div> <div class="tile" data-reveal style="--i:3"> <p class="kicker">A free book</p> <p>Everyone who comes leaves with a copy of <em>Reclaiming Your Hours with AI</em>.</p> </div> </div> </div> </section> <!-- WHAT MEMBERS GET --> <section class="pad"> <div class="wrap" style="max-width:820px" data-reveal> <p class="kicker">What your members walk out with</p> <h2>At least one task handed off, and the know-how to do the next.</h2> <ul class="checklist"> <li>How to hand off at least one task of their own, with the right workflow and skills set up for it</li> <li>How to connect their AI agent, whichever one they use, to 1,500 tools at no cost</li> <li>Their own number: roughly how many hours a week the task they hate is costing them<
24/li> <li>A free copy of the book that walks through the same steps</li> <li>If they want help with the rest, an AI assessment they can book that finds where the other hours are going</li> </ul> <p class="micro"> 25How many hours this gives back depends on the task and on the person; the point of the 26 two questions is that each person measures their own. 27</p> </div> </section> <!-- WHAT THE HOST GETS / COSTS --> <section class="pad band-letter"> <div class="wrap" style="max-width:920px"> <div data-reveal> <p class="kicker">What it costs you</p> <h2>Nothing. A room and a screen.</h2> <p class="lede"> 28You get a useful hour of programming for your members without planning it. I bring the 29 hour and the words for your newsletter. 30</p> </div> <div class="split parts"> <div class="part" data-reveal style="--i:0"> <h3>Your part</h3> <ul class="checklist"> <li>Pick a date that suits your space</li> <li>A room and a screen I can plug into</li> <li>Lunch for the room, if you would like to offer it</li> <li>Send the invitation to your members</li> </ul> </div> <div class="part mine" data-reveal style="--i:1"> <h3>My part</h3> <ul class="checklist"> <li>The whole hour, on time, in English or French</li> <li>The demo, built on the tasks your members bring</li> <li>Invitation text ready for your newsletter or member list</li> <li>A print flyer for the kitchen, the front desk, or the elevator</li> <li>A free copy of the book for everyone who comes</li> </ul> </div> </div> </div> </section> <!-- THE HOUR --> <section id="hour" class="pad"> <div class="wrap" style="max-width:820px"> <div data-reveal> <p class="kicker">What actually happens</p> <h2>Sixty minutes. Your members. Their own tasks handed off.</h2> </div> <ol class="steps run-of-show" data-reveal> <li class="step"> <p class="mono-num">11:30</p> <div> <h3>Lunch, and two questions</h3> <p>Everyone eats. Each person answers the two questions I ask every owner: what eats the most time that you wish it did not, and roughly how many hours a week it costs. Ten minutes, and the room has its own numbers before the demo starts.</p> </div> </li><li class="step"> <p class="mono-num">11:45</p> <div> <h3>Their own tasks, handed off live</h3> <p>Claude Desktop on the screen. Each person brings one task of their own, and I hand the ones the room names off to AI one at a time, on real examples, with the right workflow and skills set up for each. For a room full of owners that usually looks like a quote that writes itself from their own price list, the follow-up after a meeting, and the inbox sorted before the first coffee.</p> </div> </li><li class="step"> <p class="mono-num">12:10</p> <div> <h3>What it took</h3> <p>The setup behind what they just watched, shown rather than described, including how to connect their AI agent, whichever one they use, to 1,500 tools at no cost. Chapter 6 of the free book walks through the same setup.</p> </div> </li><li class="step"> <p class="mono-num">12:20</p> <div> <h3>Questions</h3> <p>In English or in French. The ones about their business, not about the technology.</p> </div> </li><li class="step"> <p class="mono-num">12:30</p> <div> <h3>Done, on time</h3> <p>Each person knows how to hand off at least one task, has their own number for the week, and leaves with the book. Anyone who wants help with the rest can book an AI assessment that finds where the other hours are going.</p> </div> </li> </ol> </div> </section> <!-- THE BOOK --> <section class="pad band-letter"> <div class="wrap" style="max-width:920px"> <div class="media-row" data-reveal> <a href="/book" class="media-img book-img"> <img src="/images/cover-front.png" alt="Cover of the book Reclaiming Your Hours with AI" width="1200" height="1800" loading="lazy" decoding="async"> </a> <div> <p class="kicker">Everyone in the room gets it free</p> <h2>Reclaiming Your Hours with AI</h2> <p> 31The working manual behind the hour: twenty-six chapters on the automations owners build 32 themselves, and the hours they get back. Chapter 6 walks through the same setup your 33 members watch on the screen. Every reader gets every future edition. 34</p> <p><a href="/book" class="btn btn-light">See the book</a></p> </div> </div> </div> </section> <!-- WHO --> <section class="pad"> <div class="wrap" style="max-width:920px"> <div class="media-row" data-reveal> <div class="media-img portrait"> <img src="/images/denis-hero.jpg" alt="Denis Laflamme" width="1726" height="1512" loading="lazy" decoding="async"> </div> <div> <p class="kicker">Who is running it</p> <h2>Denis Laflamme, based in Ottawa.</h2> <p> 35I have spent 30 years helping business owners save time with better technology, and I 36 am a registered Anthropic partner. An hour in your space is the shortest honest way to 37 show what that looks like on a real desk. Some of your members will want more 38 afterward. Most will just keep the hour they got back. Both are fine with me. 39</p> <p class="micro">
40Educational content. Results depend on your business and how you apply it. 41</p> </div> </div> </div> </section> <!-- REQUEST --> <section id="request" class="pad band-letter"> <div class="wrap" style="max-width:720px"> <div data-reveal> <p class="kicker hot">Request a lunch at your space</p> <h2>Tell me about your space, and pick a few dates.</h2> <p class="lede"> 42Takes about a minute. I reply within two business days with a date, the invitation text, 43 and the flyer. 44</p> </div> <div class="reg-card"> <form class="apply" id="ll-form" novalidate> <div class="field-row"> <div class="field"> <label for="ll-name">Your name</label> <input type="text" id="ll-name" name="name" autocomplete="name" maxlength="120" required> </div> <div class="field"> <label for="ll-email">Email</label> <input type="email" id="ll-email" name="email" placeholder="[email protected]" autocomplete="email" maxlength="200" required> </div> </div> <div class="field-row"> <div class="field"> <label for="ll-company">Name of the space</label> <input type="text" id="ll-company" name="company" autocomplete="organization" maxlength="200" required> </div> <div class="field"> <label for="ll-phone">Phone <span class="opt">(optional)</span></label> <input type="tel" id="ll-phone" name="phone" autocomplete="tel" maxlength="40"> </div> </div> <!-- Fixed industry value so Denis sees at a glance this came from a venue. --> <input type="hidden" name="industry" value="Co-working space or business centre"> <div class="field-row"> <div class="field"> <label for="ll-team">How many members might come?</label> <select id="ll-team" name="team_size"> <option value="">Choose one</option> <option>Under 15</option> <option>15 to 30</option> <option>31 to 50</option> <option>More than 50</option> <option>Not sure yet</option> </select> </div> <div class="field"> <label for="ll-language">Language in the room</label> <select id="ll-language" name="language"> <option>English</option> <option>Français</option> <option>Both</option> </select> </div> </div> <div class="field-row"> <div class="field"> <label for="ll-city">City</label> <input type="text" id="ll-city" name="city" placeholder="Ottawa, Gatineau, Kanataâ¦" maxlength="120"> </div> <div class="field"> <label for="ll-dates">A few dates that could work</label> <input type="text" id="ll-dates" name="preferred_dates" placeholder="Any Tuesday in October, 11:30" maxlength="500"> </div> </div> <div class="field"> <label for="ll-notes">Anything I should know <span class="opt">(optional)</span></label> <textarea id="ll-notes" name="notes" rows="3" maxlength="2000"></textarea> <p class="hint">The kind of businesses your members run, the room, whether lunch is on the house.</p> </div> <!-- Honeypot. Bots fill every field they find. --> <div class="hp-field" aria-hidden="true"> <label for="ll-website">Company website</label> <input type="text" id="ll-website" name="company_website" tabindex="-1" autocomplete="off"> </div> <button type="submit" class="btn btn-accent btn-lg" id="ll-btn">Send the request</button> <p class="form-msg" id="ll-msg" role="status" aria-live="polite"></p> <p class="micro"> 45Rather talk first? <a href="https://cal.com/claudeacademy.ca/claudeacademy-discovery">Book a free 15 minute call</a>, or write to 46<a href="mailto:[email protected]">[email protected]</a>. 47</p> </form> <div class="applied" id="ll-done" hidden> <div class="win"> <svg class="win-mark" viewBox="0 0 80 80" aria-hidden="true"> <circle cx="40" cy="40" r="36"></circle> <path d="M24 41 L35 52 L57 29"></path> </svg> <h2>Thank you. Your date request is in.</h2> <p> 48I reply within two business days with a date, the invitation text for your members, 49 and the flyer. 50</p> <div class="offer"> <p> <strong>As a thank-you, we'd like to offer you a free 30-minute AI assessment for 51 your co-working space's own operations.</strong> Bookings, member questions, 52 invoicing, onboarding: we find the admin AI can take off your plate. 53</p> <a href="https://cal.com/claudeacademy.ca/space-ai-assessment" class="btn btn-lg">Book your free assessment</a> </div> <p class="fine"> 54Nothing turned up? Check your promotions tab, or email [email protected]. 55</p> </div> </div> </div> </div> </section> <!-- FAQ --> <section class="pad"> <div class="wrap" style="max-width:820px" data-reveal> <p class="kicker">
55Questions managers ask</p> <h2>The short answers.</h2> <div class="faq"> <details> <summary>Is it a sales pitch?</summary> <p>Not from the front of the room. Some people will want more afterward: the free book, the community, an AI assessment that finds where the rest of their hours are going. That is their move to make, not mine, and it happens after the hour, not during it. Your members will not be put on a list for coming.</p> </details><details> <summary>What does the guarantee mean?</summary> <p>Nobody leaves with just a demo. Everyone who comes learns how to connect their AI agent, whichever one they use, to 1,500 tools at no cost. Nothing to buy, and it works with the agent they already have.</p> </details><details> <summary>What does it cost the space?</summary> <p>Nothing. A room and a screen I can plug into. Lunch is up to you: offer it, make it bring-your-own, or skip it. I bring the hour, the invitation text for your newsletter, a print flyer, and the books.</p> </details><details> <summary>How many members should come?</summary> <p>The session is kept small so the Q&A works. Tell me roughly how many you expect in the form, and if interest is bigger than one room, we can run a second date.</p> </details><details> <summary>Do members need to prepare or bring a laptop?</summary> <p>No. They watch the screen and answer two questions over lunch. If they already know the task that eats their week, they should bring it.</p> </details><details> <summary>Can it run in French?</summary> <p>Yes. English, French, or the mix your members already speak.</p> </details><details> <summary>Where do you go?</summary> <p>Ottawa and Gatineau, and the towns around them. Further out, ask; a morning drive is usually fine.</p> </details> </div> <p class="faq-foot micro"> 56Running an office rather than a shared space? The <a href="/lunch-and-learn">lunch and 57 learn for teams</a> is the same hour, built for one company. Questions: 58<a href="mailto:[email protected]">[email protected]</a>. 59</p> </div> </section> </div> </main> <footer class="site"> <div class="wrap foot-grid"> <div> <div class="foot-name">Reclaim Your Time with AI · Denis Laflamme</div> <div class="foot-name">Claude Academy, a product of The Agent Factory</div> <p class="foot-phone"> <a href="tel:+15485543214">(548) 554-3214</a> </p> </div> <nav class="foot-links" aria-label="Footer"> <a href="/">WEBSITE</a> <a href="https://www.skool.com/claudeacademy">COMMUNITY</a> <a href="/workshops">WORKSHOPS</a> <a href="/partners">PARTNERS</a> <a href="/audit">AI AUDIT</a> <a href="https://x.com/theagentfactory" rel="me">X</a> <a href="https://www.youtube.com/@myclaudeacademy" rel="me">YOUTUBE</a> </nav> </div> </footer> <!-- Vincent, the voice agent. --> <div class="va" data-va hidden data-astro-cid-je6adg2j> <!-- Collapsed: a quiet pill until someone wants to talk. --> <div class="va-collapsed" data-va-collapsed data-astro-cid-je6adg2j> <p class="va-toast" data-va-toast role="status" aria-live="polite" hidden data-astro-cid-je6adg2j></p> <button type="button" class="va-launch" data-va-start aria-label="Talk to Vincent" data-astro-cid-je6adg2j> <span class="va-launch-dot" aria-hidden="true" data-astro-cid-je6adg2j></span> <span data-astro-cid-je6adg2j>Talk to Vincent</span> </button> </div> <!-- Expanded: the live call panel. --> <div class="va-panel" data-va-panel role="dialog" aria-label="Call with Vincent" hidden data-astro-cid-je6adg2j> <!-- Vincent. Output amplitude only. --> <div class="va-orb" data-va-orb aria-hidden="true" data-astro-cid-je6adg2j> <span class="va-orb-halo" data-astro-cid-je6adg2j></span> <span class="va-orb-halo va-orb-halo-2" data-astro-cid-je6adg2j></span> <span class="va-orb-body" data-astro-cid-je6adg2j></span> <span class="va-orb-sheen" data-astro-cid-je6adg2j></span> </div> <!-- The visitor. A separate element in a cooler colour. --> <div class="va-listen" data-va-listen aria-hidden="true" data-astro-cid-je6adg2j> <span class="va-listen-bar" style="--w:.25;--i:0" data-astro-cid-je6adg2j></span> <span class="va-listen-bar" style="--w:.5;--i:1" data-astro-cid-je6adg2j></span> <span class="va-listen-bar" style="--w:.75;
59--i:2" data-astro-cid-je6adg2j></span> <span class="va-listen-bar" style="--w:1;--i:3" data-astro-cid-je6adg2j></span> <span class="va-listen-bar" style="--w:.75;--i:4" data-astro-cid-je6adg2j></span> <span class="va-listen-bar" style="--w:.5;--i:5" data-astro-cid-je6adg2j></span> <span class="va-listen-bar" style="--w:.25;--i:6" data-astro-cid-je6adg2j></span> </div> <p class="va-name" data-astro-cid-je6adg2j>Vincent</p> <p class="va-status" data-va-status role="status" aria-live="polite" data-astro-cid-je6adg2j>Listening, go ahead</p> <!-- 60 The capture form. Hidden until Vincent asks for it through the 61 collect_details client tool, so the call is never gated: a visitor clicks 62 and is talking in two seconds, and the ask lands only after he has been 63 useful. 64 65 Typed, never spoken. Denis's ruling 2026-09-09 stands: a misheard email 66 address becomes a no-show and a bad first impression. The visitor types 67 their own address here while Vincent keeps talking. 68 --> <!-- novalidate: the browser's own bubble fires before the submit handler 69 and suppresses our own message, so the field would silently reject 70 with no explanation. We validate in the handler instead, matching the 71 server's rules. --> <form class="va-capture" data-va-capture hidden novalidate data-astro-cid-je6adg2j> <p class="va-capture-lead" data-va-capture-lead data-astro-cid-je6adg2j>Where should I send it?</p> <label class="va-sr" for="va-first" data-astro-cid-je6adg2j>First name</label> <input class="va-field" id="va-first" data-va-first type="text" name="first_name" autocomplete="given-name" placeholder="First name" maxlength="120" required data-astro-cid-je6adg2j> <label class="va-sr" for="va-email" data-astro-cid-je6adg2j>Email</label> <input class="va-field" id="va-email" data-va-email type="email" name="email" autocomplete="email" placeholder="Email" maxlength="200" required data-astro-cid-je6adg2j> <label class="va-consent" data-astro-cid-je6adg2j> <input type="checkbox" data-va-consent data-astro-cid-je6adg2j> <span data-astro-cid-je6adg2j>Yes, email me Reclaiming Your Hours with AI, plus new editions and the occasional note about getting hours back. I can unsubscribe from any email, and Claude Academy will action it within 10 days.</span> </label> <button type="submit" class="va-send" data-va-send data-astro-cid-je6adg2j>Send it</button> <p class="va-capture-note" data-va-capture-note role="status" aria-live="polite" data-astro-cid-je6adg2j></p> </form> <button type="button" class="va-end" data-va-end data-astro-cid-je6adg2j>End call</button> </div> </div>
71<script>(function(){const SDK = "https://cdn.jsdelivr.net/npm/@elevenlabs/[email protected]/dist/lib.iife.js"; 72const destinations = {"call":"https://cal.com/claudeacademy.ca/claudeacademy-discovery","workshop":"https://cal.com/claudeacademy.ca/reclaim-your-hours-workshop","book":"/book","skills":"/skills","audit":"/audit","community":"https://www.skool.com/claudeacademy"}; 73const agentId = "agent_5301ka29j8qyepft4rp8x0w8jwxw"; 74const copy = {"idle":"Talk to Vincent","connecting":"Connecting...","listening":"Listening, go ahead","speaking":"Vincent is speaking","end":"End call","micDenied":"Microphone access was blocked. Allow it in your browser settings, then try again.","failed":"Could not start the call. Please try again in a moment.","closingNotice":"Still there? Wrapping up shortly.","endedIdle":"Call ended. Thanks for chatting."}; 75const idle = {"promptAfterMs":10000,"graceMs":8000,"closingPrompt":"The visitor has gone quiet. Ask, warmly and briefly, whether there is anything else you can help them with."}; 76const capture = {"lead":"Where should I send it?","firstLabel":"First name","emailLabel":"Email","consent":"Yes, email me Reclaiming Your Hours with AI, plus new editions and the occasional note about getting hours back. I can unsubscribe from any email, and Claude Academy will action it within 10 days.","send":"Send it","sending":"Sending...","done":"Sent. Check your inbox.","badEmail":"That email does not look right.","failed":"That did not go through. Try again in a moment."}; 77 78 (function () { 79 var root = document.querySelector('[data-va]'); 80 if (!root) return; 81 82 var elCollapsed = root.querySelector('[data-va-collapsed]'); 83 var elPanel = root.querySelector('[data-va-panel]'); 84 var elStart = root.querySelector('[data-va-start]'); 85 var elEnd = root.querySelector('[data-va-end]'); 86 var elOrb = root.querySelector('[data-va-orb]'); 87 var elListen = root.querySelector('[data-va-listen]'); 88 var elStatus = root.querySelector('[data-va-status]'); 89 var elToast = root.querySelector('[data-va-toast]'); 90 var elCapture = root.querySelector('[data-va-capture]'); 91 var elFirst = root.querySelector('[data-va-first]'); 92 var elEmail = root.querySelector('[data-va-email]'); 93 var elConsent = root.querySelector('[data-va-consent]'); 94 var elSend = root.querySelector('[data-va-send]'); 95 var elNote = root.querySelector('[data-va-capture-note]'); 96 var elCaptureLead = root.querySelector('[data-va-capture-lead]'); 97 98 // Tuning. Rising fast and falling slow is what makes a level meter look 99 // alive rather than jittery: syllables hit immediately, then the glow eases 100 // out instead of snapping to zero between every word. 101 var IDLE_LEVEL = 0.18; 102 var ATTACK = 0.35; 103 var DECAY = 0.09; 104 var IN_ATTACK = 0.42; 105 var IN_DECAY = 0.14; 106 // Slower than the amplitude on purpose: the shape should feel like it has 107 // mass and swings, rather than snapping around every frame. 108 var SHAPE_SMOOTH = 0.12; 109 var SILENCE = 0.02; 110 // getOutputByteFrequencyData is focused on 100 to 8000 Hz. The low third is 111 // roughly vowels and chest, the top third sibilance and consonants. 112 var BASS_END = 0.28; 113 var TREBLE_START = 0.55; 114 115 var conversation = null; 116 var starting = false; 117 var raf = null; 118 var reduced = false; 119 try { 120 reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches; 121 } catch (err) { 122 reduced = false; 123 } 124 125 var level = 0; 126 var inLevel = 0; 127 var stretch = 0; 128 var skew = 0; 129 var lastSound = 0; 130 var prompted = false; 131 var closingByUs = false; 132 133 // The widget only exists if the browser can actually run it. A visitor on 134 // a browser with no getUserMedia should see nothing rather than a button 135 // that cannot work. 136 if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) return; 137 root.hidden = false; 138 139 function toast(text, tone) { 140 if (!elToast) return; 141 if (!text) { 142 elToast.hidden = true; 143 elToast.textContent = ''; 144 return; 145 } 146 elToast.textContent = text; 147 if (tone) elToast.setAttribute('data-tone', tone); 148 else elToast.removeAttribute('data-tone'); 149 elToast.hidden = false;
150 } 151 152 function setStatus(text) { 153 if (elStatus) elStatus.textContent = text; 154 } 155 156 function showPanel(live) { 157 // Measure BEFORE hiding the pill: once it is hidden its box is 0x0. 158 // The panel pins to these coordinates so a call opens exactly where the 159 // visitor clicked, rather than flying to the bottom of the screen, and 160 // then stays put while they scroll. 161 if (live && elStart) { 162 var r = elStart.getBoundingClientRect(); 163 // Keep the panel on screen when the pill sits near an edge. The panel 164 // is wider (232) and taller (311) than the pill. 165 var x = Math.max(12, Math.min(r.left, window.innerWidth - 244)); 166 var y = Math.max(12, Math.min(r.top, window.innerHeight - 323)); 167 root.style.setProperty('--va-x', x + 'px'); 168 root.style.setProperty('--va-y', y + 'px'); 169 } 170 171 if (elCollapsed) elCollapsed.hidden = live; 172 if (elPanel) elPanel.hidden = !live; 173 174 // Inline placement pins the panel for the duration of a call, so 175 // scrolling the page does not carry an open conversation off screen. 176 // Harmless on the floating placement, which is already fixed. 177 if (live) { 178 root.setAttribute('data-live', ''); 179 } else { 180 root.removeAttribute('data-live'); 181 root.style.removeProperty('--va-x'); 182 root.style.removeProperty('--va-y'); 183 } 184 } 185 186 function bandLevel(buf, from, to) { 187 var a = Math.floor(buf.length * from); 188 var b = Math.max(a + 1, Math.floor(buf.length * to)); 189 var sum = 0; 190 for (var i = a; i < b; i++) sum += buf[i]; 191 return sum / (b - a) / 255; 192 } 193 194 function resetVisual() { 195 level = 0; 196 inLevel = 0; 197 stretch = 0; 198 skew = 0; 199 if (elOrb) { 200 elOrb.style.setProperty('--v', '0'); 201 elOrb.style.setProperty('--stretch', '0'); 202 elOrb.style.setProperty('--skew', '0'); 203 } 204 if (elListen) elListen.style.setProperty('--in', '0'); 205 } 206 207 // One loop owns both the animation and the idle watchdog, because both 208 // need the same per frame amplitude read. 209 function frame() { 210 if (!conversation) return; 211 212 var out = 0; 213 var inp = 0; 214 var spectrum = null; 215 try { 216 out = conversation.getOutputVolume(); 217 inp = conversation.getInputVolume(); 218 spectrum = conversation.getOutputByteFrequencyData(); 219 } catch (err) { 220 // The analyser can be torn down a frame before the loop stops. 221 } 222 223 // Vincent drives the orb. 224 var target = Math.min(1, Math.max(0, out)); 225 level += (target - level) * (target > level ? ATTACK : DECAY); 226 227 var stretchTarget = 0; 228 var skewTarget = 0; 229 if (spectrum && spectrum.length && target > SILENCE) { 230 var bass = bandLevel(spectrum, 0, BASS_END); 231 var treble = bandLevel(spectrum, TREBLE_START, 1); 232 var mid = bandLevel(spectrum, BASS_END, TREBLE_START); 233 stretchTarget = Math.max(-1, Math.min(1, (treble - bass) * 2.6)); 234 skewTarget = Math.max(-1, Math.min(1, (mid - treble) * 2.2)); 235 } 236 stretch += (stretchTarget - stretch) * SHAPE_SMOOTH; 237 skew += (skewTarget - skew) * SHAPE_SMOOTH; 238 239 if (elOrb) { 240 var shown = reduced ? IDLE_LEVEL : Math.max(IDLE_LEVEL, level); 241 elOrb.style.setProperty('--v', shown.toFixed(3)); 242 elOrb.style.setProperty('--stretch', reduced ? '0' : stretch.toFixed(3)); 243 elOrb.style.setProperty('--skew', reduced ? '0' : skew.toFixed(3)); 244 } 245 246 // The visitor drives the bars, and nothing else. 247 var inTarget = Math.min(1, Math.max(0, inp)); 248 inLevel += (inTarget - inLevel) * (inTarget > inLevel ? IN_ATTACK : IN_DECAY); 249 if (elListen) elListen.style.setProperty('--in', reduced ? '0' : inLevel.toFixed(3)); 250 251 // Idle hang up. 252 // 253 // Typing is silent, so a visitor filling in the capture form would trip 254 // the watchdog and get hung up on mid word. While the form is open and 255 // unsent, they are demonstrably still here: hold the clock. 256 var now = Date.now(); 257 if (elCapture && !elCapture.hidden && !captureDone) { 258 lastSound = now; 259 if (prompted) { 260 prompted = false;
261 setStatus(copy.listening); 262 } 263 } else if (out > SILENCE || inp > SILENCE) { 264 lastSound = now; 265 // Only the VISITOR speaking stands the hang up down. If Vincent's own 266 // voice counted, he would clear the timer just by asking the question. 267 if (prompted && inp > SILENCE) { 268 prompted = false; 269 setStatus(copy.listening); 270 } 271 } else { 272 var quietFor = now - lastSound; 273 if (!prompted && quietFor > idle.promptAfterMs) { 274 prompted = true; 275 setStatus(copy.closingNotice); 276 try { 277 conversation.sendContextualUpdate(idle.closingPrompt); 278 } catch (err) { 279 /* the session may already be closing */ 280 } 281 // Give him the floor to actually say it before the grace clock runs. 282 lastSound = now; 283 } else if (prompted && quietFor > idle.graceMs) { 284 closingByUs = true; 285 stop(); 286 return; 287 } 288 } 289 290 // Do not stamp over the closing notice, or the "sent, check your inbox" 291 // confirmation the visitor has just earned. 292 if (!prompted && !captureDone) { 293 setStatus(level > 0.04 ? copy.speaking : copy.listening); 294 } 295 296 raf = requestAnimationFrame(frame); 297 } 298 299 function loadSdk() { 300 if (window.ElevenLabsClient) return Promise.resolve(window.ElevenLabsClient); 301 return new Promise(function (resolve, reject) { 302 var s = document.createElement('script'); 303 s.src = SDK; 304 s.async = true; 305 s.onload = function () { 306 if (window.ElevenLabsClient) resolve(window.ElevenLabsClient); 307 else reject(new Error('SDK loaded but ElevenLabsClient is undefined')); 308 }; 309 s.onerror = function () { 310 reject(new Error('could not load the ElevenLabs SDK')); 311 }; 312 document.head.appendChild(s); 313 }); 314 } 315 316 // The one client tool Vincent has: open the page a visitor just asked for, 317 // in a new tab, while he keeps talking. 318 // 319 // Denis's ruling 2026-09-09: Vincent does NOT take a name and email by 320 // voice and book on the visitor's behalf. A misheard email address becomes 321 // a no-show and a bad first impression, and the booking page already does 322 // that job properly. So the agent hands the visitor to the real page and 323 // the human types their own address. 324 // Vincent's second tool: raise the capture form. He calls this once he has 325 // been useful and the visitor wants something sent, NOT as a greeting. 326 // 327 // It returns immediately rather than waiting for the visitor to type, 328 // because a tool call blocks the agent: waiting here would leave Vincent 329 // silent and the call feeling dead while they fill in two fields. 330 function collectDetails(args) { 331 if (!elCapture) return 'The form is not available on this page.'; 332 if (captureDone) { 333 return 'They have already sent their details. Do not ask again; carry on.'; 334 } 335 336 var reason = String((args && args.reason) || '').trim(); 337 if (reason && elCaptureLead) elCaptureLead.textContent = reason.slice(0, 120); 338 339 elCapture.hidden = false; 340 note(null);
341 try { 342 elFirst.focus(); 343 } catch (err) { 344 /* focus is a nicety, never a failure */ 345 } 346 347 return ( 348 'The form is open on their screen with a first name field, an email ' + 349 'field and a send button. Tell them briefly to pop their name and ' + 350 'email in, then keep the conversation going. Do NOT ask them to say ' + 351 'the address out loud, and do not wait in silence.' 352 ); 353 } 354 355 function note(text, tone) { 356 if (!elNote) return; 357 elNote.textContent = text || ''; 358 if (tone) elNote.setAttribute('data-tone', tone); 359 else elNote.removeAttribute('data-tone'); 360 } 361 362 var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/; 363 var captureDone = false; 364 var sending = false; 365 // The last page Vincent opened. When he then offers to email the link, this 366 // is what decides WHICH email goes out, so a booking link request does not 367 // come back as a book. 368 var lastPage = null; 369 370 async function submitCapture(ev) { 371 if (ev) ev.preventDefault(); 372 if (sending || captureDone) return; 373 374 var first = (elFirst.value || '').trim(); 375 var email = (elEmail.value || '').trim(); 376 377 elFirst.removeAttribute('aria-invalid'); 378 elEmail.removeAttribute('aria-invalid'); 379 380 if (!first) { 381 elFirst.setAttribute('aria-invalid', 'true'); 382 elFirst.focus(); 383 return; 384 } 385 if (!EMAIL_RE.test(email)) { 386 elEmail.setAttribute('aria-invalid', 'true'); 387 elEmail.focus(); 388 note(capture.badEmail, 'error'); 389 return; 390 } 391 392 sending = true; 393 elSend.disabled = true; 394 note(capture.sending); 395 396 try { 397 // Reuses the book gate, which already validates, records the exact 398 // consent wording with a timestamp and IP, and delivers the book. 399 // `source: 'vincent'` is what separates these leads in the table. 400 var r = await fetch('/api/book-signup', { 401 method: 'POST', 402 headers: { 'Content-Type': 'application/json' }, 403 body: JSON.stringify({ 404 name: first, 405 email: email, 406 consent: !!(elConsent && elConsent.checked), 407 source: 'vincent', 408 // Null unless Vincent opened a page first, in which case the server 409 // sends that link instead of the book. 410 page: lastPage, 411 }), 412 }); 413 var data = await r.json().catch(function () { 414 return {}; 415 }); 416 417 if (!r.ok) { 418 sending = false; 419 elSend.disabled = false; 420 note(data.error || capture.failed, 'error'); 421 return; 422 } 423 424 captureDone = true; 425 sending = false; 426 elCapture.hidden = true; 427 setStatus(capture.done); 428 429 // Tell Vincent it landed, so he can acknowledge it in his own voice 430 // instead of the visitor wondering whether anything happened.
431 try { 432 var sent = 433 lastPage && lastPage !== 'book' ? 'the link they asked for' : 'the book'; 434 conversation.sendContextualUpdate( 435 'They just sent their details: first name ' + 436 first + 437 '. You have emailed them ' + 438 sent + 439 '. Confirm in ONE short sentence, six words if you can, then carry on.', 440 ); 441 } catch (err) { 442 /* the session may have ended while the request was in flight */ 443 } 444 } catch (err) { 445 sending = false; 446 elSend.disabled = false; 447 note(capture.failed, 'error'); 448 } 449 } 450 451 function openDestination(args) { 452 var key = String((args && args.destination) || '') 453 .toLowerCase() 454 .trim(); 455 var url = destinations[key]; 456 457 if (!url) { 458 // Tell the model, not the visitor. Vincent then says where to look 459 // instead of pretending something opened. 460 return ( 461 'No page matched "' + 462 key + 463 '". Tell the visitor which page to look for instead of claiming you opened it.' 464 ); 465 } 466 467 var win = window.open(url, '_blank', 'noopener,noreferrer'); 468 if (!win) { 469 return 'The browser blocked the popup. Tell the visitor to look for the link on the page instead.'; 470 } 471 // Remember it, so an offer to email "that link" sends THIS page. 472 lastPage = key; 473 return 'Opened ' + url + ' in a new tab. Confirm briefly that it is open, and stop talking so they can use it.'; 474 } 475 476 async function start() { 477 if (starting || conversation) return; 478 starting = true; 479 if (elStart) elStart.disabled = true; 480 toast(copy.connecting); 481 482 // The microphone, from inside the user gesture. Browsers only grant 483 // access on one. 484 try { 485 await navigator.mediaDevices.getUserMedia({ audio: true }); 486 } catch (err) { 487 starting = false; 488 if (elStart) elStart.disabled = false; 489 toast(copy.micDenied, 'error'); 490 return; 491 } 492 493 var Sdk; 494 try { 495 Sdk = await loadSdk(); 496 } catch (err) { 497 starting = false; 498 if (elStart) elStart.disabled = false; 499 toast(copy.failed, 'error'); 500 return; 501 } 502 503 try { 504 // Public session: the agent has auth disabled, so there is no token to 505 // mint and no server round trip. See the note at the top of this file. 506 conversation = await Sdk.Conversation.startSession({ 507 agentId: agentId, 508 connectionType: 'webrtc', 509 clientTools: { 510 open_page: openDestination, 511 collect_details: collectDetails, 512 }, 513 onDisconnect: function () { 514 teardown(); 515 }, 516 onError: function (message) { 517 teardown(); 518 toast(copy.failed, 'error'); 519 }, 520 }); 521 } catch (err) { 522 starting = false; 523 conversation = null; 524 if (elStart) elStart.disabled = false; 525 toast(copy.failed, 'error'); 526 return; 527 } 528 529 starting = false; 530 closingByUs = false; 531 prompted = false; 532 lastSound = Date.now(); 533 534 // Page context. A page that has something Vincent should know before 535 // he speaks (the calculator hands him the visitor's live numbers) 536 // defines window.vaPageContext as a function returning one string. 537 // Every other page defines nothing and this is a no-op. 538 try { 539 if (typeof window.vaPageContext === 'function') { 540 var pageCtx = window.vaPageContext(); 541 if (pageCtx) conversation.sendContextualUpdate(String(pageCtx)); 542 } 543 } catch (err) { 544 /* context is a nice to have; never let it break the call */ 545 } 546 resetVisual(); 547 toast(null); 548 setStatus(copy.listening); 549 showPanel(true); 550 raf = requestAnimationFrame(frame); 551 } 552 553 function teardown() { 554 if (raf) cancelAnimationFrame(raf); 555 raf = null; 556 conversation = null; 557 starting = false; 558 prompted = false;
559 resetVisual(); 560 showPanel(false); 561 // Reset the form between calls, or the next visitor on this page opens 562 // the panel to the previous person's name and email sitting in it. 563 if (elCapture) { 564 elCapture.hidden = true; 565 try { 566 elCapture.reset(); 567 } catch (err) { 568 /* not fatal */ 569 } 570 elFirst && elFirst.removeAttribute('aria-invalid'); 571 elEmail && elEmail.removeAttribute('aria-invalid'); 572 } 573 if (elSend) elSend.disabled = false; 574 note(null); 575 captureDone = false; 576 sending = false; 577 if (elCaptureLead) elCaptureLead.textContent = capture.lead; 578 if (elStart) elStart.disabled = false; 579 // A hang up we initiated on idle should explain itself, so it never 580 // looks like the call simply dropped. 581 if (closingByUs) { 582 toast(copy.endedIdle); 583 window.setTimeout(function () { 584 toast(null); 585 }, 4000); 586 closingByUs = false; 587 } 588 } 589 590 function stop() { 591 var active = conversation; 592 // Clear our handle first, so the loop and any late callback stop 593 // touching a session that is on its way out. 594 if (raf) cancelAnimationFrame(raf); 595 raf = null; 596 conversation = null; 597 if (active) { 598 try { 599 Promise.resolve(active.endSession()).catch(function () {}); 600 } catch (err) { 601 /* already closed */ 602 } 603 } 604 teardown(); 605 } 606 607 if (elCapture) elCapture.addEventListener('submit', submitCapture); 608 if (elStart) elStart.addEventListener('click', start); 609 if (elEnd) 610 elEnd.addEventListener('click', function () { 611 closingByUs = false; 612 stop(); 613 }); 614 615 // Never leave a live microphone open behind a navigation. 616 window.addEventListener('pagehide', function () { 617 if (conversation) { 618 try { 619 conversation.endSession(); 620 } catch (err) { 621 /* already closed */ 622 } 623 } 624 }); 625 })(); 626})();</script>
626 <div class="bp" data-book-popup data-locale="en" hidden data-astro-cid-4ifyvisz> <div class="bp-backdrop" data-bp-close data-astro-cid-4ifyvisz></div> <div class="bp-panel" role="dialog" aria-modal="true" aria-labelledby="bp-title" aria-describedby="bp-body" data-astro-cid-4ifyvisz> <button type="button" class="bp-x" data-bp-close aria-label="Close" data-astro-cid-4ifyvisz> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true" data-astro-cid-4ifyvisz><path d="M6 6l12 12M18 6L6 18" data-astro-cid-4ifyvisz></path></svg> </button> <div class="bp-cover" data-astro-cid-4ifyvisz> <img src="/images/cover-front.png" alt="Front cover of Reclaiming Your Hours with AI" width="1200" height="1800" loading="lazy" decoding="async" data-astro-cid-4ifyvisz> </div> <div class="bp-copy" data-astro-cid-4ifyvisz> <p class="bp-kicker" data-astro-cid-4ifyvisz>The free book</p> <h2 class="bp-title" id="bp-title" data-astro-cid-4ifyvisz>One task off your plate, per chapter.</h2> <p class="bp-body" id="bp-body" data-astro-cid-4ifyvisz>Reclaiming Your Hours with AI: twenty-six chapters, each one takes a repeating task off your week and prices it in the hours you get back. The first build takes one evening. Free, and every future edition arrives at the same address.</p> <form class="bp-form" novalidate data-astro-cid-4ifyvisz> <div class="bp-row" data-astro-cid-4ifyvisz> <label class="bp-sr" for="bp-name" data-astro-cid-4ifyvisz>First name</label> <input id="bp-name" name="name" type="text" autocomplete="given-name" placeholder="First name" required data-astro-cid-4ifyvisz> <label class="bp-sr" for="bp-email" data-astro-cid-4ifyvisz>Email</label> <input id="bp-email" name="email" type="email" autocomplete="email" inputmode="email" placeholder="Email" required data-astro-cid-4ifyvisz> </div> <label class="bp-consent" data-astro-cid-4ifyvisz> <input type="checkbox" name="consent" data-astro-cid-4ifyvisz> <span data-astro-cid-4ifyvisz>Yes, email me Reclaiming Your Hours with AI, plus new editions and the occasional note about getting hours back. I can unsubscribe from any email, and Claude Academy will action it within 10 days.</span> </label> <div class="bp-actions" data-astro-cid-4ifyvisz> <button type="submit" class="bp-send" data-astro-cid-4ifyvisz>Send me the book</button> <button type="button" class="bp-later" data-bp-close data-astro-cid-4ifyvisz>Not now</button> </div> <p class="bp-msg" aria-live="polite" data-astro-cid-4ifyvisz></p> </form> <p class="bp-done" hidden data-astro-cid-4ifyvisz>Sent. Check your inbox in the next minute.</p> </div> </div> </div> </body></html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.