// Service detail — one template, data-driven per slug

const { useParams } = ReactRouterDOM;

const serviceDetails = {
  'lead-response-followup': {
    eyebrow: 'Lead Response & Follow-Up',
    h1: 'Reply in under a minute. Then stay in front of them until they buy.',
    subhead: 'The two reasons most leads die: response was too slow on the first touch, or there was no second touch. We fix both at once \u2014 instant first reply, then a sequence that keeps showing up until they\u2019re ready.',
    photo: 'assets/photos/painting-mission-vines.png',
    why: {
      label: 'Why this matters',
      stats: [
        ['21\u00d7', 'more likely to qualify a lead if you respond in under 5 minutes vs. 30.', 'InsideSales.com / MIT'],
        ['78%', 'of customers buy from the company that responds first.', 'Lead Connect'],
        ['80%', 'of sales require 5+ follow-up touches after the first conversation.', 'Marketing Donut'],
      ],
      paragraph: 'Most leads aren\u2019t lost on price or pitch. They\u2019re lost in the gap between when they reach out and when you get back to them \u2014 and in the silence that follows after the first conversation. The fix isn\u2019t a new sales tactic. It\u2019s making sure the lead never feels forgotten.',
    },
    bleed: [
      'A lead came in Monday at 2 p.m. You meant to call back that afternoon. A job ran long. Tuesday morning you opened your phone to a text: "Going with someone else, thanks anyway." That was a $4,000 job. Or a $14,000 one. You didn\u2019t lose it on price or quality. You lost it because you were 16 hours late on what should have been a 5-minute reply.',
      'And the leads that did get a first call? Half of them needed a 4th, 5th, or 6th touch before saying yes \u2014 and you didn\u2019t have time to keep showing up. You weren\u2019t bad at sales. You were the only person doing it, and the math stops working eventually.',
    ],
    steps: [
      'A new form submission, phone call, or inquiry lands in your system.',
      'Within 60 seconds, a personal SMS and email go out using the lead\u2019s name and exactly what they asked about. Your team gets pinged by SMS or email with the full lead details and the caller\u2019s number as a tap-to-call link.',
      'The lead is automatically added to a multi-step nurture sequence \u2014 value-first message on day 1, check-in on day 4, objection-handling on day 7, clean break-up on day 14.',
      'Every touch is personalized using what the lead actually told you when they came in. No generic "just checking in."',
      'The whole sequence stops the moment they reply, book a call, or convert. Nothing keeps firing at someone already in.',
      'Every conversation lives in one place \u2014 the full thread, every touch, every reply, in your GHL inbox. Nothing to type, nothing to remember.',
    ],
    outcomes: [
      ['clock', 'Reply time in seconds, not days', 'The gap that loses you deals closes for good.'],
      ['trending-up', 'Closed deals you would have lost', 'Touch #5 finally gets sent.'],
      ['check', 'Zero mental load on follow-up', 'You stop trying to remember who you owe a reply.'],
    ],
    math: [
      'A small services business pulling 60 leads a month at a $4,000 average ticket and an 18% close rate is leaving close-rate points on the table on both ends \u2014 slow first reply and abandoned follow-up. Combined, the lift on close rate is routinely 15\u201325 points.',
      'On those numbers, that\u2019s $36,000 to $60,000 in monthly revenue from leads you\u2019re already paying to generate. Build is one-time. Monthly run cost is less than a tank of gas.',
    ],
    smsCaveat: true,
    // Paste a Loom share/embed URL here (e.g. 'https://www.loom.com/embed/abc123...'). Empty string = placeholder card.
    loomUrl: '',
  },
  'missed-call-textback': {
    eyebrow: 'Missed Call Text-Back',
    h1: 'Every missed call becomes a 30-second text. The lead never goes cold.',
    subhead: '62% of calls to small businesses go unanswered during the day. 85% of those callers never call back \u2014 they call the next business on the list. The simplest, highest-ROI automation we build, and the one most owners haven\u2019t even thought of.',
    photo: 'assets/photos/painting-beach-dunes.png',
    why: {
      label: 'Why this matters',
      stats: [
        ['62%', 'of phone calls to small businesses go unanswered during business hours. After hours, it\u2019s nearly 100%.', 'Ruby Receptionists / Numa'],
        ['85%', 'of unanswered callers never call back. They call your competitor instead.', 'BrightLocal / Zipwhip'],
        ['$1,200', 'average lifetime value of a single missed call for service businesses. Multiply that by 5 misses a week.', 'Invoca / industry avg'],
      ],
      paragraph: 'You\u2019re spending money every month to make that phone ring \u2014 ads, referrals, your Google listing, word of mouth. When it rings and nobody picks up, that money doesn\u2019t pause. It just transfers to whoever the caller dials next. A missed call isn\u2019t a missed opportunity. It\u2019s a paid opportunity handed directly to your competition. The text-back turns a dead end into a live conversation \u2014 automatically, in under 30 seconds, without you touching your phone.',
    },
    bleed: [
      'It\u2019s a Tuesday. You\u2019re elbow-deep in a job, on a ladder, in the truck, with a customer in front of you. The phone rings, it goes to voicemail, you forget. By the time you check the missed-calls list at the end of the day, that lead has already booked the next company that picked up.',
      'Five missed calls a week, $800 average ticket: that\u2019s $48,000 a year sitting in your call log. Not because they didn\u2019t want you. Because they couldn\u2019t reach you in the 90 seconds before they moved on.',
    ],
    steps: [
      'A call comes in. You miss it \u2014 voicemail, ring-out, busy, doesn\u2019t matter.',
      'Within 30 seconds, the caller gets a personal text: "Sorry I missed you \u2014 what\u2019s going on?" Warm, human, opens a conversation instead of a dead end.',
      'They text back. An AI conversation handles qualification \u2014 what they need, where they\u2019re located, how urgent, who they are.',
      'The conversation gets packaged into a one-paragraph brief and routed by urgency. Emergency: SMS straight to the owner\u2019s phone so a callback can happen inside an hour. Routine: the brief lands in your email and your GHL inbox with the next action.',
      'Anyone who calls more than once doesn\u2019t get blasted with three texts. Dedup keeps it clean.',
      'Everything logs \u2014 who called, what they needed, what happened next, whether it converted.',
    ],
    outcomes: [
      ['phone-incoming', 'Every miss becomes a conversation', 'Ringing through to nobody stops costing you customers.'],
      ['clock', '30 seconds, not 30 minutes', 'Caught while they\u2019re still holding the phone.'],
      ['check', 'No more wondering who called', 'Everything captured, qualified, and routed automatically.'],
    ],
    math: [
      'Five missed calls a week, $800 average ticket, 25% close rate on captured-back leads \u2014 that\u2019s roughly $4,000 a month, $48,000 a year, in revenue you\u2019re currently leaving in the call log.',
      'Build is one-time. Monthly run cost is under $50. The math gets worse for every business that doesn\u2019t have this. Not better.',
    ],
    smsCaveat: true,
    loomUrl: '',
  },
  'reviews-reputation': {
    eyebrow: 'Reviews & Reputation',
    h1: 'More 5-star reviews. Faster responses. Without ever opening Google.',
    subhead: '98% of consumers read reviews before calling a local business. 3.3 stars is the floor most people won\u2019t even consider. Your reputation is your top-of-funnel \u2014 and most owners are running it by hand.',
    photo: 'assets/photos/painting-cliffs-sunset.png',
    why: {
      label: 'Why this matters',
      stats: [
        ['98%', 'of consumers read online reviews for local businesses before reaching out.', 'BrightLocal 2024'],
        ['3.3\u2605', 'is the minimum rating consumers will consider. Below that, you\u2019re invisible \u2014 no matter how good your work is.', 'BrightLocal'],
        ['50%', 'more revenue for businesses that respond to reviews vs. those that don\u2019t.', 'Harvard Business Review / Womply'],
      ],
      paragraph: 'Your reputation online is your storefront now. Before anyone calls you, they\u2019ve already read what other people said about you. The problem isn\u2019t that you\u2019re getting bad reviews \u2014 it\u2019s that you\u2019re not getting enough good ones, and the ones you do get sit there with no response. An unanswered review tells the next customer you\u2019re too busy to care, even if the reason you\u2019re busy is that you\u2019re doing great work.',
    },
    bleed: [
      'You finished the job. Customer was thrilled \u2014 told you to your face. But you didn\u2019t ask for a review because it felt awkward, or you meant to send a link later and forgot. Two months go by. You check Google: 4.1 stars with 23 reviews. The guy down the road has 4.7 with 140. Same quality of work. He just has a system asking for reviews and you don\u2019t.',
      'Meanwhile the one customer who had a complaint? Their 2-star review has been sitting on your profile for three weeks unanswered, doing more damage every time someone reads it. You meant to write a thoughtful reply. You haven\u2019t had the time.',
    ],
    steps: [
      'Job hits Complete \u2014 drag the card in GHL, or text DONE [name] from the truck. Either way works.',
      'A 2-touch review request goes out \u2014 personal SMS first from your name with a one-tap link straight to the Google review box. If they don\u2019t review within 48 hours, an email follow-up fires automatically.',
      'n8n checks your Google Business Profile every morning. New reviews get pulled, drafted, and queued.',
      'AI drafts the response. 4\u20135 stars: auto-posts a personal, on-brand reply. 3 stars: drafts for your one-tap approval. 1\u20132 stars: urgent SMS first thing in the morning with a draft, never auto-posts. You respond inside an hour of seeing it, not a week.',
      'No emojis. No exclamation points. No "We appreciate your feedback." Reads like you wrote it because the prompt is built that way.',
      'Monday morning summary lands in your inbox: new reviews, current rating, response rate, anything that needs attention.',
    ],
    outcomes: [
      ['star', 'Star count climbs on its own', 'Every happy customer becomes a review.'],
      ['message-square', 'Negative reviews handled fast', 'Within the hour, with a real reply, drafted and waiting.'],
      ['trending-up', 'More leads from the listing', 'Higher rating = more click-throughs from search.'],
    ],
    math: [
      'Going from a 3.5 to a 4.5 star rating typically lifts click-throughs from Google by ~25%. For a business getting 80 leads a month from search, that\u2019s 20 additional leads. At a $2,000 average ticket and 20% close rate, that\u2019s $8,000/month in revenue directly attributable to your review profile.',
      'And the negative review you used to take three weeks to answer now gets a thoughtful reply in under an hour. The damage stops compounding.',
    ],
    smsCaveat: true,
    loomUrl: '',
  },
  'internal-reporting': {
    eyebrow: 'Internal Reporting',
    h1: 'One daily summary instead of opening 5 tools every morning.',
    subhead: 'Most owners spend 5+ hours a week pulling numbers from different dashboards. The tools were meant to save time. They\u2019re costing it.',
    photo: 'assets/photos/painting-sea-stack.png',
    why: {
      label: 'Why this matters',
      stats: [
        ['5+ hrs', 'per week the average owner spends checking dashboards and pulling numbers manually.', 'Multiple industry surveys'],
        ['$39,000', 'in annual opportunity cost at a $150/hr owner-equivalent rate. That\u2019s your time, not an employee\u2019s.', 'Calculated'],
        ['82%', 'of business failures trace back to cash flow problems \u2014 often caught weeks too late because nobody was watching the right number.', 'U.S. Bank study'],
      ],
      paragraph: 'The problem isn\u2019t that you don\u2019t have data. You have too much of it, scattered across too many tools that don\u2019t talk to each other. So you end up being the human bridge \u2014 logging in, pulling numbers, doing the math in your head, and hoping you catch the thing that\u2019s about to go wrong before it does.',
    },
    bleed: [
      'You start with the CRM to check new leads, then the booking calendar, then QuickBooks for what came in overnight. By the time you\u2019ve cycled through the project board for what\u2019s stuck and your inbox for what\u2019s on fire, an hour is gone and you haven\u2019t started the day\u2019s actual work.',
      'None of those tools talk to each other. None of them flag the deal that\u2019s been stuck in "negotiation" for 19 days. None of them tell you that conversion is down 12% week over week until you go looking. The numbers are all there. They\u2019re just scattered, and you\u2019re the human bridge between them.',
    ],
    steps: [
      'A scheduled trigger fires at whatever time you want \u2014 6 a.m., 9 a.m., end of day on Fridays.',
      'The system pulls live data from your tools \u2014 GHL, QuickBooks, Stripe, Google Sheets, and most tools with an API. We audit your stack on the discovery call to confirm what\u2019s pullable before anything gets built.',
      'The numbers get aggregated and checked for anything outside normal range. Comparisons to last week and last month start working immediately for the tools we can pull history from, and inside about two weeks for everything else.',
      'Anomalies get flagged automatically \u2014 the deal stuck for 3 weeks, the revenue dip, the conversion drop.',
      'A clean 5-line summary lands in your email before you sit down at the desk.',
    ],
    outcomes: [
      ['clock', '5+ hours back every week', 'Spent on actual work instead of dashboard hopping.'],
      ['trending-up', 'Anomalies caught early', 'The stuck deal becomes a conversation, not a lost contract.'],
      ['check', 'One number to read, not 5 to find', 'The morning starts with clarity instead of tabs.'],
    ],
    math: [
      'At an owner-equivalent rate of $150/hr, 5 hours a week of dashboard time is roughly $1,000 a month \u2014 $12,000 a year \u2014 of your highest-value time being spent on the lowest-value task in the business.',
      'That\u2019s before counting the deals quietly stuck in stages nobody is watching. Build is one-time. The summary runs forever after that.',
    ],
    loomUrl: '',
  },
  'document-processing': {
    eyebrow: 'Document Processing',
    h1: 'Invoices send themselves out. Vendor invoices read themselves in.',
    subhead: 'Both ends of the loop, both eating hours every week. Outbound invoices go out by SMS in 30 seconds. Inbound vendor invoices land in your books on their own. You stop opening QuickBooks.',
    photo: 'assets/photos/painting-vineyard-rows.png',
    why: {
      label: 'Why this matters',
      stats: [
        ['$15\u2013$40', 'per inbound invoice when you\u2019re processing by hand. That\u2019s the loaded cost of the time, the errors, and the re-work.', 'IOFM / Stampli'],
        ['60+ hrs', 'per month most small offices waste on AR/AP data entry between sending invoices out and entering them in.', 'Industry surveys'],
        ['1\u20134%', 'error rate in manual data entry. Small enough to ignore until tax season, when it isn\u2019t.', 'Multiple studies'],
      ],
      paragraph: 'Invoice work doesn\u2019t feel expensive until you add it up. Twenty minutes to send one out. Fifteen minutes to enter one in. An hour every night after the kids are in bed. It\u2019s not hard work \u2014 that\u2019s what makes it worse. It\u2019s just volume, and it\u2019s eating the time you could spend on the parts of the business that actually grow revenue.',
    },
    bleed: [
      'Tuesday night, 10 p.m. Kids are asleep. You\u2019re at the kitchen table with a stack of vendor invoices, opening QuickBooks for the third time today. Vendor name, amount, date, line items. Type and tab. Type and tab. 47 to go. Same five vendors you\u2019ve been using for years. Same data. You\u2019ve typed the same vendor address 300 times this year.',
      'And in the other direction: a customer asks for an invoice on Monday. You finish the job, get back to the truck, mean to send it that night. Wednesday it\u2019s still on your list. Friday you finally open QuickBooks, hunt for the customer, fill out the line items, hit send. Three days late. The bleed runs both ways \u2014 the invoices you owe people, and the ones people owe you.',
    ],
    steps: [
      'Outbound: you text a dedicated number from anywhere \u2014 "send invoice to John Smith, logo job, $500." A short bot conversation fills any missing pieces (email, due date) and asks you to confirm. Reply YES and it fires.',
      'The system creates the customer in QuickBooks if they don\u2019t exist, builds the invoice, and sends it via QB\u2019s native email with the payment link. You get a confirmation text. You never opened QuickBooks.',
      'Reminders fire automatically at 7, 14, and 21 days if the invoice goes unpaid. Payment lands \u2192 status flips to paid \u2192 you get a "$500 paid by John Smith" SMS the moment it clears.',
      'Inbound: vendor invoices arrive in a dedicated inbox. The system reads each PDF or image and extracts vendor + amount + line items into clean structured data. Anything blurry, partial, or uncertain goes to the review queue instead of guessing.',
      'Clean entries post directly into the right QuickBooks account. The system never auto-posts anything that hits a hard rule \u2014 invoices over your set ceiling, new vendors not in your list, possible duplicates, or anything with suspicious wording all get held back for your eyes first.',
      'Flagged invoices come to your phone with a tap-to-review link. You see the actual invoice next to what we extracted, edit anything wrong, and approve in one tap. No login, no QuickBooks, no desktop. Average review time: 15 seconds.',
      'A daily summary lands in your inbox at 5 p.m.: what went out, what came in, what was paid, what needs your review. Books are closed before dinner.',
    ],
    outcomes: [
      ['clock', '60+ hours back per month', 'Both ends of the loop, automated together.'],
      ['trending-up', 'Faster cash flow', 'Reminders go out on time. Invoices get paid earlier. DSO drops.'],
      ['check', 'Nothing falls through', 'Every invoice in or out is logged, audited, and visible at a glance.'],
    ],
    math: [
      'A business sending 30 invoices a month and processing 200 vendor invoices is looking at 50\u201370 hours of manual work between the two \u2014 roughly $1,500 to $2,400 a month in bookkeeper time at $30/hr, plus the soft cost of late reminders, missed follow-ups, and data entry errors at tax time.',
      'If you\u2019re doing the books yourself instead of paying someone, the cost is your time at $100+/hr. The math gets brutal fast.',
      'Build is one-time. Monthly run cost is small enough that it pays for itself the first week. Triple-digit invoice counts make the math more obvious.',
    ],
    smsCaveat: true,
    loomUrl: '',
  },
};

// Old slug → new slug redirects. Anyone hitting /services/speed-to-lead etc. gets bounced
// to the live equivalent so no public link returns a 404 or stale render.
const slugRedirects = {
  'speed-to-lead': 'lead-response-followup',
  'follow-up-nurture': 'lead-response-followup',
  'database-reactivation': 'reviews-reputation',
};

function ServiceDetail() {
  const { slug } = useParams();
  React.useEffect(() => {
    if (slugRedirects[slug]) {
      window.location.hash = '#/services/' + slugRedirects[slug];
    }
  }, [slug]);
  if (slugRedirects[slug]) return null;
  const d = serviceDetails[slug] || serviceDetails['lead-response-followup'];
  return <>
    <section style={{background:'var(--bg-cream)',padding:'120px var(--container-pad) 80px'}}>
      <div style={{maxWidth:'var(--container-max)',margin:'0 auto',display:'grid',gridTemplateColumns:'1fr 1fr',gap:72,alignItems:'end'}} className="svc-hero">
        <div>
          <Eyebrow>{d.eyebrow}</Eyebrow>
          <h1 style={{fontFamily:'var(--font-display)',fontWeight:400,fontSize:'clamp(38px,5vw,62px)',lineHeight:1.06,letterSpacing:'-0.02em',margin:'20px 0 28px'}}>
            {d.h1}
          </h1>
          <p style={{fontFamily:'var(--font-body)',fontSize:20,lineHeight:1.6,color:'var(--text-charcoal)',opacity:0.85,maxWidth:540,margin:'0 0 36px'}}>
            {d.subhead}
          </p>
          <Button to="/book" variant="primary" icon="calendar">Book a 45-min call</Button>
        </div>
        <div style={{aspectRatio:'5/4',borderRadius:16,background:`url(${d.photo}) center / cover no-repeat`,boxShadow:'var(--shadow-photo)'}}/>
      </div>
    </section>

    {/* Why this matters — research-backed stats BEFORE the bleed */}
    {d.why && <section style={{background:'var(--bg-bone)',padding:'100px var(--container-pad)'}}>
      <div style={{maxWidth:'var(--container-max)',margin:'0 auto'}}>
        <div style={{fontFamily:'var(--font-body)',fontSize:12,letterSpacing:'0.14em',textTransform:'uppercase',color:'var(--accent-clay)',fontWeight:500,marginBottom:40}}>{d.why.label}</div>
        <div style={{display:'grid',gridTemplateColumns:'repeat(3,1fr)',gap:24,marginBottom:48}} className="outcome-grid">
          {d.why.stats.map(([num, desc, src], i) =>
            <Reveal key={i} delay={i*110}>
              <div style={{background:'var(--bg-cream)',borderRadius:16,padding:'28px 26px',display:'flex',flexDirection:'column',gap:12,height:'100%'}}>
                <div style={{fontFamily:'var(--font-display)',fontSize:48,fontWeight:500,lineHeight:1,letterSpacing:'-0.02em',color:'var(--text-charcoal)'}}>{num}</div>
                <div style={{fontFamily:'var(--font-body)',fontSize:15,lineHeight:1.55,color:'var(--text-charcoal)',opacity:0.88}}>{desc}</div>
                <div style={{fontFamily:'var(--font-body)',fontSize:11,letterSpacing:'0.1em',textTransform:'uppercase',color:'#7a5a2f',fontWeight:500,marginTop:'auto',paddingTop:10,borderTop:'1px solid rgba(122,90,47,0.25)'}}>{src}</div>
              </div>
            </Reveal>
          )}
        </div>
        <p style={{fontFamily:'var(--font-body)',fontSize:18.5,lineHeight:1.7,color:'var(--text-charcoal)',maxWidth:720,margin:0}}>
          {d.why.paragraph}
        </p>
      </div>
    </section>}

    {/* The bleed */}
    <section style={{background:'var(--bg-cream)',padding:'80px var(--container-pad) 120px'}}>
      <div style={{maxWidth:720,margin:'0 auto',fontFamily:'var(--font-body)',fontSize:19,lineHeight:1.75,color:'var(--text-charcoal)'}}>
        <div style={{fontFamily:'var(--font-body)',fontSize:12,letterSpacing:'0.14em',textTransform:'uppercase',color:'var(--accent-clay)',fontWeight:500,marginBottom:24}}>The bleed</div>
        {d.bleed.map((p,i) => <p key={i} style={{margin: i === d.bleed.length-1 ? 0 : '0 0 1.1em'}}>{p}</p>)}
      </div>
    </section>

    {/* What gets built */}
    <section style={{background:'var(--bg-bone)',padding:'120px var(--container-pad)'}}>
      <div style={{maxWidth:'var(--container-max)',margin:'0 auto'}}>
        <h2 style={{fontFamily:'var(--font-display)',fontWeight:400,fontSize:'clamp(36px,4.5vw,54px)',lineHeight:1.1,letterSpacing:'-0.02em',margin:'0 0 64px'}}>
          What gets built
        </h2>
        <div style={{display:'flex',flexDirection:'column',gap:0,maxWidth:960}}>
          {d.steps.map((step, n) =>
            <div key={n} style={{display:'grid',gridTemplateColumns:'140px 1fr',gap:40,alignItems:'start',borderTop:'1px solid var(--border-hair)',padding:'36px 0'}}>
              <div style={{fontFamily:'var(--font-display)',fontSize:58,fontWeight:400,color:'var(--accent-clay)',lineHeight:1,letterSpacing:'-0.02em'}}>{String(n+1).padStart(2,'0')}</div>
              <div style={{fontFamily:'var(--font-body)',fontSize:18.5,lineHeight:1.65,color:'var(--text-charcoal)',maxWidth:680,paddingTop:8}}>
                {step}
              </div>
            </div>
          )}
        </div>
        {d.smsCaveat && (
          <div style={{maxWidth:960,marginTop:48,padding:'24px 28px',background:'var(--accent-clay-soft)',borderRadius:14,borderLeft:'3px solid var(--accent-clay)',display:'flex',gap:14,alignItems:'flex-start'}}>
            <i data-lucide="info" style={{width:18,height:18,color:'#7a5a2f',flexShrink:0,marginTop:3}}></i>
            <div style={{fontFamily:'var(--font-body)',fontSize:15,lineHeight:1.6,color:'var(--text-charcoal)'}}>
              <strong style={{fontWeight:600}}>Note on go-live timing.</strong> This system sends SMS, which means it has to clear U.S. carrier registration (A2P 10DLC) before the first text can go out &mdash; typically 1&ndash;5 business days, outside our control. The registration runs in parallel with the build, but it can extend the actual go-live date depending on how fast the carriers move. Flagged here so the timeline is clear before you commit.
            </div>
          </div>
        )}
      </div>
    </section>

    {/* What changes */}
    <section style={{background:'var(--bg-cream)',padding:'120px var(--container-pad)'}}>
      <div style={{maxWidth:'var(--container-max)',margin:'0 auto'}}>
        <h2 style={{fontFamily:'var(--font-display)',fontWeight:400,fontSize:'clamp(36px,4.5vw,54px)',lineHeight:1.1,letterSpacing:'-0.02em',margin:'0 0 56px'}}>
          What changes
        </h2>
        <div style={{display:'grid',gridTemplateColumns:'repeat(3,1fr)',gap:24}} className="outcome-grid">
          {d.outcomes.map(([icon,h,sub], i) =>
            <Reveal key={h} delay={i*110}>
              <div style={{background:'var(--bg-bone)',borderRadius:16,padding:32,display:'flex',flexDirection:'column',gap:18,height:'100%'}}>
              <div style={{width:48,height:48,borderRadius:12,background:'var(--accent-clay-soft)',display:'flex',alignItems:'center',justifyContent:'center',color:'var(--text-charcoal)'}}>
                <i data-lucide={icon} style={{width:22,height:22}}></i>
              </div>
              <div style={{fontFamily:'var(--font-display)',fontSize:26,fontWeight:400,lineHeight:1.2,letterSpacing:'-0.015em'}}>{h}</div>
              <div style={{fontFamily:'var(--font-body)',fontSize:15.5,lineHeight:1.55,color:'var(--text-muted)'}}>
                {sub}
              </div>
            </div>
            </Reveal>
          )}
        </div>
      </div>
    </section>

    {/* The math */}
    <section style={{background:'var(--bg-cream)',padding:'40px var(--container-pad) 140px'}}>
      <div style={{maxWidth:820,margin:'0 auto',background:'var(--accent-clay-soft)',borderRadius:20,padding:'56px 52px'}}>
        <Eyebrow color="#7a5a2f">The math &middot; illustrative scenario</Eyebrow>
        <div style={{marginTop:22,fontFamily:'var(--font-body)',fontSize:18.5,lineHeight:1.7,color:'var(--text-charcoal)'}}>
          {d.math.map((p,i) => <p key={i} style={{margin: i === d.math.length-1 ? 0 : '0 0 1em'}}>{p}</p>)}
        </div>
      </div>
    </section>

    {/* Watch it run — walkthrough video slot. Renders embed when loomUrl set, placeholder when empty. */}
    <section style={{background:'var(--bg-bone)',padding:'120px var(--container-pad)'}}>
      <div style={{maxWidth:980,margin:'0 auto'}}>
        <div style={{textAlign:'center',marginBottom:48}}>
          <Eyebrow>Watch it run</Eyebrow>
          <h2 style={{fontFamily:'var(--font-display)',fontWeight:400,fontSize:'clamp(32px,4.2vw,50px)',lineHeight:1.12,letterSpacing:'-0.02em',color:'var(--text-charcoal)',margin:'14px auto 16px',maxWidth:720}}>
            See the actual system in motion.
          </h2>
          <p style={{fontFamily:'var(--font-body)',fontSize:17,lineHeight:1.6,color:'var(--text-muted)',maxWidth:600,margin:'0 auto'}}>
            A short walkthrough &mdash; the build, the moving parts, what it looks like the moment a real lead hits it.
          </p>
        </div>
        <VideoSlot loomUrl={d.loomUrl}/>
      </div>
    </section>

    <section style={{background:'var(--bg-forest)',padding:'120px var(--container-pad)',textAlign:'center'}}>
      <h3 style={{fontFamily:'var(--font-display)',fontWeight:400,fontSize:'clamp(30px,3.8vw,44px)',lineHeight:1.2,letterSpacing:'-0.02em',color:'var(--text-cream)',margin:'0 auto 36px',maxWidth:720}}>
        Let&rsquo;s see if this fits your business.
      </h3>
      <Button to="/book" variant="cream" icon="calendar">Book a 45-min call</Button>
    </section>
  </>;
}

function VideoSlot({ loomUrl }) {
  // Accepts either a Loom share URL ('https://www.loom.com/share/abc123') or embed URL ('https://www.loom.com/embed/abc123').
  // Auto-converts share -> embed. If empty, renders a placeholder card.
  const embed = loomUrl ? loomUrl.replace('/share/', '/embed/') : null;
  if (embed) {
    return (
      <div style={{position:'relative',width:'100%',paddingBottom:'56.25%',borderRadius:18,overflow:'hidden',boxShadow:'var(--shadow-photo)',background:'#0e120c'}}>
        <iframe
          src={embed}
          frameBorder="0"
          allowFullScreen
          allow="autoplay; fullscreen; picture-in-picture"
          style={{position:'absolute',top:0,left:0,width:'100%',height:'100%'}}
          title="Service walkthrough"
        />
      </div>
    );
  }
  return (
    <div style={{position:'relative',width:'100%',paddingBottom:'56.25%',borderRadius:18,overflow:'hidden',background:'linear-gradient(135deg, rgba(30,38,26,0.95), rgba(30,38,26,0.78)), var(--bg-forest)',border:'1px dashed rgba(248,244,237,0.22)'}}>
      <div style={{position:'absolute',inset:0,display:'flex',flexDirection:'column',alignItems:'center',justifyContent:'center',gap:18,padding:24,textAlign:'center'}}>
        <div style={{width:72,height:72,borderRadius:'50%',border:'1.5px solid rgba(248,244,237,0.4)',display:'flex',alignItems:'center',justifyContent:'center',color:'var(--accent-clay)'}}>
          <i data-lucide="play" style={{width:28,height:28}}></i>
        </div>
        <div style={{fontFamily:'var(--font-display)',fontStyle:'italic',fontSize:22,color:'rgba(248,244,237,0.92)',letterSpacing:'-0.01em'}}>
          Walkthrough video coming soon.
        </div>
        <div style={{fontFamily:'var(--font-body)',fontSize:13.5,color:'rgba(248,244,237,0.55)',maxWidth:420,lineHeight:1.55}}>
          Recording these once the systems are live with their first clients. Want a custom demo of this exact build before then? Book the audit call.
        </div>
      </div>
    </div>
  );
}

window.ServiceDetail = ServiceDetail;
