/* global React, Container, Section, Eyebrow, Button, Reveal */
const {
  useState: useStateArticles,
  useEffect: useEffectArticles,
  useRef: useRefArticles,
} = React;

/* ─── Inline markdown: **bold** → <strong> ─────────── */
function rt(text) {
  if (!text || typeof text !== 'string') return text;
  const parts = text.split(/(\*\*[^*]+\*\*)/g);
  return parts.map((p, i) =>
    p.startsWith('**') && p.endsWith('**')
      ? React.createElement('strong', { key: i, style: { color: 'var(--fg)', fontWeight: 600 } }, p.slice(2, -2))
      : p
  );
}

/* ─── SEO helpers ────────────────────────────────────── */
function setMeta(sel, attr, val) {
  const el = document.querySelector(sel);
  if (el) el.setAttribute(attr, val);
}
const DEFAULT_TITLE = 'Daee Media: Revenue systems, not ad management';
const DEFAULT_DESC  = 'Daee Media builds end-to-end revenue systems for service businesses. Meta Ads, funnels, CRM, creative direction, and tracking treated as one compounding system. Founder-led. Globally distributed.';

/* ═══════════════════════════════════════════════════════
   ARTICLES DATA
═══════════════════════════════════════════════════════ */
const ARTICLES = [
  /* ── 01 ── */
  {
    id: 'real-service-is-never-for-you',
    num: '01', date: 'Apr 2026', schemaDate: '2026-04-01',
    readTime: '4 min', tag: 'Philosophy',
    title: "Real service is never for you.",
    subtitle: "It's always with you.",
    seoTitle: "Real Service Is Never For You | Daee Media Field Notes",
    seoDesc: "The most common mistake in service businesses is the framing. Service is not order-taking. It is collaboration. Here is why the distinction determines everything.",
    ogTitle: "Real service is never for you. It's always with you.",
    ogDesc: "Most agencies optimise for your approval. We optimise for your outcome. That distinction changes everything.",
    keywords: "service business marketing agency UK USA Australia, vendor vs partner marketing agency, how to choose a marketing agency, agency partnership model, performance marketing agency for service businesses, boutique marketing agency globally",
    excerpt: "The most common mistake in service businesses is the framing. You're serving the client. They're the boss. You execute what they ask, hope they're happy, repeat. That's not service. That's order-taking.",
    body: [
      { type: 'p', text: "The most common mistake in service businesses is the framing. You're serving the client. They're the boss. You execute what they ask, hope they're happy, repeat." },
      { type: 'p', text: "That's not service. That's order-taking." },
      { type: 'p', text: "Real service, the kind that actually moves a business, is never for the client. It's with them. Think about it: a doctor can't cure a patient who won't follow the treatment. The best architect in the world can't build your vision if you won't tell them what you actually want. A performance agency can't compound your revenue if you won't give them access to the business underneath the ads." },
      { type: 'p', text: "The professional works alongside you, not as a subordinate to your instructions." },
      { type: 'p', text: "When service providers prioritize your approval over your outcomes, they shrink. They stop giving honest feedback. They stop pushing back on bad decisions. They start optimizing for the contract instead of the number. And the results always follow." },
      { type: 'heading', text: "This is why we work with partners, not clients." },
      { type: 'p', text: "We're not executing your brief. We're building your revenue system. That requires access, trust, and genuine collaboration from both sides. If you want a vendor to take instructions and deliver reports, we're not the right fit. If you want a partner invested in the outcome, we might be." },
      { type: 'p', text: "The question isn't how good is your agency. The real question is: are you treating them like a boss, or a partner? Because the answer determines everything that comes after." },
    ],
    metrics: null, cta: 'Apply to work with us', ctaTarget: 'apply',
    linkedinUrl: 'https://www.linkedin.com/posts/mohammed-saad-shaikh_real-service-is-never-for-you-its-always-ugcPost-7461809970573946880-TAwQ',
    related: ['apple-is-not-a-product-company', 'agency-client-communication-crisis'],
  },
  /* ── 02 ── */
  {
    id: 'apple-is-not-a-product-company',
    num: '02', date: 'Apr 2026', schemaDate: '2026-04-15',
    readTime: '4 min', tag: 'Systems',
    title: "Apple is not a product company.",
    subtitle: "And neither are you.",
    seoTitle: "Apple Is Not a Product Company | Daee Media Field Notes",
    seoDesc: "Apple makes the most expensive consumer products in the world. And they're not a product company. Here is what that means for service businesses and how we apply it at Daee.",
    ogTitle: "Apple is not a product company. And neither are you.",
    ogDesc: "The product is the vehicle. The experience is the business. Here's what Apple's model teaches us about running a service agency.",
    keywords: "service experience marketing UK USA Australia, how to differentiate marketing agency, agency client experience, boutique marketing agency service business, premium marketing agency globally",
    excerpt: "Apple makes the most expensive consumer products in the world. And they're not a product company. Every product they ship exists for one reason: to deliver the best possible experience to the end user. The product is the vehicle. The experience is the business.",
    body: [
      { type: 'p', text: "Apple makes the most expensive consumer products in the world. And they're not a product company." },
      { type: 'p', text: "Every product they ship exists for one reason: to deliver the best possible experience to the end user. The product is the vehicle. The experience is the business. They could have put the same chips in a cheaper case. They didn't. They could have exposed the complexity of their software. They don't. They conceal everything hard, so everything the user touches feels effortless." },
      { type: 'p', text: "The result: people pay 3x more for equivalent hardware, and they feel good about it." },
      { type: 'heading', text: "Now apply that to a service business." },
      { type: 'p', text: "If you're an agency, a consultancy, or an advisory firm, your deliverable is not your business. The experience the client has around the deliverable is." },
      { type: 'p', text: "The quality of your work matters. But so does how clear the kickoff call feels. How you communicate when something goes wrong. Not if, when. Whether the client feels more confident or more anxious after every check-in. Whether they'd describe working with you as smooth or exhausting." },
      { type: 'p', text: "Most agencies get the deliverable right and fumble the experience. The client gets results but doesn't feel looked after. They leave for someone who delivers less but makes them feel more." },
      { type: 'heading', text: "What we optimize for at Daee." },
      { type: 'p', text: "We engineer both. The system has to perform. That's non-negotiable. But the experience has to match. The founder has to feel like they have a thinking partner, not a vendor who sends reports on Fridays." },
      { type: 'p', text: "Apple didn't build loyalty by having the best products. They built it by making people feel something every time they opened the box. The question worth asking: are you giving people a service, or an experience they'll never stop talking about?" },
    ],
    metrics: null, cta: 'See how we work', ctaTarget: 'apply',
    linkedinUrl: 'https://www.linkedin.com/posts/mohammed-saad-shaikh_apple-is-not-a-product-company-ugcPost-7462559059800612864-KXLD',
    related: ['real-service-is-never-for-you', 'godspeed-client-communication'],
  },
  /* ── 03 ── */
  {
    id: 'why-we-say-no',
    num: '03', date: 'Mar 2026', schemaDate: '2026-03-01',
    readTime: '4 min', tag: 'How we work',
    title: "Why we say no more than we say yes.",
    subtitle: "And why that's the whole business model.",
    seoTitle: "Why Daee Media Says No More Than Yes | Field Notes",
    seoDesc: "We turn down more clients than we take on. That's not a capacity problem. It's a deliberate choice. Here is what happens when an agency says yes to everyone, and why we chose the other path.",
    ogTitle: "Why we say no more than we say yes.",
    ogDesc: "We turn down more clients than we take on. That's not a capacity problem. It's the whole model.",
    keywords: "selective marketing agency UK USA Australia, boutique performance marketing for service businesses, how to choose the right marketing agency, high-ticket service business marketing, agency client fit, performance marketing agency that says no",
    excerpt: "We turn down more clients than we take on. That's not a capacity problem. It's a deliberate choice. Here is what happens when an agency says yes to everyone, and why we chose the other path.",
    body: [
      { type: 'p', text: "We turn down more clients than we take on. That's not a capacity problem. It's the whole business model." },
      { type: 'heading', text: "What happens when an agency takes every client." },
      { type: 'p', text: "They optimize for revenue, not results. More clients means more retainers. More retainers means the work gets divided. The founder stops being in the room. An account manager takes over. The work gets shallower. The results follow." },
      { type: 'p', text: "This is how most agencies work. It scales. It just doesn't produce the outcome the client hired for." },
      { type: 'heading', text: "Why we chose the other path." },
      { type: 'p', text: "We work with two or three partners at a time. One team, no account chain. Saad is in the room: writing the brief, reviewing the creative, inside the ad account, building the CRM logic. That's only possible at a specific capacity. When we say yes to a fourth client, one of the existing three gets less. We'd rather not take the fourth client." },
      { type: 'heading', text: "What fit actually means." },
      { type: 'p', text: "We say no when the business doesn't have product-market fit yet. Ads can't fix a broken offer. We say no when the founder can't service the leads we'd generate. A system that sends 200 leads a month is useless if the team can only handle 20. We say no when the relationship would be transactional. We don't do vendor. We do partner." },
      { type: 'heading', text: "What happens when we say no." },
      { type: 'p', text: "We refer. If someone's not a fit for us, there's usually someone better positioned for what they need. We'd rather end a call with a useful introduction than a retainer that doesn't serve them. This costs us short-term revenue. It's the whole reason the work actually lands." },
    ],
    metrics: null, cta: 'Apply to work with us', ctaTarget: 'apply',
    linkedinUrl: null,
    related: ['real-service-is-never-for-you', 'apple-is-not-a-product-company'],
  },

  /* ════════════════════════════════════════════════════
     TIER 1: PROTEIN PALS FIELD NOTES (04-10)
  ════════════════════════════════════════════════════ */

  /* 04: CAPI / LeadChain */
  {
    id: 'conversion-api-meta-crm-loop',
    num: '04', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '7 min', tag: 'Infrastructure',
    title: "The invisible wire between your CRM and Meta's brain.",
    subtitle: "How a single integration dropped CPL from $3.50 to $1.13.",
    seoTitle: "How the Meta Conversion API Cuts Your Cost Per Lead in Half | Daee Media",
    seoDesc: "Most service businesses run Meta ads and never close the loop back to their CRM. Here's the exact CAPI infrastructure that dropped CPL from $3.50 to $1.13 for a subscription client, and why the savings compound every month.",
    ogTitle: "The invisible wire between your CRM and Meta's brain.",
    ogDesc: "Every unrecorded conversion is wasted intelligence. Here's how we fed CRM outcomes back to Meta in real time. Here's what happened to the cost per lead.",
    keywords: "Meta Conversion API CAPI, lower cost per lead Meta ads UK USA Australia UAE, CRM Meta integration, Facebook ads CPL reduction, CAPI lead generation service business, LeadChain Zoho CRM Meta, improve Meta ad targeting with CRM data, Meta advertising feedback loop, server-side tracking Meta ads",
    excerpt: "You run a Meta ad. Someone fills the form. You get a name and number. Your salesperson calls. Maybe they convert. Maybe they don't. Meta never finds out which. That's the gap. It has a fix.",
    body: [
      { type: 'p', text: "You run a Meta ad. Someone fills a form. You get a name and number. Your salesperson calls. Maybe they convert. Maybe they don't." },
      { type: 'p', text: "Meta never finds out which. That's the default state of almost every Meta ads campaign running right now. The loop ends at the form fill. Meta's algorithm keeps optimising blind." },
      { type: 'p', text: "This is the most expensive gap in performance marketing. And it has a fix." },
      { type: 'heading', text: "What the Conversion API actually does" },
      { type: 'p', text: "The Meta Conversion API (CAPI) is a server-side connection between your CRM and Meta's ads system. When a lead in your CRM is marked **converted**, that signal travels back to Meta: find more people who look like this. When a lead is marked **junk**, that signal also travels back: stop finding people who look like this." },
      { type: 'p', text: "Every outcome, in real time, teaching the system. The CPL doesn't stay flat. It compounds down." },
      { type: 'heading', text: "What this looked like for Protein Pals" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. When Daee Media began working with them in May 2025, there was no ads infrastructure, no CRM, no automation. We built the full stack. CAPI was the piece that closed the loop." },
      { type: 'steps', items: [
        { n: '01', title: 'Ad impression', body: 'Prospect sees an Instagram or Facebook ad targeting Toronto GTA.' },
        { n: '02', title: 'Native lead form', body: 'Two-tap form inside Meta. No redirect, no landing page drop-off.' },
        { n: '03', title: 'ManyChat qualification', body: 'Bot captures postal code, dietary preference, health goal, profession.' },
        { n: '04', title: 'CRM entry', body: 'Fully tagged lead lands in Zoho CRM. Founders call, have the conversation.' },
        { n: '05', title: 'Stage update', body: 'Founder marks the lead: qualified, contacted, closed, or junk.' },
        { n: '06', title: 'CAPI event fires', body: 'LeadChain routes the stage change back to Meta as a conversion event.' },
        { n: '07', title: 'Algorithm recalibrates', body: 'Meta learns what a Protein Pals subscriber looks like. Next lead is cheaper.' },
      ]},
      { type: 'screenshot', src: '/assets/pp-case/pp-leadchain.png', variant: 'capi',
        caption: 'LeadChain · CAPI events routing Zoho CRM stage updates back to Meta in real time',
        alt: 'LeadChain dashboard showing Conversion API event routing from Zoho CRM to Meta Ads for Protein Pals' },
      { type: 'heading', text: "The compounding effect on cost per lead" },
      { type: 'metrics', items: [
        { num: '$3.50', label: 'Launch CPL', sub: 'Founder-led creative, Jun 2025' },
        { num: '$1.13', label: 'Peak CPL', sub: 'CAPI-optimised, Oct 2025' },
        { num: '60%', label: 'CPL reduction', sub: 'System learning over 4 months' },
      ]},
      { type: 'p', text: "The October figure wasn't just better creative. It was a system that had been learning for four months, with hundreds of conversion outcomes fed back to Meta, teaching it what a Protein Pals subscriber looks like with increasing precision." },
      { type: 'faq', items: [
        { q: 'What is the Meta Conversion API (CAPI)?', a: 'The Meta Conversion API is a server-side connection between your CRM or backend system and Meta\'s advertising algorithm. Unlike the Meta Pixel which relies on browser-side tracking, CAPI sends conversion events directly from your server, making it more reliable, privacy-resilient, and capable of sending outcomes that browser tracking cannot capture. When a lead in your CRM is marked as converted, qualified, or junk, CAPI fires that outcome back to Meta\'s algorithm in real time.' },
        { q: 'How does the Meta Conversion API reduce cost per lead?', a: 'CAPI closes the feedback loop between your sales outcomes and Meta\'s targeting algorithm. Positive signals (converted leads) teach Meta to find more people who look like your best customers. Negative signals (junk leads) teach Meta to avoid spending on similar profiles. Over 60-90 days, this continuous learning compounds into lower cost per lead. For Protein Pals, CAPI integration reduced CPL from $3.50 CAD to $1.13 CAD over four months.' },
        { q: 'Which CRM tools integrate with the Meta Conversion API?', a: 'The Meta Conversion API integrates with most CRMs using bridge tools. LeadChain is purpose-built for CRM-to-Meta CAPI routing and supports granular pipeline-stage events. Zapier handles simpler setups. Zoho CRM integrates with CAPI natively for basic events or via LeadChain for stage-level mapping. The key is mapping your pipeline stages to Meta event types: Closed Won becomes a Purchase event, Junk Lead becomes a negative custom conversion.' },
      ] },
      { type: 'cta-inline', text: "See the full 1,942-lead system that ran this loop.", label: "Read the Protein Pals case study", target: 'case' },
      { type: 'heading', text: "Why most agencies skip this" },
      { type: 'p', text: "Installing CAPI properly requires CRM configuration, event mapping, server-side setup, and ongoing QA. It doesn't produce an immediate dashboard metric. Most agencies skip it because clients can't see it working. Three months in, when the CPL has dropped by 60%, they feel it." },
      { type: 'heading', text: "The minimum viable setup" },
      { type: 'steps', items: [
        { n: '01', title: 'Map pipeline stages to Meta events', body: 'Closed Won = Purchase. Junk = custom negative signal. Contacted = Lead (lower weight).' },
        { n: '02', title: 'Choose a bridge tool', body: 'LeadChain is built for this. Zapier handles simpler CRM setups. Both fire server-side.' },
        { n: '03', title: 'Test in Meta Events Manager', body: 'Verify events are received and deduplicated before scaling spend.' },
        { n: '04', title: 'Give it 60–90 days', body: 'The algorithm needs volume to recalibrate. Don\'t judge impact after two weeks.' },
      ]},
    ],
    cta: 'Book a system audit', ctaTarget: 'apply',
    related: ['five-questions-98-percent-qualified', 'meta-ad-rejection-fix'],
  },

  /* 05: ManyChat qualification */
  {
    id: 'five-questions-98-percent-qualified',
    num: '05', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '6 min', tag: 'Lead Quality',
    title: "Five questions that eliminated 98% of bad leads.",
    subtitle: "Before a single phone call was made.",
    seoTitle: "Five Questions That Produced a 98.67% Lead Quality Rate on Meta Ads | Daee Media",
    seoDesc: "Five ManyChat qualification questions turned 1,942 raw Meta leads into a 98.67% pre-qualified pipeline before a single sales call. Here's the exact structure, the question order rationale, and how to replicate it for your service business.",
    ogTitle: "Five questions that eliminated 98% of bad leads before a human got involved.",
    ogDesc: "Your sales team shouldn't be qualifying leads. Automation should. Here's how ManyChat filtered 1,942 leads down to a 1.33% junk rate.",
    keywords: "ManyChat lead qualification Meta ads, how to qualify leads automatically UK USA Australia, reduce junk leads Facebook ads, automated sales qualification service business, Instagram lead generation qualification, ManyChat Zoho CRM, pre-qualified leads pipeline, lead quality rate Meta advertising, 98% lead quality Meta ads",
    excerpt: "Most lead generation problems aren't lead volume problems. They're lead quality problems. A business runs Meta ads, gets 50 enquiries a week, and the sales team spends three days chasing numbers that don't pick up. Here's the qualification layer that fixed it.",
    body: [
      { type: 'p', text: "Most lead generation problems aren't lead volume problems. They're lead quality problems." },
      { type: 'p', text: "A business runs Meta ads, gets 50 enquiries a week, and the sales team spends three days calling numbers that don't pick up, zip codes outside the delivery area, and people who clicked out of curiosity, not intent. By the time they reach the 12 people who actually want to buy, they're exhausted. And so is the pipeline." },
      { type: 'p', text: "The solution isn't fewer leads. It's **earlier filtering**." },
      { type: 'heading', text: "The context: Protein Pals" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. The founders were doing their own sales calls. Every minute spent on a bad lead was a minute not spent on a real one. We built a ManyChat qualification flow that sat between the Meta lead form and the CRM. Every lead passed through five questions before a founder's phone rang." },
      { type: 'heading', text: "The five questions and what each filters for" },
      { type: 'steps', items: [
        { n: '01', title: 'What\'s your postal code?', body: 'The gating question. Protein Pals delivered to specific zones. Wrong geography = operationally worthless lead, regardless of interest. Postal code comes first, before anything warm or qualifying, because it eliminates the unserviceable instantly. The wrong-zone signal also fed back to Meta via CAPI as a negative audience signal.' },
        { n: '02', title: 'Dietary preference: veg or non-veg?', body: 'Pre-assigns the lead to the correct follow-up flow. Also built one of the most valuable data sets in the engagement: 60–70% of converting subscribers were vegetarian, a majority preference completely hidden behind the brand\'s gym-culture positioning. One question. Months of strategic clarity.' },
        { n: '03', title: 'What\'s your health goal?', body: 'Qualifies intent depth. Someone with a specific goal (muscle gain, fat loss) is further along the buying decision than someone answering "generally eat healthier." It also writes the sales script: the founder opens the call with the lead\'s own words.' },
        { n: '04', title: 'Work situation: student, WFH, or office?', body: 'Predicts conversion likelihood and LTV. WFH leads had the highest conversion rate: they eat at home, control their own lunch, and are the decision-maker. Office workers converted lower. Students showed lower LTV. This question prioritised the call list without eliminating anyone.' },
        { n: '05', title: 'Name and best contact number', body: 'Last, not first. By placing name and number after four questions that demonstrated understanding of their situation, completion rate was significantly higher. The lead had already invested in the conversation. Dropping off at question five was psychologically harder.' },
      ]},
      { type: 'heading', text: "What happened in Zoho after the flow completed" },
      { type: 'p', text: "Every completed ManyChat flow fired a structured entry into Zoho CRM: name, number, postal code, dietary preference, health goal, work situation, all pre-tagged. The founder opened a lead record with a complete profile before saying hello." },
      { type: 'pullquote', text: "The call wasn't: 'So tell me what you're looking for.' It was: 'Hey, you mentioned you're WFH in Vaughan, looking to hit your muscle gain goals. I'd actually suggest the lunch-dinner macro plan. Let me walk you through it.' That's the difference between a cold call and a warm close.", attribution: "Saad, Daee Media" },
      { type: 'metrics', items: [
        { num: '1,942', label: 'Total leads', sub: 'Jun–Nov 2025 · 6–7k CAD spend' },
        { num: '26', label: 'Junk leads', sub: '1.33% junk rate' },
        { num: '98.67%', label: 'Pre-qualified', sub: 'Before any sales call' },
      ]},
      { type: 'screenshot', src: '/assets/pp-case/pp-crm-junk.png', variant: 'crm',
        caption: 'Zoho CRM · Junk Lead filter: only 26 junk records out of 1,942 total leads generated',
        alt: 'Zoho CRM filtered to Junk Lead status, showing Total Records: 26 out of 1942 leads' },
      { type: 'faq', items: [
        { q: 'How many questions should a lead qualification flow have?', a: 'Five questions is optimal for most service businesses. Fewer than four misses critical qualifying signals. More than six causes completion rates to drop significantly. The structure matters as much as the count: a hard eligibility gate first (geography, service area, or budget threshold), segmentation second, intent depth third, priority ranking fourth, and contact details last. Placing contact details last consistently improves completion because the lead has already invested in the prior four answers.' },
        { q: 'What is ManyChat and how is it used for lead generation?', a: 'ManyChat is a conversational automation platform used to qualify leads between the Meta ad form and your CRM. When a prospect submits a Meta lead form or sends a DM keyword trigger, ManyChat asks qualifying questions via automated chat, captures structured responses, and passes the tagged data to your CRM. It acts as an automated screening layer, ensuring only qualified leads reach your sales team. For Protein Pals, ManyChat produced a 98.67% pre-qualified lead rate across 1,942 leads.' },
        { q: 'How do I reduce junk leads from Meta ads?', a: 'Reducing junk leads from Meta ads requires both upstream and downstream intervention. Upstream: add a qualification automation layer (like ManyChat) between the ad form and your CRM, and use geography or service eligibility as the first gating question to eliminate unserviceable leads before any human involvement. Downstream: feed junk lead outcomes back to Meta via Conversion API as negative signals, which trains the algorithm to deprioritise similar profiles in future campaigns.' },
      ] },
      { type: 'cta-inline', text: "See the full system that generated 1,942 pre-qualified leads.", label: "Read the Protein Pals case study", target: 'case' },
      { type: 'heading', text: "How to build this for your business" },
      { type: 'steps', items: [
        { n: '01', title: 'Gate first', body: 'Geography, service eligibility, or any hard operational constraint. Eliminate the unserviceable before qualifying the rest.' },
        { n: '02', title: 'Segment second', body: 'Product type, service tier, dietary preference. Shapes downstream conversation and creative retargeting.' },
        { n: '03', title: 'Intent third', body: 'Goal, timeline, urgency. Tells you how hot the lead is and what angle to open the sales call with.' },
        { n: '04', title: 'Priority fourth', body: 'Work situation, budget range, decision-making position. Ranks the call list before it hits your inbox.' },
        { n: '05', title: 'Contact last', body: 'Always last. The investment in the prior four questions drives completion. Name and number at the end converts at a higher rate than name and number at the start.' },
      ]},
    ],
    cta: 'Build a qualified pipeline', ctaTarget: 'apply',
    related: ['conversion-api-meta-crm-loop', 'free-trial-vs-subscribe-now'],
  },

  /* 06: Instagram pinned post */
  {
    id: 'instagram-pinned-post-offer-visibility',
    num: '06', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '5 min', tag: 'Organic',
    title: "The Instagram move that costs nothing and converts like an ad.",
    subtitle: "DMs picked up in 48 hours. Zero spend.",
    seoTitle: "Instagram Pinned Post Strategy for Service Businesses | Daee Media",
    seoDesc: "Before running a single paid ad, we asked Protein Pals to build pinned carousel posts for every plan. DMs picked up in 48 hours. Zero spend. Here's the exact structure.",
    ogTitle: "The Instagram move that costs nothing and converts like an ad.",
    ogDesc: "Before we spent a dollar on Protein Pals' paid campaigns, we asked them to do one thing on Instagram. DMs picked up within 48 hours.",
    keywords: "Instagram pinned post strategy service business UK USA Australia, how to convert Instagram followers to customers, Instagram profile optimization for business, offer visibility Instagram, Instagram carousel for service businesses, organic Instagram lead generation, Instagram marketing without paid ads, Instagram offer content strategy",
    excerpt: "Open your business Instagram right now. Pretend you've never heard of what you do. Can a new visitor tell, within ten seconds, what your service is, what it costs, and how to get started? If the answer is no, you have an offer visibility problem. No amount of paid advertising will fix it.",
    body: [
      { type: 'p', text: "Open your business Instagram right now. Pretend you've never heard of what you do." },
      { type: 'p', text: "Can a new visitor tell, within ten seconds and without clicking anything, what your service is, what it costs, and how to get started?" },
      { type: 'p', text: "If the answer is no, you have an **offer visibility problem**. And no amount of paid advertising will fix it, because ads send people to your profile, and your profile sends them nowhere." },
      { type: 'heading', text: "Protein Pals: good product, invisible offer" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. Before Daee Media's involvement, they had under 300 Instagram followers, beautiful food photographs, and zero indication of what the plans cost, how to subscribe, or what a new customer would actually receive." },
      { type: 'p', text: "A potential subscriber could scroll the entire grid and leave with nothing actionable. The offer wasn't visible. And an invisible offer doesn't convert." },
      { type: 'highlight', label: 'The distinction', text: "Aesthetic content says: 'We are real and our food looks good.' Offer content says: 'Here is what you get, here is what it costs, here is how to start.' You need both. Most food businesses have only the first." },
      { type: 'heading', text: "The free move before any ad spend" },
      { type: 'p', text: "Before formal onboarding, before the creative shoot, before a single paid campaign, we gave Protein Pals one specific piece of advice: build a **pinned carousel post** for each core plan." },
      { type: 'steps', items: [
        { n: 'S1', title: 'Slide 1: Plan name + headline', body: 'What it is and who it\'s for. One sentence. Nothing else.' },
        { n: 'S2', title: 'Slides 2-4: Real photographs', body: 'Not styled. Not stock. Real food, real portions, real presentation. This is the trust layer.' },
        { n: 'S3', title: 'Slide 5: Macros', body: 'Protein, carbs, fats, calories per meal. Numbers speak to the fitness-minded buyer immediately.' },
        { n: 'S4', title: 'Slide 6: Price and options', body: 'Stated clearly. No "DM for pricing." The offer has to be visible without friction.' },
        { n: 'S5', title: 'Slide 7: Single CTA', body: '"DM us \'menu\' to get the full plan details." One trigger word that starts the ManyChat automation.' },
      ]},
      { type: 'p', text: "Three plans. Three pinned carousels. Pinned to the top of the profile: the first thing any visitor sees on any device." },
      { type: 'heading', text: "What happened in 48 hours" },
      { type: 'p', text: "DMs picked up within 48 hours. Not from paid promotion: the carousels were organic posts. Anyone landing from a hashtag, a tag, or a share could now see the offer immediately and act on it. Subscriptions climbed past the early twenties. This was **before any campaign launched**." },
      { type: 'whatsapp', src: '/assets/pp-case/pp-wa-launch.jpeg',
        caption: '25 June 2025 · Campaign launch day: first leads coming in, on a foundation that was already converting' },
      { type: 'heading', text: "The bigger principle" },
      { type: 'p', text: "Paid advertising amplifies what exists. If a new visitor lands on your profile and can't understand what you sell, the ad that sent them there was wasted. The pinned carousel doesn't just improve organic performance. It makes every paid campaign more efficient, because every person who clicked the ad now has a clear next step." },
      { type: 'p', text: "The foundation has to be there before the machine runs on top of it." },
      { type: 'cta-inline', text: "See what happened when we built the full machine.", label: "Read the Protein Pals case study", target: 'case' },
    ],
    cta: 'Audit my system', ctaTarget: 'apply',
    related: ['free-trial-vs-subscribe-now', 'five-questions-98-percent-qualified'],
  },

  /* 07: Free trial */
  {
    id: 'free-trial-vs-subscribe-now',
    num: '07', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '5 min', tag: 'Conversion',
    title: "Why 'free trial' outperformed 'subscribe now', by a margin we didn't expect.",
    subtitle: "The trial isn't a giveaway. It's a closing mechanism.",
    seoTitle: "Why Free Trial Outperforms Subscribe Now for Subscription Businesses | Daee Media",
    seoDesc: "For subscription businesses, the trial isn't a giveaway. It's a closing mechanism. Here's why 'free 2-day trial' converted at a higher rate, and when to use it.",
    ogTitle: "Why 'free trial' outperformed 'subscribe now' for a meal delivery startup.",
    ogDesc: "A $100/month subscription requires trust that a form can't build. Here's why we used a trial as the conversion engine and how it fed the qualification flow.",
    keywords: "free trial conversion subscription business UK USA Australia, how to convert leads for subscription services, trial offer lead generation strategy, subscription business acquisition, subscription marketing Meta ads, ManyChat trial automation, reduce subscriber churn, subscription service Meta advertising",
    excerpt: "There's a conventional tension in subscription marketing: free trials attract the wrong people. The logic goes: people who want something free don't intend to pay. This logic is wrong for a specific category of business. Here's why.",
    body: [
      { type: 'p', text: "There's a conventional tension in subscription business marketing: free trials attract the wrong people. The logic goes: people who want something free don't intend to pay." },
      { type: 'p', text: "This logic is wrong for a specific category of service business. And understanding why is worth a significant amount of revenue." },
      { type: 'heading', text: "The context: a $100/month decision" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. Their subscription plans started at roughly **$100 CAD per month**, a recurring commitment that required the buyer to trust, before ordering, that the food would taste good, arrive on time, and be worth the routine." },
      { type: 'p', text: "No amount of Instagram photography fully closes that trust gap. Neither does a well-written lead form. The product itself closes it." },
      { type: 'highlight', label: 'Core insight', text: "When the product is good enough to sell itself on first contact, the trial isn't a cost. It's your best-converting salesperson." },
      { type: 'heading', text: "How the trial worked inside ManyChat" },
      { type: 'p', text: "When a prospect tapped a Protein Pals ad, the ManyChat automation offered two entry points: **'Menu'**, which sent the plan PDF and began qualification, and **'Trial'**, which captured their details, confirmed postal code eligibility, and scheduled a free 2-day meal delivery." },
      { type: 'p', text: "Both paths fed the same qualification questions and the same Zoho CRM pipeline. But the trial path produced a meaningfully different downstream outcome." },
      { type: 'whatsapp', src: '/assets/pp-case/pp-wa-july13.jpeg',
        caption: '13 July 2025 · 45 closed deals in under 15 days, many starting from the trial entry point' },
      { type: 'heading', text: "Why trial leads converted at a higher rate" },
      { type: 'p', text: "A lead who requests a menu is expressing **interest**. A lead who requests a trial is expressing **intent**." },
      { type: 'steps', items: [
        { n: '01', title: 'Address shared', body: 'A significantly higher trust signal than a phone number. They\'ve committed a delivery location.' },
        { n: '02', title: 'Time slot committed', body: 'They\'re expecting a delivery. The psychological ownership of the experience has already started.' },
        { n: '03', title: 'Product experienced', body: 'The objection "but I don\'t know if I\'ll like it" is pre-resolved before the sales call starts.' },
      ]},
      { type: 'p', text: "When the founder called a trial lead, the conversation started from a completely different position. The lead had already eaten the food. The call wasn't 'are you interested?' It was: 'did you enjoy it, and which plan makes sense for you?'" },
      { type: 'heading', text: "When the trial model applies" },
      { type: 'steps', items: [
        { n: '01', title: 'The product sells itself on first contact', body: 'If experiencing it once removes the primary objection, a trial removes that objection at scale.' },
        { n: '02', title: 'The commitment is recurring', body: 'A one-time purchase doesn\'t need a trial. A monthly subscription asks someone to say yes repeatedly. The trial earns that yes before you ask for it.' },
        { n: '03', title: 'Your geography can service it', body: 'The trial only works for deliverable leads. The postal code qualification question exists precisely to ensure you\'re not shipping to someone you can\'t serve.' },
      ]},
      { type: 'p', text: "A subscriber who started with a free trial has a lower churn rate and higher lifetime value than one who clicked 'Subscribe Now' out of impulse. The trial doesn't just convert better. It converts **better customers**." },
      { type: 'cta-inline', text: "See the full acquisition system that built this pipeline.", label: "Read the Protein Pals case study", target: 'case' },
    ],
    cta: 'Build a qualified pipeline', ctaTarget: 'apply',
    related: ['instagram-pinned-post-offer-visibility', 'five-questions-98-percent-qualified'],
  },

  /* 08: Meta rejection */
  {
    id: 'meta-ad-rejection-fix',
    num: '08', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '8 min', tag: 'Meta Ads',
    title: "Meta rejected every ad we ran for six weeks.",
    subtitle: "Here's the diagnosis, the rebuild, and the $1.28 comeback.",
    seoTitle: "Meta Keeps Rejecting Your Lead Gen Ads: The Exact Fix | Daee Media",
    seoDesc: "Meta rejected every lead gen ad we ran for six weeks. CPL hit $9 CAD. Here's the exact three-phase diagnosis, the rebuild process, and the $1.28 CPL comeback. What to do when Meta flags your lead forms for policy violations.",
    ogTitle: "Meta kept rejecting our lead gen ads for 6 weeks. Here's what we rebuilt.",
    ogDesc: "'Forms collecting data' cited as a violation. By Meta. On Meta Lead Ads. Here's how we navigated the rejection cycle and came back at $1.28 CPL.",
    keywords: "why Meta rejects lead generation ads, how to fix rejected Meta ad UK USA Australia, Meta ad policy lead forms, Meta ad review system explained, CPL spike Meta ads fix, Facebook ads rejected how to appeal, Instagram lead gen ads rejected, Meta advertising compliance service business, Meta ad account health",
    excerpt: "In August 2025, Meta cited 'forms collecting data' as a policy violation on a lead generation ad, on the same platform whose entire lead product exists to collect data. CPL climbed from $2 to $9. This is exactly what we did.",
    body: [
      { type: 'p', text: "If you've run Meta lead generation ads long enough, you've seen the rejection screen. 'This ad violates our Advertising Standards.' Policy cited: something generic. Appeal available. Appeal reviewed in 48 hours. Appeal denied. No further explanation." },
      { type: 'p', text: "Between August and September 2025, Daee Media experienced this repeatedly on behalf of **Protein Pals**, a high-protein Indian meal delivery service in the Toronto GTA. At one point, Meta cited 'forms collecting data' as a violation, on a campaign running Meta's **own** lead generation forms, which exist specifically to collect data." },
      { type: 'p', text: "CPL, which had been running at **2–3 CAD**, climbed to 4–5. Then 8–9. This is not a story about a campaign that failed. It's a field record of exactly what we did, why it worked, and what any business running lead gen ads should know." },
      { type: 'heading', text: "How Meta's automated review system actually works" },
      { type: 'p', text: "Meta's ad review combines automated machine review and human review. For most ad sets, the machine handles it first." },
      { type: 'p', text: "The automated system doesn't read **intent**. It reads **signals**: specific combinations of creative elements, form field types, question phrasing, and account history that it has been trained to flag as policy-adjacent. A lead form asking about 'health goals' may trigger a health-data flag. An ad mentioning 'weight loss' may trigger a body image violation. Neither is your intent. Both cause rejections." },
      { type: 'highlight', label: 'Key principle', text: "You cannot argue with a pattern-matching system. You can only change the pattern." },
      { type: 'heading', text: "What we changed and in what order" },
      { type: 'subheading', text: "Phase 1: Challenge and escalate (Weeks 1–2)" },
      { type: 'p', text: "We filed appeals, escalated to Meta Business Support, requested human review, and explained the context. Result: rejections upheld, no actionable feedback. This phase is necessary to exhaust. It occasionally resolves false positives. In this case, it didn't. But it documented that the appeals route was exhausted." },
      { type: 'subheading', text: "Phase 2: Isolate the trigger (Weeks 3–4)" },
      { type: 'p', text: "Rather than rebuilding everything at once, we ran a diagnostic: stripping ads to single variables and re-submitting. The key signal: a new ad account with identical creative setup was approved on first submission. The rejection pattern was **partially account-level**, not just creative-level. Accumulated rejection history was being used as a prior signal for future reviews." },
      { type: 'subheading', text: "Phase 3: Structural rebuild (Weeks 4–6)" },
      { type: 'steps', items: [
        { n: '01', title: 'Fresh campaign architecture', body: 'New campaign structures with clean account signals, not duplicates of flagged ad sets.' },
        { n: '02', title: 'Rewritten form questions', body: 'Same qualifying intent, different surface language. Health goal → Wellness objective. Dietary restriction → Food preference.' },
        { n: '03', title: 'New source creative', body: 'Rebuilt from original footage, not edited versions of rejected assets. The machine remembers creative fingerprints.' },
        { n: '04', title: 'Sequenced submission', body: 'Fewer ads submitted simultaneously. Concentrated review volume slows the human review queue.' },
        { n: '05', title: 'Creative bank pre-built', body: '8–10 creatives shortlisted from 20–25 candidates, mapped against 15+ audience segments before launch.' },
      ]},
      { type: 'whatsapp', src: '/assets/pp-case/pp-wa-sep30.jpeg',
        caption: '30 September 2025 · The rebuild promise: new campaign structure ready after multiple late nights' },
      { type: 'heading', text: "3 October 2025: the comeback" },
      { type: 'metrics', items: [
        { num: '33', label: 'Leads in 12 hours', sub: '3 October 2025 · campaign relaunch' },
        { num: '$1.28', label: 'Cost per lead', sub: '60% below pre-crisis average' },
        { num: '700', label: 'Leads in 10 days', sub: 'At $1.13–1.50 CPL · scaled to 70–80/day' },
      ]},
      { type: 'screenshot', src: '/assets/pp-case/pp-ads-comeback.png', variant: 'ads',
        caption: 'Meta Ads Manager · BOFU Lead Form campaign · 722 leads at $1.13 CPL · October 2025',
        alt: 'Meta Ads Manager dashboard showing 722 leads at $1.13 cost per lead for Protein Pals October comeback campaign' },
      { type: 'pullquote', text: "Crazy !!", attribution: "Rohan, Co-founder, Protein Pals · 3 October 2025" },
      { type: 'heading', text: "What the rejection crisis taught us" },
      { type: 'steps', items: [
        { n: '01', title: 'Appeal early, rebuild fast', body: 'Don\'t spend more than two weeks on appeals before starting the diagnostic phase.' },
        { n: '02', title: 'Isolate before rebuilding', body: 'Testing variables individually costs time but prevents you from changing everything and not knowing what fixed it.' },
        { n: '03', title: 'Account history matters', body: 'A clean account reviews faster. If a primary account is deep in a cycle, a parallel clean account can resume delivery while it recovers.' },
        { n: '04', title: 'Rephrase, don\'t remove', body: 'Qualifying questions can almost always be rephrased to achieve the same intent without triggering automated flags.' },
        { n: '05', title: 'The creative bank matters most at rebuild', body: 'Having 20–25 creative assets available when the rebuild launches is the difference between a two-week comeback and a six-week one.' },
      ]},
      { type: 'faq', items: [
        { q: 'Why does Meta reject lead generation ads?', a: 'Meta rejects lead generation ads most commonly for: health or personal attribute queries in form questions that pattern-match to restricted data categories (e.g., questions about "health goals" or "weight" may trigger a health-data flag), form field language that resembles restricted personal data collection, accumulated rejection history on an account that increases automated scrutiny, and creative elements containing text or visuals that trigger automated policy flags. The automated review system reads patterns, not intent.' },
        { q: 'How do I fix a rejected Meta ad for lead generation?', a: 'To fix rejected Meta lead gen ads: (1) file appeals and request human review, then exhaust that path within 1-2 weeks, (2) run a diagnostic by stripping ads to single variables and resubmitting individually to identify the specific trigger, (3) rephrase qualifying questions using neutral language (for example, "wellness objective" instead of "health goal", "food preference" instead of "dietary restriction"), (4) rebuild from fresh creative source footage rather than editing rejected assets since Meta\'s system retains creative fingerprints, and (5) if the account has deep rejection history, use a clean parallel account while the primary account recovers.' },
        { q: 'Does Meta ad rejection history affect future campaigns?', a: 'Yes. Accumulated rejection history on an ad account is weighted as a prior signal that increases automated scrutiny on future submissions from that account. This explains why identical creative approved on a fresh account may be flagged on a rejection-heavy account. Managing account health proactively by avoiding policy-adjacent content, not over-submitting simultaneously, and using clean campaign architecture reduces long-term review risk.' },
      ] },
      { type: 'cta-inline', text: "See the full story: crisis, rebuild, and the October comeback.", label: "Read the Protein Pals case study", target: 'case' },
    ],
    cta: 'Book a system audit', ctaTarget: 'apply',
    related: ['conversion-api-meta-crm-loop', 'agency-client-communication-crisis'],
  },

  /* 09: Agency comms during crisis */
  {
    id: 'agency-client-communication-crisis',
    num: '09', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '6 min', tag: 'Partnership',
    title: "What a real agency-client relationship looks like when the numbers go bad.",
    subtitle: "We didn't send a report. We sent a rebuild plan and a promise.",
    seoTitle: "What Good Agency-Client Communication Looks Like When Results Drop | Daee Media",
    seoDesc: "When Meta started rejecting every ad we ran, we didn't send a report. We sent a rebuild plan. Here's what transparent agency communication looks like and why it kept the engagement alive.",
    ogTitle: "What a real agency-client relationship looks like when the numbers go bad.",
    ogDesc: "Most agencies go quiet when performance drops. Here's what we sent Protein Pals at 9:32 AM on September 30th. And why it matters.",
    keywords: "agency client communication UK USA Australia, how to handle bad results marketing agency, agency transparency performance marketing, what good marketing agency looks like, how to evaluate a marketing agency, agency partner vs vendor, marketing agency accountability, honest marketing agency service business",
    excerpt: "There's a version of agency-client communication most businesses have experienced: monthly reports, benchmarked metrics, a slide that says 'CPL increased due to market conditions,' and a recommended next step that requires more budget. This is not transparency. This is documentation with the hard parts softened.",
    body: [
      { type: 'p', text: "There's a version of agency-client communication that most businesses have experienced: monthly reports delivered on schedule, metrics benchmarked against previous periods, a slide that says 'CPL increased due to market conditions,' and a recommended next step that requires more budget." },
      { type: 'p', text: "This is not transparency. It's documentation with the hard parts softened." },
      { type: 'heading', text: "The situation: six weeks of Meta rejections, CPL at $9" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. Daee Media launched paid campaigns in June 2025. The first month produced 45 new subscriptions. UGC creative dropped CPL to 2–3 CAD. The results were compounding. Then Meta started rejecting the ads." },
      { type: 'p', text: "August into September, the rejection cycle deepened. CPL climbed from 2–3 CAD to 4–5. Then 8–9. Volume dropped. The founders were watching a dashboard that had looked excellent two months earlier now produce nothing actionable." },
      { type: 'heading', text: "Two paths available" },
      { type: 'highlight', label: 'The choice', text: "Path A: Send a report. Document the CPL spike. Attribute it to platform volatility. Recommend increased budget to maintain volume at the higher CPL. Schedule the next check-in.\n\nPath B: Be honest, show the work, make a specific promise." },
      { type: 'heading', text: "What we sent at 9:32 AM on September 30th" },
      { type: 'whatsapp', src: '/assets/pp-case/pp-wa-sep30.jpeg',
        caption: '30 September 2025 · The message that preceded the $1.28 comeback' },
      { type: 'p', text: "Not a deck. Not a report. A direct message in the group chat. It acknowledged the slump directly. It showed specific work done: 8-10 creatives shortlisted from 20-25, 15+ audience segments mapped. It made a bounded, specific ask: **24 hours and nothing more**. It made an unconditional promise: a comeback with a bang. It closed with: *'Can't wait to see your phones buzzing with CRM and Shopify notifications. Godspeed.'*" },
      { type: 'heading', text: "Five things that message contained that most agency communication doesn't" },
      { type: 'steps', items: [
        { n: '01', title: 'Direct acknowledgement', body: '"A bit of a slump." Not platform volatility, not competitive conditions. A slump. Named clearly.' },
        { n: '02', title: 'Evidence of specific work done', body: 'Not "we\'re working on it." Specific: 8–10 creatives from 20–25, 15+ audiences mapped. The client could see the nights were real.' },
        { n: '03', title: 'A bounded, concrete ask', body: '"24 hours and nothing more." Not "in the coming weeks." A specific timeline with an expected outcome.' },
        { n: '04', title: 'An accountable promise', body: '"We promise to make a comeback with a bang for sure." Written. Permanent. In a client group chat. Consequences if broken.' },
        { n: '05', title: 'A specific vision of success', body: '"Your phones buzzing with CRM and Shopify notifications." Not \'great results\'. Their phones. Buzzing. Specific.' },
      ]},
      { type: 'heading', text: "Why this kept the engagement going" },
      { type: 'p', text: "Protein Pals stayed with Daee Media through six weeks of underperformance because the communication had established a pattern. Every update was honest, specific, and oriented toward the business outcome. The founders knew that 'we're rebuilding this' was not deflection. It was a process they'd already seen work." },
      { type: 'p', text: "Trust is not built in the hard moments. It's **spent** in the hard moments and built in all the moments before. The September 30th message spent trust correctly. It didn't hide. It showed up." },
      { type: 'cta-inline', text: "See the full Protein Pals engagement, including what the October comeback produced.", label: "Read the case study", target: 'case' },
    ],
    cta: 'Work with a partner, not a vendor', ctaTarget: 'apply',
    related: ['meta-ad-rejection-fix', 'godspeed-client-communication'],
  },

  /* 10: Godspeed */
  {
    id: 'godspeed-client-communication',
    num: '10', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '7 min', tag: 'Partnership',
    title: '"Godspeed."',
    subtitle: "What to say to a client when the results have been bad.",
    seoTitle: "How to Write Client Communication When Performance Has Dropped | Daee Media",
    seoDesc: "One message, sent at 9:32 AM after six weeks of Meta rejections, kept a 10-month client engagement intact. Here's why it worked, sentence by sentence.",
    ogTitle: '"Godspeed." What to say to a client when the results have been bad.',
    ogDesc: "Here's the September 30th message that preceded a $1.28 CPL comeback, and a line-by-line breakdown of why the writing mattered as much as the results.",
    keywords: "agency client communication UK USA Australia UAE, how to retain clients during bad results marketing, agency communication under pressure, what separates good marketing agencies, client trust marketing agency, honest agency update email, agency partner relationship service business",
    excerpt: "Every agency relationship eventually reaches a hard moment. Performance drops. The platform changes. A campaign that worked stops working. What happens next, and what the agency says next, determines whether the engagement survives.",
    body: [
      { type: 'p', text: "Every agency relationship eventually reaches a hard moment." },
      { type: 'p', text: "Performance drops. The platform changes. A campaign that worked stops working. The founder opens the dashboard and the numbers are going the wrong direction." },
      { type: 'p', text: "What happens next, and what the agency **says** next, determines whether the engagement survives." },
      { type: 'p', text: "This is a line-by-line reading of a message sent at 9:32 AM on September 30th, 2025, after six weeks of Meta rejecting Protein Pals' lead generation ads, CPL at 8-9 CAD, and multiple nights of rebuilding campaigns from scratch." },
      { type: 'heading', text: "The message, in full" },
      { type: 'highlight', label: 'September 30, 2025 · 9:32 AM', text: "Hello team! How are you all?\n\nThe last few days have been a bit of a slump for our lead gen, although we were generating leads but not at the pace and volume that we got used to before.\n\nSat a few nights back to back to figure out long withstanding campaigns with shortlisting 8–10 creatives from the pool of 20–25 and 15+ audiences along with figuring out what worked in the past and how we can smartly take it ahead from here.\n\nTeam Daee Media is nothing but grateful for your patience and we promise to make a comeback with a bang for sure.\n\nWe are extremely positive with our strategy now and would need your support and patience for another 24 hours and nothing more.\n\nCan't wait to see your phones buzzing with CRM and Shopify notifications.\n\nGodspeed ✨\nMohammed Saad Shaikh — Your Partner at Daee Media" },
      { type: 'heading', text: "Line by line: why each element does work" },
      { type: 'subheading', text: '"Hello team! How are you all?"' },
      { type: 'p', text: "The opener is human, not professional. In a moment where the instinct is to lead with defence or data, this message opens with a greeting that treats the founders as people. The tone is set before the hard content arrives: we are still in a normal relationship, not a crisis meeting." },
      { type: 'subheading', text: '"A bit of a slump"' },
      { type: 'p', text: "Direct, honest, and precise. Names the problem without catastrophising. The qualifier, 'we were generating leads,' is not spin. It's accurate. Volume had dropped; it hadn't stopped. Both parties know what good looked like. This sentence acknowledges they're not there." },
      { type: 'subheading', text: '"Sat a few nights back to back... shortlisting 8–10 creatives from the pool of 20–25"' },
      { type: 'p', text: "This is the most important sentence. Not because of what it says, but because of what it **proves**: work happened before this message was sent. The message isn't asking for patience before doing the work. It's reporting on work already done. The specificity matters enormously: 8-10 from 20-25. Not 'we've been working on creatives.' A specific action, a specific number. The client can visualise the nights." },
      { type: 'subheading', text: '"24 hours and nothing more"' },
      { type: 'p', text: "Bounded. Specific. The opposite of 'in the coming weeks, we anticipate.' The client knows exactly when to expect an update. Short enough to feel credible. Long enough to be achievable. This sentence alone reduces anxiety more than any data dashboard." },
      { type: 'subheading', text: '"We promise to make a comeback with a bang for sure"' },
      { type: 'p', text: "This is a high-stakes sentence to write. If the comeback doesn't come, the promise is broken. Writing it, in a permanent message, in a client group chat, is a commitment device. It creates accountability that motivates delivery. Clients recognise it as one." },
      { type: 'subheading', text: '"Godspeed ✨ — Your Partner at Daee Media"' },
      { type: 'p', text: "Godspeed is not a corporate word. It's the word you use when something important is about to happen, when you're sending someone into something that requires everything they have. 'Your Partner,' not Account Manager, not the agency. One word that reframes the entire relationship." },
      { type: 'heading', text: "What happened four days later" },
      { type: 'metrics', items: [
        { num: '33', label: 'Leads in 12 hours', sub: '3 October 2025' },
        { num: '$1.28', label: 'CPL at relaunch', sub: 'Down from $9 in September' },
        { num: '10 months', label: 'Total engagement', sub: 'May 2025 – March 2026' },
      ]},
      { type: 'p', text: "The rebuilt campaigns launched on October 3rd. Rohan's response in the group: *'Crazy !!'* By October 19th, demand had exceeded the kitchen's capacity and he asked to pause the ads." },
      { type: 'p', text: "The September 30th message didn't produce the $1.28 CPL. The rebuilt campaigns did. But the message is why the rebuilt campaigns had the chance to run, because the client was still there to see them." },
      { type: 'p', text: "**How you communicate in a bad week determines whether the good ones are still yours to deliver.**" },
      { type: 'cta-inline', text: "Read the full Protein Pals engagement: 1,942 leads, $1.13 CPL, and the 1:53 AM message that proved it worked.", label: "Read the case study", target: 'case' },
    ],
    cta: 'Work with a partner, not a vendor', ctaTarget: 'apply',
    related: ['agency-client-communication-crisis', 'meta-ad-rejection-fix'],
  },

  /* ════════════════════════════════════════════════════
     TIER 2 (11-17)
  ════════════════════════════════════════════════════ */

  /* 11: CPL Feedback Loop */
  {
    id: 'cpl-feedback-loop-meta-crm',
    num: '11', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '6 min', tag: 'Infrastructure',
    title: "Why your cost per lead should get cheaper every month.",
    subtitle: "And the three-node loop that makes it happen.",
    seoTitle: "Why CPL Drops Over Time With a CRM-Meta Feedback Loop | Daee Media",
    seoDesc: "Most Meta campaigns plateau or get more expensive. Here's the exact three-node loop that dropped Protein Pals' CPL from $3.50 to $1.13 over four months, and why it compounds automatically.",
    ogTitle: "Why your cost per lead should get cheaper every month.",
    ogDesc: "Every unrecorded conversion is wasted intelligence. Here's the feedback loop that made the algorithm teach itself what a Protein Pals subscriber looks like.",
    keywords: "CPL reduction Meta ads UK USA Australia UAE, why cost per lead increases Meta ads, Meta ads feedback loop CRM, how to lower cost per lead Facebook ads, CRM Conversion API loop, Meta algorithm learning service business, lead generation cost optimisation globally",
    excerpt: "Most Meta campaigns get more expensive over time, not less. The algorithm optimises toward what it measures. If it only measures form fills, it finds people who fill forms. If it measures actual subscribers, it finds actual subscribers. The difference in outcome is not marginal. It is the difference between $3.50 and $1.13.",
    body: [
      { type: 'p', text: "Most Meta campaigns get more expensive over time, not less." },
      { type: 'p', text: "The algorithm optimises toward what it measures. If the only signal you give it is a form fill, it finds people who fill forms. Not people who buy. Not people who subscribe. People who complete forms. These are not the same population." },
      { type: 'p', text: "If you give it actual purchase and subscription outcomes, it finds people who purchase and subscribe. The difference in cost per lead is not marginal. For Protein Pals, it was the difference between $3.50 and $1.13." },
      { type: 'heading', text: "The three-node loop" },
      { type: 'steps', items: [
        { n: '01', title: 'Meta shows the ad', body: 'Prospect sees an Instagram or Facebook placement. They tap the native lead form. Two taps. Done. No redirect, no landing page. The lead is captured inside the platform.' },
        { n: '02', title: 'CRM records the outcome', body: 'The lead enters Zoho, passes through ManyChat qualification, and the founder calls. Then the founder updates the stage: closed-won, contacted, junk. That stage update is the signal.' },
        { n: '03', title: 'Signal travels back to Meta', body: 'LeadChain routes the CRM stage change back to Meta as a Conversion API event. Meta learns: this profile type converted. Or: this profile type was junk. The next impression goes to a sharper audience.' },
      ]},
      { type: 'p', text: "The loop runs automatically after setup. Every outcome teaches the algorithm. Every week it has more signal. Every week the targeting gets more precise." },
      { type: 'heading', text: "What this looked like in numbers for Protein Pals" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. Daee Media built their full acquisition stack from scratch in May 2025: no prior ads, no CRM, no automation. The Conversion API was connected from day one, routing CRM outcomes back to Meta as each lead progressed through the pipeline." },
      { type: 'metrics', items: [
        { num: '$3.50', label: 'Launch CPL', sub: 'June 2025 · first campaigns' },
        { num: '$2.13', label: 'Month 2 CPL', sub: 'Algorithm learning on 45+ converters' },
        { num: '$1.13', label: 'Peak CPL', sub: 'October 2025 · 4 months of signal' },
      ]},
      { type: 'p', text: "The October CPL was not a creative breakthrough. The creative that ran in October was strong, but it had run before. The difference was that the algorithm had four months of outcome data behind it. It knew, with increasing precision, what a Protein Pals subscriber looked like. It was not finding leads anymore. It was finding buyers." },
      { type: 'screenshot', src: '/assets/pp-case/pp-leadchain.png', variant: 'capi',
        caption: 'LeadChain · CAPI events routing Zoho CRM stage updates back to Meta Ads in real time',
        alt: 'LeadChain dashboard showing Conversion API events firing from Zoho CRM to Meta for Protein Pals' },
      { type: 'heading', text: "Why most businesses never build this" },
      { type: 'p', text: "The setup requires CRM configuration, event mapping, a bridge tool like LeadChain or Zapier, and ongoing QA to verify events are firing and deduplicating correctly. There is no dashboard widget that says 'the loop is working.' The evidence appears six to eight weeks later in the CPL trend." },
      { type: 'p', text: "Most agencies skip it because the client cannot see the immediate output. The client sees the CPL today. They do not see that today's CPL is four months of signal compounding. When the agency skips it, the client pays $3.50 for leads for as long as the campaign runs." },
      { type: 'highlight', label: 'The principle', text: "The algorithm is not set-and-forget. It is a model that updates on every signal you give it. Withhold the outcome signals and it stays blind. Feed it outcome signals and it gets smarter. There is no shortcut to four months of clean data, but there is also no substitute for it." },
      { type: 'cta-inline', text: "See the full system that ran this loop across 1,942 leads.", label: "Read the Protein Pals case study", target: 'case' },
      { type: 'heading', text: "The minimum viable setup" },
      { type: 'steps', items: [
        { n: '01', title: 'Name your CRM stages correctly', body: 'Closed-won, junk, and contacted need to be distinct stage tags. Ambiguous stages create ambiguous signals.' },
        { n: '02', title: 'Connect a CAPI bridge', body: 'LeadChain is built specifically for CRM-to-Meta routing. Zapier handles simpler setups. Both fire server-side, bypassing browser tracking limitations.' },
        { n: '03', title: 'Verify in Events Manager', body: 'Meta Events Manager shows received events and deduplication rate. Verify before scaling spend. A misconfigured event poisons the model.' },
        { n: '04', title: 'Hold the data for 60 days before judging impact', body: 'The algorithm needs volume to recalibrate. Forty conversions is a minimum. One hundred is where the signal gets precise.' },
      ]},
    ],
    cta: 'Build the loop for your business', ctaTarget: 'apply',
    related: ['conversion-api-meta-crm-loop', 'five-questions-98-percent-qualified'],
  },

  /* 12: ManyChat Keyword Triggers */
  {
    id: 'manychat-keyword-triggers-menu-trial',
    num: '12', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '5 min', tag: 'Automation',
    title: "Two trigger words. Two buyer intents. Zero humans required.",
    subtitle: "What 'Menu' and 'Trial' actually do inside ManyChat.",
    seoTitle: "How ManyChat Keyword Triggers Work for Service Business Lead Gen | Daee Media",
    seoDesc: "Two comment trigger words routed every Protein Pals lead into distinct automation paths before a human was involved. Here's the architecture and why the entry point determined the close rate.",
    ogTitle: "Two trigger words. Two buyer intents. Zero humans required.",
    ogDesc: "One word unlocked a PDF and a qualification flow. Another booked a free trial. Both fed the same CRM. Here's how keyword-triggered ManyChat automation worked for Protein Pals.",
    keywords: "ManyChat keyword trigger automation, how to use ManyChat for lead generation UK USA Australia, ManyChat DM automation service business, Instagram DM automation lead capture, ManyChat CRM integration, Instagram comment trigger lead gen, ManyChat lead automation globally",
    excerpt: "Most businesses respond to Instagram comments manually, hours later, after the intent has cooled. A keyword trigger on a Meta ad comment opens an automation instantly, in the same app, at the moment of maximum interest. Here's what happened when we built two of them for a meal delivery subscription.",
    body: [
      { type: 'p', text: "Most businesses respond to Instagram comments manually. Someone comments 'interested,' a social media manager sees it two hours later, types a response, waits for the reply. By then the person has scrolled through forty more posts. The intent has cooled." },
      { type: 'p', text: "A ManyChat keyword trigger removes the lag entirely. When someone comments a specific word on an ad or post, an automation opens in their DMs instantly, without a human involved. The conversation begins at the exact moment of maximum interest." },
      { type: 'heading', text: "The context: two entry points, two buyer types" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. When a prospect tapped a Protein Pals ad or commented on a post, they were offered two trigger words: **'Menu'** and **'Trial'**. Each word opened a different automation path." },
      { type: 'steps', items: [
        { n: 'Menu', title: "What 'Menu' triggered", body: "A DM opened immediately with a formatted PDF: plan names, dish descriptions, macros per meal, weekly and monthly prices. Then the qualification flow began: postal code, dietary preference, health goal, work situation. The lead was in the funnel within 60 seconds of commenting. No human involved." },
        { n: 'Trial', title: "What 'Trial' triggered", body: "A different DM path. The automation confirmed interest, collected name and address for delivery, verified postal code eligibility, and scheduled a free 2-day meal drop. The lead booked a trial without speaking to a human. The founder called after the trial was delivered, not before." },
      ]},
      { type: 'p', text: "Both paths fed the same five qualification questions. Both pushed to the same Zoho CRM pipeline. But the downstream conversion rates were meaningfully different." },
      { type: 'heading', text: "Why the entry word predicted the close rate" },
      { type: 'p', text: "A 'Menu' lead had expressed **curiosity**. They wanted information before deciding. A 'Trial' lead had expressed **intent**. They had already resolved enough of the objection to commit to a delivery address." },
      { type: 'p', text: "The qualification flow was the same. The CRM entry was the same. But by the time the founder called a Trial lead, the lead had already eaten the food. The call was not about whether they wanted to subscribe. It was about which plan." },
      { type: 'pullquote', text: "The trial path didn't just convert better. It converted faster. The sales call was a formality. The product had already done the selling.", attribution: "Saad, Daee Media" },
      { type: 'whatsapp', src: '/assets/pp-case/pp-wa-launch.jpeg',
        caption: '25 June 2025 · Campaign launch day: DMs flowing from the keyword trigger automation from day one',
        alt: 'WhatsApp conversation showing early Protein Pals campaign results on launch day June 2025' },
      { type: 'heading', text: "The engagement ad phase that made the triggers work" },
      { type: 'p', text: "Before lead generation campaigns ran, Daee Media ran engagement ads with ManyChat triggers active. Cost per conversation: 0.50 CAD. Each conversation built an audience of people who had already raised their hand. They had clicked, chatted, and asked about the menu." },
      { type: 'p', text: "When lead gen campaigns launched on June 25th, they were not running cold. The retargeting pool was warm. The triggers had already done the first qualification. The CPL on day one was lower than it would have been on a cold audience because a subset of the audience had already interacted." },
      { type: 'metrics', items: [
        { num: '$0.50', label: 'Cost per conversation', sub: 'Engagement phase · pre-launch' },
        { num: '45', label: 'Closed in 15 days', sub: 'First lead gen campaign' },
        { num: '1,942', label: 'Total leads', sub: 'Jun-Nov 2025' },
      ]},
      { type: 'cta-inline', text: "See the full automation stack that ran across 1,942 leads.", label: "Read the Protein Pals case study", target: 'case' },
      { type: 'heading', text: "How to replicate this for your business" },
      { type: 'steps', items: [
        { n: '01', title: 'Identify your two buyer intent levels', body: 'Information-seeker vs ready-to-commit. Each intent level needs a different entry path and a different first automation message.' },
        { n: '02', title: 'Set trigger words on both ads and organic posts', body: 'Keyword triggers work on ad comments and organic post comments. Run engagement ads pointing to posts with triggers active to build the warm pool before lead gen launches.' },
        { n: '03', title: 'Deliver immediate value at entry', body: 'The Menu path delivered a full PDF within 60 seconds. The Trial path confirmed and booked within 90 seconds. Speed of delivery is the first trust signal.' },
        { n: '04', title: 'Route both paths to the same CRM entry', body: 'Different triggers, same CRM. The entry source is tagged so you can compare downstream conversion by trigger type and adjust emphasis accordingly.' },
      ]},
    ],
    cta: 'Build an automation stack for your funnel', ctaTarget: 'apply',
    related: ['five-questions-98-percent-qualified', 'free-trial-vs-subscribe-now'],
  },

  /* 13: 15 Audience Segments */
  {
    id: 'audience-segmentation-meta-comeback',
    num: '13', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '7 min', tag: 'Meta Ads',
    title: "We mapped 15 audience segments before running a single ad.",
    subtitle: "The $1.28 CPL was not one winning audience. It was fifteen right ones.",
    seoTitle: "How to Build Meta Ad Audience Segments That Lower CPL | Daee Media",
    seoDesc: "When the October comeback launched for Protein Pals, we didn't target 'Indian adults in Toronto.' We had 15 distinct audience segments, each matched to a specific creative. Here's the framework.",
    ogTitle: "We mapped 15 audience segments before running a single ad in October.",
    ogDesc: "Broad targeting finds leads. Segmented targeting finds buyers. Here's how 15 audience segments produced a $1.28 CPL on relaunch day.",
    keywords: "Meta ads audience segmentation UK USA Australia UAE, how to build audience segments Facebook ads, Meta targeting strategy service business, segmented ad targeting lower CPL, custom audience Meta ads, lookalike audience strategy, Meta ads comeback strategy, Facebook ads audience architecture",
    excerpt: "The most common mistake in Meta campaign setup is not the creative and not the copy. It is launching against one audience and calling it targeting. Here is what real audience architecture looks like, and what it produced on a campaign relaunch day.",
    body: [
      { type: 'p', text: "The most common Meta campaign setup looks like this: interest targeting, one saved audience, ages 25-45, relevant country. Launch. Wait. Optimise the creative if it underperforms." },
      { type: 'p', text: "The problem is structural. One audience cannot tell you anything useful. You cannot know which sub-group is converting and which is not. You cannot match a creative to a specific buyer context. You are averaging across a population instead of targeting within it." },
      { type: 'heading', text: "The context: rebuilding after six weeks of Meta rejections" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. In August and September 2025, Meta rejected their lead generation ads repeatedly, driving CPL from 2-3 CAD to 8-9 CAD. When Daee Media rebuilt the campaigns for an October relaunch, audience architecture was the foundation of the rebuild." },
      { type: 'p', text: "The rebuild did not start with creative. It started with a map: who are the distinct people in the Toronto GTA who would subscribe to a high-protein Indian meal delivery service, and what does each of them care about?" },
      { type: 'heading', text: "The 15-segment framework" },
      { type: 'steps', items: [
        { n: 'Layer 1', title: 'By geography and income profile', body: 'Vaughan, Markham, Mississauga high-density, North York corridors. Each geography has a different household income profile and a different likelihood of a discretionary meal subscription. High-income residential areas outperformed dense urban zones consistently.' },
        { n: 'Layer 2', title: 'By dietary preference', body: 'Vegetarian and non-veg were separate segments from the start. By month three, data from the qualification flow confirmed that 60-70% of paying subscribers were vegetarian. Separate segments meant the veg-specific creative could be weighted accordingly.' },
        { n: 'Layer 3', title: 'By lifestyle and profession', body: 'WFH professionals, working mothers, gym-goers, office workers. Each group has a different relationship to meal prep, a different time constraint, and a different objection to a subscription. The creative for a WFH professional is not the same as for a gym-goer.' },
        { n: 'Layer 4', title: 'By audience temperature', body: 'Cold (interest and lookalike), warm (engaged with profile or past ads), hot (past leads who had not converted). Each temperature level got different creative and a different ask. Cold audiences got awareness creative. Hot audiences got a direct trial offer.' },
      ]},
      { type: 'p', text: "Fifteen segments is not a large number when you map the matrix honestly. It is geography (four zones) times dietary preference (two) times temperature (two), with lifestyle added as a modifier. The combinations are real buyer contexts, not arbitrary divisions." },
      { type: 'heading', text: "The creative matching step" },
      { type: 'p', text: "Each segment had a creative matched to its specific context. The Vaughan WFH vegetarian segment saw a UGC video of a working professional unboxing a veg lunch plan at home. The Markham gym-goer non-veg segment saw the macro grid for the muscle plan. The hot retargeting segment saw a direct 'try it free' offer." },
      { type: 'p', text: "This is not complex ad management. It is the difference between showing the right person the right message and showing everyone the average message." },
      { type: 'screenshot', src: '/assets/pp-case/pp-ads-comeback.png', variant: 'ads',
        caption: 'Meta Ads Manager · October 2025 · 722 leads at $1.13 CPL across the segmented campaign structure',
        alt: 'Meta Ads Manager showing 722 leads at $1.13 CPL for Protein Pals October comeback campaign' },
      { type: 'metrics', items: [
        { num: '15+', label: 'Audience segments', sub: 'Mapped before October relaunch' },
        { num: '$1.28', label: 'Day 1 CPL', sub: 'October 3, 2025' },
        { num: '33', label: 'Leads in 12 hours', sub: 'Relaunch day' },
      ]},
      { type: 'cta-inline', text: "See how the full audience architecture performed across 1,942 leads.", label: "Read the Protein Pals case study", target: 'case' },
      { type: 'heading', text: "How to build this for your campaigns" },
      { type: 'steps', items: [
        { n: '01', title: 'Start with geography times one qualifier', body: 'You do not need fifteen segments on day one. Start with your delivery zones or service areas, then split by the single most predictive qualifier your product has. For Protein Pals it was dietary preference.' },
        { n: '02', title: 'Use your qualification flow data to inform the split', body: 'After 200 leads, your ManyChat or CRM data will show you which segments are converting at higher rates. Weight your ad spend toward those segments. Let the data build the media plan.' },
        { n: '03', title: 'Match one creative angle per segment', body: 'The creative does not need to be unique per segment. It needs to speak to the specific context. A different hook, a different first line, a different visual emphasis can serve a different segment without a full production.' },
        { n: '04', title: 'Build hot retargeting as a separate campaign from day one', body: 'Every lead that enters the funnel but does not convert in 30 days is a warm retargeting audience. These leads need a different message than cold traffic. Segment them from the start so you have the audience ready when the volume is sufficient.' },
      ]},
    ],
    cta: 'Build a segmented campaign for your business', ctaTarget: 'apply',
    related: ['meta-ad-rejection-fix', 'conversion-api-meta-crm-loop'],
  },

  /* 14: CRM Pipeline Stage Vocabulary */
  {
    id: 'crm-pipeline-stages-revenue',
    num: '14', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '5 min', tag: 'CRM',
    title: "The four CRM stages that tell you where revenue is hiding.",
    subtitle: "Your pipeline is not a database. It is a diagnostic.",
    seoTitle: "How to Set Up CRM Pipeline Stages for Service Business Sales | Daee Media",
    seoDesc: "Naming your CRM stages wrong means losing revenue you can't see. Here's the four-stage vocabulary Protein Pals used across 1,942 leads and what each stage revealed about the pipeline.",
    ogTitle: "The four CRM stages that tell you where revenue is hiding.",
    ogDesc: "Most CRMs are filing systems. Here's how to turn your pipeline stages into a diagnostic that shows you exactly where leads are stalling and why.",
    keywords: "CRM pipeline stages service business UK USA Australia, how to set up CRM sales pipeline, Zoho CRM pipeline stages, CRM stage names best practices, service business CRM setup, lead management pipeline, sales pipeline for service business, CRM for high-ticket services",
    excerpt: "Most businesses have a CRM. Most of them use it as a filing system: a place to store names and numbers. The pipeline stages exist, but they are never read diagnostically. Here is how four stage names across 1,942 leads surfaced revenue that would otherwise have stayed invisible.",
    body: [
      { type: 'p', text: "Most businesses have a CRM. Most of them use it as a filing system." },
      { type: 'p', text: "Names go in. Numbers go in. Sometimes notes. But the pipeline stages are rarely used to answer the question they exist to answer: where are leads stalling, and why?" },
      { type: 'heading', text: "The context: 1,942 leads, four stage tags" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. Daee Media managed their Zoho CRM pipeline from June through November 2025. Every lead that entered the pipeline was tagged with one of four stages." },
      { type: 'steps', items: [
        { n: '01', title: 'Qualified', body: 'Lead has passed the ManyChat flow. Postal code is in the delivery zone. Contact details are confirmed. The lead is real and reachable. This stage means: the founder should call.' },
        { n: '02', title: 'Contacted', body: 'Founder has spoken to the lead. Conversation happened. No commitment yet. This is where the diagnostic work begins: a lead sitting here for more than 48 hours means something in the pitch needs attention, or a follow-up sequence is missing.' },
        { n: '03', title: 'Closed Won', body: 'Subscription started. This stage fires a Conversion API event back to Meta immediately: find more people who look like this. The closed-won pool is the most valuable targeting signal in the system.' },
        { n: '04', title: 'Junk', body: 'Wrong geography, fake number, or no intent. This stage also fires a negative CAPI signal: stop finding people who look like this. The 26 junk leads out of 1,942 also built the exclusion audience.' },
      ]},
      { type: 'screenshot', src: '/assets/pp-case/pp-crm-pipeline.png', variant: 'crm',
        caption: 'Zoho CRM · Protein Pals pipeline · Jun-Nov 2025 · four stage tags across 1,942 leads',
        alt: 'Zoho CRM pipeline view showing Protein Pals lead stages across the full engagement' },
      { type: 'heading', text: "How stages become diagnostics" },
      { type: 'p', text: "The stage distribution tells you where to look. If **Qualified** is growing faster than **Contacted**, the bottleneck is the sales capacity: the founder is not calling fast enough, or the call list is not prioritised correctly." },
      { type: 'p', text: "If **Contacted** is growing faster than **Closed Won**, the bottleneck is the pitch: the conversation is happening but not converting. That points to objection handling, not lead quality." },
      { type: 'p', text: "If **Junk** is more than 3-4% of total pipeline, the qualification flow has a gap: leads are passing the automation filter that should not be passing." },
      { type: 'highlight', label: 'The Protein Pals numbers', text: "1,942 total leads. 26 junk (1.33%). 420 still in pipeline at campaign pause. The stage distribution showed the bottleneck was not lead quality. It was kitchen capacity: the business could not service the qualified leads fast enough to justify continuing at volume." },
      { type: 'p', text: "That is the kind of business intelligence that saves founders from scaling into a capacity crisis. The CRM stages surfaced it." },
      { type: 'heading', text: "What most businesses name their stages instead" },
      { type: 'p', text: "New. In Progress. Follow Up. Closed." },
      { type: 'p', text: "'New' tells you when a lead arrived. It tells you nothing about what it is. 'In Progress' is a holding pen. It means someone looked at it once. 'Follow Up' creates a to-do, not a diagnosis. 'Closed' conflates won and lost." },
      { type: 'p', text: "Stage names shape behaviour. A founder with a 'Qualified' tag knows exactly what action to take next. A founder with an 'In Progress' tag does not." },
      { type: 'cta-inline', text: "See how the CRM stage system worked across the full Protein Pals engagement.", label: "Read the case study", target: 'case' },
    ],
    cta: 'Build a CRM that earns you revenue', ctaTarget: 'apply',
    related: ['five-questions-98-percent-qualified', 'conversion-api-meta-crm-loop'],
  },

  /* 15: Vegetarian Data Insight */
  {
    id: 'crm-data-brand-strategy-vegetarian',
    num: '15', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '5 min', tag: 'Data',
    title: "The data point that changed an entire brand's menu strategy.",
    subtitle: "60-70% of paying subscribers were vegetarian. The brand had no idea.",
    seoTitle: "How Lead Generation Data Revealed a Brand's Wrong Assumptions | Daee Media",
    seoDesc: "Protein Pals built their brand around gym culture and non-veg protein. One ManyChat qualification question revealed that 60-70% of paying subscribers preferred vegetarian. Here's what changed.",
    ogTitle: "The data point that changed an entire brand's menu strategy.",
    ogDesc: "Your lead generation system doesn't just generate leads. It generates market intelligence your intuition will never surface. Here's what one question revealed.",
    keywords: "using CRM data for marketing strategy UK USA Australia, customer data insights service business marketing, how to use lead qualification data, ManyChat data analysis, CRM data brand strategy, customer preference data Meta ads, data-driven marketing service business",
    excerpt: "Most brands think they know their customer. They have an intuition built from product decisions, early buyers, and the aesthetic they chose for the Instagram grid. Then a lead generation system starts producing real data. The gap between the intuition and the data is where the real customer lives.",
    body: [
      { type: 'p', text: "Most brands think they know their customer." },
      { type: 'p', text: "They have an intuition built from early buyers, product decisions, and the aesthetic they chose for the Instagram grid. The intuition feels accurate because it produced the first sales. It does not mean it reflects the majority." },
      { type: 'heading', text: "The brand assumption" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. Their brand identity was built around gym culture and high-performance fitness: bold packaging, high-protein macros, non-veg meal photography. The implicit assumption was that the core customer was a fitness-active, non-vegetarian young professional." },
      { type: 'p', text: "It was a reasonable assumption. It was also wrong for the majority of paying subscribers." },
      { type: 'heading', text: "The qualification question that surfaced the data" },
      { type: 'p', text: "The second question in the Protein Pals ManyChat qualification flow was: dietary preference, veg or non-veg?" },
      { type: 'p', text: "The purpose was to route the lead to the correct follow-up flow and pre-tag the CRM record. The answer was expected to split roughly 40-60 in favour of non-veg, consistent with the brand's gym-culture positioning." },
      { type: 'p', text: "After six months of data across nearly 1,942 leads, the actual split was: **60-70% of converting subscribers preferred vegetarian meals**." },
      { type: 'highlight', label: 'What this meant in practice', text: "The majority customer was not a gym-goer buying whey-protein-level macros in chicken and paneer. The majority customer was a health-conscious vegetarian professional looking for clean, high-protein veg meals with zero meal-prep overhead. Two completely different people. One brand. One set of ads. One creative direction." },
      { type: 'heading', text: "What changed after the data landed" },
      { type: 'steps', items: [
        { n: '01', title: 'Menu expansion', body: 'The veg plan tier was expanded and given more visibility. New dishes were developed to meet the actual demand profile rather than the assumed one.' },
        { n: '02', title: 'Creative re-brief', body: 'UGC creators were re-briefed to feature vegetarian meals prominently. The gym-culture aesthetic remained but was balanced with lifestyle content aimed at working professionals and family households.' },
        { n: '03', title: 'Audience reweighting', body: 'The vegetarian segment in the Meta campaign structure received proportionally more spend. The creative matched to that segment outperformed non-veg creative in the same geography.' },
        { n: '04', title: 'Instagram content pivot', body: 'The pinned carousel posts were reordered to lead with the veg plan. Organic posts began featuring vegetarian dishes at a higher frequency.' },
      ]},
      { type: 'screenshot', src: '/assets/pp-case/pp-crm-junk.png', variant: 'crm',
        caption: 'Zoho CRM · qualification data across 1,942 leads: dietary preference, geography, and work situation tagged per record',
        alt: 'Zoho CRM showing lead qualification data including dietary preference tags for Protein Pals leads' },
      { type: 'p', text: "The qualification question was not market research. It was a routing mechanism. But the aggregate of routing data, at scale, is market research. The brand had run an assumption for two years. Six months of lead qualification data corrected it." },
      { type: 'pullquote', text: "Your CRM is the most honest market research tool you have. It doesn't tell you what people say they want. It tells you what they're willing to pay for.", attribution: "Saad, Daee Media" },
      { type: 'cta-inline', text: "See the full qualification system that generated this data across 1,942 leads.", label: "Read the Protein Pals case study", target: 'case' },
    ],
    cta: 'Build a system that generates market intelligence', ctaTarget: 'apply',
    related: ['five-questions-98-percent-qualified', 'instagram-pinned-post-offer-visibility'],
  },

  /* 16: No Landing Page */
  {
    id: 'meta-lead-form-no-landing-page',
    num: '16', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '5 min', tag: 'Meta Ads',
    title: "Why we killed the landing page.",
    subtitle: "Native Meta forms vs. off-platform redirects: what the data showed.",
    seoTitle: "Meta Native Lead Forms vs Landing Pages: Which Converts Better | Daee Media",
    seoDesc: "For cold mobile traffic in a high-intent local service, a landing page redirect loses leads before you capture them. Here's why Protein Pals ran exclusively on native Meta lead forms and what it produced.",
    ogTitle: "Why we killed the landing page for Protein Pals.",
    ogDesc: "Every redirect is a leak. Here's what native Meta lead forms produced when used for a local service subscription with a mobile-first audience.",
    keywords: "Meta lead form vs landing page UK USA Australia UAE, native lead generation Meta ads, should I use landing page or lead form Facebook ads, Meta instant forms conversion rate, mobile landing page drop off Meta ads, Meta lead ads no website service business, lead gen form strategy Meta advertising",
    excerpt: "The conventional advice for service businesses is to build a landing page. More copy, more trust signals, more conversion opportunity. For a specific category of offer and audience temperature, this advice loses you leads before you even capture them.",
    body: [
      { type: 'p', text: "The conventional advice is: build a landing page." },
      { type: 'p', text: "More copy space. More trust signals. A dedicated URL you can optimise over time. Control over the experience. Good reasons. And for the right audience temperature and offer type, correct." },
      { type: 'p', text: "For cold mobile traffic, from a community with low prior brand familiarity, on a subscription product requiring trust before the first transaction, a landing page redirect is a leak. Every additional step between interest and form completion is a drop-off. The question is not whether landing pages can work. It is whether they are the right tool for this specific audience at this specific moment." },
      { type: 'heading', text: "The context: cold Indian diaspora audience on mobile, Toronto GTA" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. Their target audience was South Asian working professionals and families in Vaughan, Markham, and Mississauga. This audience was primarily on mobile, scrolling Instagram and Facebook between tasks. Prior brand awareness was near zero when campaigns launched in June 2025." },
      { type: 'p', text: "A redirect to an external landing page at that moment asks a cold user to: leave the app, wait for a page to load on mobile data, read new copy in a new context, then commit to submitting personal information on an unfamiliar website. Each step is an exit point." },
      { type: 'heading', text: "What native Meta lead forms remove" },
      { type: 'steps', items: [
        { n: '01', title: 'The redirect itself', body: 'The form loads inside the Meta app. The user never leaves the platform. No browser switch. No load time. No lost context.' },
        { n: '02', title: 'Manual form entry', body: "Meta pre-fills the user's name and email from their profile data. The lead completes a form with fewer keystrokes than a landing page would require." },
        { n: '03', title: 'The trust gap from an unknown domain', body: 'A first-time visitor to an unfamiliar website has no prior signal that the business is legitimate. Inside Meta, the ad account and business page provide that signal. The context is familiar.' },
        { n: '04', title: 'The mobile loading variable', body: 'A poorly optimised landing page on 4G in a moving vehicle loses 40-60% of clicks before the page finishes loading. Native forms have no loading variable because they are already in the app.' },
      ]},
      { type: 'highlight', label: 'What this cost us', text: "Less copy space per interaction. The native form has limited fields and limited creative real estate. For a product that benefits from longer explanation, that is a real constraint. We addressed it through the ManyChat qualification flow: the form captured the contact, the ManyChat conversation delivered the depth." },
      { type: 'p', text: "The form captured the lead in two taps. The ManyChat flow, triggered automatically after form submission, delivered the PDF, the plan details, the macro breakdowns, and the qualification questions. The function of a landing page was distributed across two steps rather than compressed into one." },
      { type: 'screenshot', src: '/assets/pp-case/pp-ads-comeback.png', variant: 'ads',
        caption: 'Meta Ads Manager · native lead form campaign · 722 leads at $1.13 CPL · October 2025',
        alt: 'Meta Ads Manager showing 722 leads at $1.13 CPL using native lead forms for Protein Pals' },
      { type: 'metrics', items: [
        { num: '1,942', label: 'Total leads captured', sub: 'Native form · Jun-Nov 2025' },
        { num: '$1.13', label: 'Lowest CPL achieved', sub: 'October 2025' },
        { num: '1.33%', label: 'Junk rate', sub: 'Of all captured leads' },
      ]},
      { type: 'heading', text: "When a landing page is still the right call" },
      { type: 'p', text: "Native forms work best for: cold mobile audiences with low prior brand familiarity, high-intent local services with a short consideration cycle, and markets where the form is a qualifying step rather than the final commitment." },
      { type: 'p', text: "A landing page becomes the right call when: the offer requires significant education before commitment, the buyer is desktop-first, or retargeting a warm audience that already knows the brand and needs more detail before converting." },
      { type: 'p', text: "The question is not which format is generically better. It is which format matches the audience temperature, device behaviour, and offer complexity of the specific campaign." },
      { type: 'cta-inline', text: "See how the native form system performed across the full Protein Pals engagement.", label: "Read the Protein Pals case study", target: 'case' },
    ],
    cta: 'Build the right funnel for your audience', ctaTarget: 'apply',
    related: ['five-questions-98-percent-qualified', 'free-trial-vs-subscribe-now'],
  },

  /* 17: Kitchen Upgrade */
  {
    id: 'demand-exceeds-capacity-campaign-success',
    num: '17', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '6 min', tag: 'Growth',
    title: "The clearest sign a campaign worked: we had to stop it.",
    subtitle: "When demand exceeds operational capacity, that is not a problem. That is the goal.",
    seoTitle: "When Marketing Works Faster Than Your Operations Can Scale | Daee Media",
    seoDesc: "In October 2025, Protein Pals paused a campaign running at $1.13 CPL because the kitchen couldn't keep up with 70-80 leads per day. Here's what that moment reveals about what campaign success actually means.",
    ogTitle: "The clearest sign a campaign worked: we had to stop it.",
    ogDesc: "Most businesses measure campaign success in ROAS. Here's a different measure: the founder called to say the kitchen couldn't keep up with the leads. That's the goal.",
    keywords: "scaling service business marketing UK USA Australia, when to pause Meta ads demand capacity, demand exceeds capacity business problem, service business scaling constraints, lead generation too many leads, too many enquiries scaling problem, Meta ads pause scale operations",
    excerpt: "Most businesses measure campaign success in cost per lead, ROAS, or subscriber count. Here is a different measure: the founder called on October 19th to say the kitchen could not keep up with the demand. The ads had to pause. That is not a campaign failure. That is the correct sequence for a product business.",
    body: [
      { type: 'p', text: "Most businesses measure campaign success in CPL, ROAS, or subscriber count. These are useful numbers. They are not the most important number." },
      { type: 'p', text: "The most important number for a product business is this: can your operations service the demand the campaign generates?" },
      { type: 'p', text: "On October 19th, 2025, Rohan from Protein Pals sent a message asking to pause the ads. Not because they were underperforming. Because the kitchen could not keep up." },
      { type: 'heading', text: "The context: 70-80 leads per day, one kitchen" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. Daee Media managed their paid acquisition from June through November 2025. The October campaign relaunched on October 3rd after a six-week Meta rejection crisis. Within 72 hours, the system was generating 70-80 leads per day at $1.13-1.50 CPL." },
      { type: 'p', text: "The production operation was running from a home kitchen. By October 19th, the volume of subscribers being onboarded was at the physical limit of what that kitchen could produce and deliver." },
      { type: 'whatsapp', src: '/assets/pp-case/pp-wa-oct19.jpeg',
        caption: '19 October 2025 · Rohan asks to pause the campaigns because production capacity is at its limit',
        alt: 'WhatsApp message from Protein Pals founder on October 19 2025 requesting campaign pause due to kitchen capacity' },
      { type: 'heading', text: "Why this is the correct sequence" },
      { type: 'p', text: "Most founders think about marketing as the bottleneck: if only we had more leads, the business would grow. The Protein Pals engagement proved that marketing was not the bottleneck. The kitchen was. And that is exactly the right problem to have." },
      { type: 'steps', items: [
        { n: '01', title: 'Prove demand before scaling infrastructure', body: 'Protein Pals did not invest in a commercial kitchen before knowing the product could generate sustained demand. The campaign proved demand first. The infrastructure investment followed, justified by evidence.' },
        { n: '02', title: 'Pause the campaign, not the business', body: 'Pausing ads when operational capacity is exhausted is not a failure state. It is a transition point. The ads pause. The kitchen upgrades. The ads restart at a higher capacity ceiling.' },
        { n: '03', title: 'The pipeline carries the revenue while the ops catch up', body: 'At pause, 420 leads were still in pipeline: contacted but not closed, or qualified but not yet reached. The business did not need new leads to stay active. It needed to work the existing pipeline while the capacity scaled.' },
      ]},
      { type: 'metrics', items: [
        { num: '240', label: 'Active subscribers', sub: 'At campaign pause · Oct 2025' },
        { num: '420', label: 'Leads still in pipeline', sub: 'Contacted or qualified · not yet closed' },
        { num: '12x', label: 'Subscriber growth', sub: 'May to October 2025' },
      ]},
      { type: 'heading', text: "What the commercial kitchen upgrade means for the next campaign" },
      { type: 'p', text: "The campaign that resumes after the kitchen upgrade will run into a completely different operational ceiling. Where the October campaign could sustain roughly 240 active subscribers before the kitchen hit capacity, the next campaign will run against a higher number. The same CPL. A larger addressable supply." },
      { type: 'p', text: "This is the correct growth sequence for a product business: generate demand, prove you can close it, identify the operational constraint, remove the constraint, repeat at scale." },
      { type: 'p', text: "The 420 leads in pipeline are not a backlog problem. They are the warm list that the next campaign does not have to generate from scratch." },
      { type: 'pullquote', text: "Marketing that works faster than your operations can scale is not a marketing failure. It is an operations opportunity. The correct response is to upgrade the operations, not throttle the marketing.", attribution: "Saad, Daee Media" },
      { type: 'cta-inline', text: "Read the full Protein Pals engagement: from 15 subscribers to 240, and why the campaign paused at the top.", label: "Read the case study", target: 'case' },
    ],
    cta: 'Build demand that scales with your operations', ctaTarget: 'apply',
    related: ['instagram-pinned-post-offer-visibility', 'godspeed-client-communication'],
  },

  /* ════════════════════════════════════════════════════
     TIER 3 (18-23)
  ════════════════════════════════════════════════════ */

  /* 18: The Creative Bank (angle 07) */
  {
    id: 'creative-bank-meta-ads-strategy',
    num: '18', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '6 min', tag: 'Creative',
    title: "We built 20 creatives before we scaled to one.",
    subtitle: "Why a creative bank is insurance, not overhead.",
    seoTitle: "Why You Need a Creative Bank Before Scaling Meta Ads | Daee Media",
    seoDesc: "When the October comeback launched for Protein Pals, we had 20-25 creative assets ready. The $1.28 CPL winner wasn't the first ad we made. It was the best match from a bank we built deliberately.",
    ogTitle: "We built 20 creatives before we scaled to one.",
    ogDesc: "The creative that ran at $1.28 CPL wasn't lucky. It was the best match from a deliberate bank of 20-25 assets. Here's why volume of creative is a strategic decision.",
    keywords: "Meta ads creative strategy UK USA Australia UAE, how many creatives for Meta ads, creative bank Facebook ads service business, UGC creative volume strategy, Meta ad creative testing, creative fatigue Meta ads, how to scale Meta ad creative, ad creative bank performance marketing",
    excerpt: "Most businesses build one ad, launch it, and optimise. When it dies, they build another. The cycle is reactive. A creative bank reverses the sequence: you build volume before you need it, so when a campaign stalls or Meta rejects an asset, you are not starting from zero.",
    body: [
      { type: 'p', text: "Most businesses build one ad, launch it, and optimise. When it dies, they build another." },
      { type: 'p', text: "The cycle is reactive. Each time a creative fatigues, there is a production gap: time to brief, time to shoot, time to edit, time to review, time to relaunch. During that gap, CPL climbs. Volume drops. The algorithm loses momentum." },
      { type: 'p', text: "A creative bank reverses the sequence. You build volume before you need it, so when a campaign stalls or Meta rejects an asset, you are not starting from zero." },
      { type: 'heading', text: "The context: rebuilding after six weeks of Meta rejections" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. In August and September 2025, Meta rejected their lead generation ads repeatedly. When Daee Media rebuilt the campaigns for the October relaunch, the creative bank was built first." },
      { type: 'p', text: "Before a single ad went live on October 3rd, there were 20-25 creative assets ready: different hooks, different formats, different spokespeople, different meal features. From that pool, 8-10 were shortlisted against the 15+ audience segments. The campaign launched with creative already matched to audience, not creative waiting to be tested." },
      { type: 'metrics', items: [
        { num: '20-25', label: 'Assets in the bank', sub: 'Built before relaunch day' },
        { num: '8-10', label: 'Shortlisted for launch', sub: 'Matched to specific segments' },
        { num: '$1.28', label: 'CPL on day one', sub: 'October 3, 2025' },
      ]},
      { type: 'heading', text: "Why the winning creative was not the obvious one" },
      { type: 'p', text: "The creative that ran at $1.28 CPL on relaunch day was not the most polished asset in the bank. It was the closest match between a real person's story and a specific audience's concern. A WFH vegetarian professional in Vaughan saw a video of someone in a similar situation opening a veg lunch plan at home." },
      { type: 'p', text: "That specificity of match is only possible when you have enough assets to choose from. One creative cannot be the closest match to fifteen different audience segments. Twenty-five assets give you the coverage to actually select." },
      { type: 'screenshot', src: '/assets/pp-case/pp-ads-comeback.png', variant: 'ads',
        caption: 'Meta Ads Manager · October 2025 · 722 leads at $1.13 CPL · built on a pre-prepared creative bank',
        alt: 'Meta Ads Manager showing the October Protein Pals comeback campaign at $1.13 CPL' },
      { type: 'heading', text: "Three functions the creative bank serves" },
      { type: 'steps', items: [
        { n: '01', title: 'Insurance against Meta rejection cycles', body: "When Meta rejects an asset, you have 19 others ready. The campaign does not pause. You swap the asset, resubmit, and maintain volume while the rejected creative goes through appeal." },
        { n: '02', title: 'Fuel for audience-creative matching', body: 'Different audience segments respond to different creative angles. Without a bank, you cannot match. You run the same ad at everyone and average the results.' },
        { n: '03', title: 'Protection against creative fatigue', body: 'A single creative fatigues in 10-21 days on a hot audience. A bank of 20-25 rotates automatically. Frequency stays manageable. CPL stays stable for longer.' },
      ]},
      { type: 'heading', text: "What goes into a creative bank for a service business" },
      { type: 'steps', items: [
        { n: '01', title: 'Founder-on-camera', body: 'Builds trust with audiences who buy on brand identity. Works best in early-funnel cold targeting where awareness is the objective.' },
        { n: '02', title: 'UGC from real customers', body: 'Outperforms branded creative for CPL because it looks like organic content. The algorithm rewards watch time, and a real person reacting to a real product holds attention differently than a pitch.' },
        { n: '03', title: 'Product-focused', body: 'Macro grids, portion sizes, packaging details. Serves the audience that is in research mode and needs specificity before committing.' },
        { n: '04', title: 'Social proof formats', body: 'Street Q&A, reaction videos, before-and-after. Reaches the audience that is convinced by third-party credibility rather than first-party claims.' },
      ]},
      { type: 'cta-inline', text: "See the creative strategy behind 1,942 leads at $1.13 CPL.", label: "Read the Protein Pals case study", target: 'case' },
    ],
    cta: 'Build a creative strategy that does not run out', ctaTarget: 'apply',
    related: ['audience-segmentation-meta-comeback', 'meta-ad-rejection-fix'],
  },

  /* 19: Offer Visibility (angle 20) */
  {
    id: 'offer-visibility-instagram-service-business',
    num: '19', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '5 min', tag: 'Organic',
    title: "Beautiful photos are not an offer.",
    subtitle: "Aesthetic and offer are two different things. Most food businesses only have one.",
    seoTitle: "Offer Visibility on Instagram: Why Beautiful Photos Don't Convert | Daee Media",
    seoDesc: "Protein Pals had great food photography. But a new visitor could scroll the entire grid and not know what a plan cost or how to subscribe. Here's the distinction between aesthetic and offer, and why it matters more than creative quality.",
    ogTitle: "Beautiful photos are not an offer.",
    ogDesc: "You can have the most beautiful Instagram grid in your niche and still have an invisible offer. Here's the difference between aesthetic content and offer content, and why most food businesses only have one.",
    keywords: "Instagram offer visibility service business UK USA Australia UAE, how to convert Instagram followers to clients, service business Instagram strategy, offer clarity Instagram profile, Instagram profile optimization conversion, how to sell services on Instagram, Instagram for high-ticket services",
    excerpt: "Aesthetic content says: we are real and our product looks good. Offer content says: here is what you get, here is what it costs, here is how to start. Both are necessary. They are not the same thing. Most food and service businesses have built the first and have almost none of the second.",
    body: [
      { type: 'p', text: "There is a version of Instagram presence that looks impressive and converts nothing." },
      { type: 'p', text: "Beautiful photography. Consistent editing. A grid that feels cohesive and professional. Engagement from people who say the food looks amazing. And a new visitor who scrolls the entire profile and leaves with no idea what the service costs, what the plans include, or what to do next." },
      { type: 'p', text: "This is the offer visibility problem. It is more common than any other failure in food and service business marketing." },
      { type: 'heading', text: "The distinction that matters" },
      { type: 'highlight', label: 'Two types of content', text: "Aesthetic content signals legitimacy. It says: we exist, we are real, our product is worth photographing. It builds passive brand recognition.\n\nOffer content converts. It says: here is what you get, here is what it costs, here is how to start. It answers the question a buyer is actually asking.\n\nBoth are necessary. They are not interchangeable." },
      { type: 'heading', text: "The context: Protein Pals before Daee Media" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. Before Daee Media's involvement, they had under 300 Instagram followers and a grid of food photographs that showed the quality of the product without showing the product." },
      { type: 'p', text: "A prospective subscriber landing on the profile from a friend's tag could see that the food was well-presented. They could not see: how many plan tiers existed, what a weekly subscription cost, whether there was a vegetarian option, which areas were covered for delivery, or what to do to get started." },
      { type: 'p', text: "Every one of those unknowns is an exit. A visitor who cannot answer the basic buyer questions does not DM to ask. They leave." },
      { type: 'heading', text: "What offer content looks like in practice" },
      { type: 'steps', items: [
        { n: '01', title: 'Plan names and what they include', body: 'Not just "meal plans." The specific plan names, the number of meals per week, the macro profile, the target buyer for each plan. Specificity creates recognition: "that one is for me."' },
        { n: '02', title: 'Price stated clearly', body: "No 'DM for pricing.' Pricing in the open removes a friction point and pre-qualifies: someone who reads the price and DMs anyway is a warm lead. Someone who bounces at the price was not going to convert regardless." },
        { n: '03', title: 'One action to start', body: 'A single trigger: DM the word "Menu." Not "contact us," not "visit our website," not "fill in the form." One word. One action. The lower the activation energy, the higher the completion rate.' },
        { n: '04', title: 'Pinned to the top', body: 'Offer content buried in the feed is invisible. Pinned carousels are the first thing any visitor sees on any device. Three pinned posts, one per core plan, answered every buyer question before a DM was sent.' },
      ]},
      { type: 'whatsapp', src: '/assets/pp-case/pp-wa-launch.jpeg',
        caption: '25 June 2025 · Campaign launch day: DMs already flowing because the offer was visible before paid traffic arrived',
        alt: 'WhatsApp showing Protein Pals leads coming in on campaign launch day June 2025' },
      { type: 'p', text: "When paid campaigns launched on June 25th, the profile already had three pinned offer carousels in place. Every paid click landed on a profile that could answer the buyer's questions without a DM. The ad traffic was not introducing a brand that needed explaining. It was sending warm intent to a profile that was ready to convert it." },
      { type: 'cta-inline', text: "See how offer visibility became the foundation of the Protein Pals system.", label: "Read the Protein Pals case study", target: 'case' },
      { type: 'heading', text: "The audit question" },
      { type: 'p', text: "Open your business profile. Pretend you have never heard of what you sell. Can you answer, within ten seconds and without clicking anything: what exactly is for sale, what does it cost, and what do you do to get it?" },
      { type: 'p', text: "If the answer is no, the problem is not your creative quality. The problem is offer visibility. Fix that before running a single paid ad." },
    ],
    cta: 'Audit your offer visibility', ctaTarget: 'apply',
    related: ['instagram-pinned-post-offer-visibility', 'crm-data-brand-strategy-vegetarian'],
  },

  /* 20: Junk Leads as Targeting Asset (angle 23) */
  {
    id: 'junk-leads-exclusion-audience-meta',
    num: '20', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '5 min', tag: 'Meta Ads',
    title: "26 junk leads. One exclusion audience. A sharper algorithm.",
    subtitle: "Most businesses discard bad leads. Here is what to do with them instead.",
    seoTitle: "How to Turn Junk Leads Into a Meta Exclusion Audience | Daee Media",
    seoDesc: "Protein Pals had a 1.33% junk rate across 1,942 leads. Those 26 junk leads weren't discarded. They built an exclusion audience that made every subsequent campaign more precise. Here's how.",
    ogTitle: "26 junk leads. One exclusion audience. A sharper algorithm.",
    ogDesc: "Most businesses write off bad leads. We fed them back to Meta as negative signals. Here's what a 1.33% junk rate produced beyond the obvious quality metric.",
    keywords: "Meta exclusion audience UK USA Australia UAE, how to use junk leads Meta ads, negative audience Meta advertising, custom audience exclusion Facebook ads, lead quality Meta ads, CRM exclusion audience Meta, Meta ads negative signal CAPI, improve lead quality Meta advertising",
    excerpt: "A junk lead feels like a cost: time spent calling a number that doesn't pick up, a postal code outside the delivery zone, an email that bounces. Most businesses mark it and move on. In a system connected to the Conversion API, a junk lead is a signal. And signals have value.",
    body: [
      { type: 'p', text: "A junk lead feels like a cost." },
      { type: 'p', text: "Time spent calling a number that doesn't pick up. A postal code outside the delivery zone. Someone who filled the form out of curiosity with no intent to buy. Most businesses mark it as junk and move on. The lead is discarded. The data is wasted." },
      { type: 'p', text: "In a system connected to the Conversion API, a junk lead is a signal. And signals, including negative ones, have value." },
      { type: 'heading', text: "The context: 26 junk leads out of 1,942" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. The ManyChat qualification flow filtered leads before they reached the CRM: postal code, dietary preference, health goal, work situation. By the time a lead entered Zoho, it had already passed four filters. Junk was rare." },
      { type: 'p', text: "Of 1,942 total leads generated between June and November 2025, 26 were tagged as junk: a 1.33% junk rate. A quality metric that proved the qualification system was working." },
      { type: 'p', text: "But the junk tags did something beyond proving quality. They fed a function." },
      { type: 'screenshot', src: '/assets/pp-case/pp-crm-junk.png', variant: 'crm',
        caption: 'Zoho CRM · Junk Lead filter: 26 records out of 1,942 total leads generated Jun-Nov 2025',
        alt: 'Zoho CRM filtered to Junk Lead status showing 26 total junk records' },
      { type: 'heading', text: "How junk leads feed the exclusion audience" },
      { type: 'p', text: "Every lead tagged as junk in Zoho fired a Conversion API event back to Meta via LeadChain: a negative outcome signal associated with a specific profile. Meta's algorithm uses these signals to build a picture of what a non-converting lead looks like: which ad they clicked, what demographics they match, what behavioural patterns they share." },
      { type: 'p', text: "Over time, this becomes an exclusion layer. When Meta encounters a new prospect who statistically resembles the junk pool, that prospect is deprioritised in the auction. The algorithm does not just learn who to find. It learns who to avoid." },
      { type: 'highlight', label: 'The compound effect', text: "A positive CAPI signal says: find more people like this converter. A negative CAPI signal says: stop finding people like this junk lead. Both signals improve targeting. Most businesses only send the first kind. The second kind is equally valuable and almost never used." },
      { type: 'heading', text: "Why the 1.33% junk rate was not just a quality metric" },
      { type: 'steps', items: [
        { n: '01', title: 'It validated the qualification flow', body: 'A 1.33% junk rate meant the ManyChat filters were doing their job. Fewer junk leads entering the CRM meant fewer wasted founder calls and less noise in the pipeline.' },
        { n: '02', title: 'It built the exclusion audience', body: '26 junk profiles, aggregated and fed to Meta, contributed to the negative lookalike that suppressed similar profiles in future campaigns. Small in number. Real in effect.' },
        { n: '03', title: 'It reinforced the positive signal', body: 'When almost every lead in the CRM is qualified, the converter data that flows back to Meta is clean. The algorithm is learning from a high-signal pool. The CPL drops faster.' },
      ]},
      { type: 'p', text: "The junk leads did not just prove the system was working. They actively made the system work better. That is the difference between a lead management tool and a revenue system." },
      { type: 'cta-inline', text: "See the full 1,942-lead system and the infrastructure behind the 1.33% junk rate.", label: "Read the Protein Pals case study", target: 'case' },
    ],
    cta: 'Build a system that learns from every lead', ctaTarget: 'apply',
    related: ['five-questions-98-percent-qualified', 'cpl-feedback-loop-meta-crm'],
  },

  /* 21: 15 to 240 Subscriptions (angle 32) */
  {
    id: 'subscription-growth-compounding-system',
    num: '21', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '6 min', tag: 'Growth',
    title: "From 15 to 240 subscriptions in five months.",
    subtitle: "Not a campaign spike. A system compounding.",
    seoTitle: "How a Subscription Business Grew 16x in 5 Months With Meta Ads | Daee Media",
    seoDesc: "Protein Pals had 15 active subscribers in May 2025. By October they had 240, with 420 more in pipeline, before pausing because the kitchen couldn't keep up. Here's the compounding math behind that growth.",
    ogTitle: "From 15 to 240 subscriptions in five months.",
    ogDesc: "This wasn't a traffic spike. It was a system that compounded: leads qualified, called, subscribed, and each subscription improved the next campaign. Here's the math.",
    keywords: "subscription business growth Meta ads UK USA Australia UAE, how to grow subscriptions with Meta advertising, subscription business acquisition strategy, compounding revenue system Meta, LTV subscription marketing, Facebook ads subscription growth, subscription service lead generation globally",
    excerpt: "A campaign that spikes and plateaus is a media buy. A system that compounds is a business asset. The difference shows up in the growth curve: one produces a peak followed by regression to baseline. The other produces a floor that rises each month. Here is what the second one looks like in practice.",
    body: [
      { type: 'p', text: "A campaign that spikes and plateaus is a media buy." },
      { type: 'p', text: "A system that compounds is a business asset. The difference shows up in the growth curve. A media buy produces a peak followed by regression to baseline. A compounding system produces a floor that rises each month, because each month's results feed the next month's targeting." },
      { type: 'heading', text: "The Protein Pals growth curve" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. When Daee Media began working with them in May 2025, there were 15 active subscribers. By October 19th, when the kitchen hit capacity and the founders paused the campaign, the subscriber base was at 230-240." },
      { type: 'metrics', items: [
        { num: '15', label: 'Subscribers in May', sub: 'Before any paid campaigns' },
        { num: '45', label: 'New in 15 days', sub: 'First lead gen campaign · Jul 2025' },
        { num: '240', label: 'Active subscribers', sub: 'At campaign pause · Oct 2025' },
      ]},
      { type: 'p', text: "That is not a 16x growth story from one good campaign. It is a 16x growth story from a system that accumulated signal, improved targeting, lowered CPL, and converted leads at an increasing rate month over month." },
      { type: 'heading', text: "The compounding mechanics" },
      { type: 'steps', items: [
        { n: 'Month 1', title: 'June 2025: Foundation', body: 'Engagement ads running at $0.50 per conversation. ManyChat flows tested. Pinned carousels published. The warm audience pool building before lead gen launches. No subscriptions from paid yet, but the audience is not cold when the campaign starts.' },
        { n: 'Month 2', title: 'July 2025: First conversion cohort', body: '45 new subscriptions in the first 15 days of lead gen. The first converter data flows back to Meta via CAPI. The algorithm gets its first real signal: this is what a Protein Pals subscriber looks like.' },
        { n: 'Month 3', title: 'August-September 2025: Crisis and hold', body: 'Meta rejection cycle. CPL climbs to 8-9 CAD. Volume drops. But the CAPI data from the first two months does not disappear. It waits in the model.' },
        { n: 'Month 4', title: 'October 2025: Compounding visible', body: 'Relaunch day: $1.28 CPL. 33 leads in 12 hours. The algorithm is running on four months of outcome data. It is not finding leads anymore. It is finding subscribers. The compounding is now visible in the number.' },
      ]},
      { type: 'whatsapp', src: '/assets/pp-case/pp-wa-july13.jpeg',
        caption: 'July 13, 2025 · 45 closed in 15 days: the first conversion cohort that fed the CAPI model',
        alt: 'WhatsApp showing 45 closed Protein Pals deals in first 15 days of lead gen campaign' },
      { type: 'heading', text: "Why 420 leads in pipeline at pause is not a failure" },
      { type: 'p', text: "When the campaign paused on October 19th, 420 leads were still in the pipeline: qualified but not yet called, or contacted but not yet closed. Most businesses would read this as a conversion failure." },
      { type: 'p', text: "It is not. It is a warm list that the next campaign does not need to generate from scratch. When the kitchen upgrades and campaigns restart, those 420 leads receive a re-engagement message. Some will convert in the new year when the routine motivation resets. Some will refer. The pipeline does not expire. It waits." },
      { type: 'p', text: "A system that compounds does not reset to zero when you pause it. The data stays. The audience model stays. The pipeline stays. You restart from a higher floor than you started from in June." },
      { type: 'cta-inline', text: "Read the full Protein Pals engagement: the system, the numbers, and the pause.", label: "Read the case study", target: 'case' },
    ],
    cta: 'Build a system that compounds', ctaTarget: 'apply',
    related: ['demand-exceeds-capacity-campaign-success', 'free-trial-vs-subscribe-now'],
  },

  /* 22: ROAS vs LTV (angle 33) */
  {
    id: 'roas-vs-ltv-subscription-marketing',
    num: '22', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '5 min', tag: 'Strategy',
    title: "We don't pitch ROAS. We pitch LTV.",
    subtitle: "ROAS counts the first transaction. A subscription business lives on what happens after.",
    seoTitle: "Why LTV Matters More Than ROAS for Subscription Businesses | Daee Media",
    seoDesc: "Protein Pals produced 4-8x ROAS on a 6-7k CAD spend. That number is accurate and incomplete. Here's why LTV is the metric that tells the real story of what a working acquisition system produces.",
    ogTitle: "We don't pitch ROAS. We pitch LTV.",
    ogDesc: "4-8x ROAS sounds strong. It's also the floor, not the ceiling. Here's what the real return looks like when you account for subscription LTV, referrals, and 420 leads still in pipeline.",
    keywords: "ROAS vs LTV marketing UK USA Australia UAE, lifetime value vs return on ad spend, subscription business marketing metrics, how to measure Meta ads ROI, LTV calculation service business, performance marketing metrics service business, how to evaluate marketing agency results, beyond ROAS marketing",
    excerpt: "ROAS is a snapshot. It counts what the ad spend produced in the measurement window. For a subscription business, the measurement window is the wrong frame. The subscriber who joined in July is still paying in November. The subscriber who joined in July referred their colleague in September. ROAS does not count either of those.",
    body: [
      { type: 'p', text: "ROAS is a snapshot." },
      { type: 'p', text: "It counts what the ad spend produced in the measurement window. For a one-time purchase business, the measurement window is the right frame: the customer bought or they didn't, and the transaction is complete." },
      { type: 'p', text: "For a subscription business, the measurement window is the wrong frame entirely." },
      { type: 'heading', text: "What the Protein Pals ROAS number says" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA. The six-month paid campaign ran on 6-7k CAD in total ad spend. The direct subscriber revenue attributable to that spend, counting only the first month of each subscription, produces a ROAS of 4-8x depending on how the attribution window is set." },
      { type: 'p', text: "That number is accurate. It is also a significant undercount of the actual return." },
      { type: 'highlight', label: 'What ROAS misses for a subscription business', text: "Month two of each subscription. Month three. The upgrade from a weekly plan to a monthly plan. The referral from a subscriber who told a colleague in the same building. The pipeline of 420 qualified leads who did not convert in the measurement window but will convert when the kitchen restarts. ROAS counts none of this." },
      { type: 'heading', text: "What LTV changes about the calculation" },
      { type: 'p', text: "A Protein Pals subscriber on a weekly plan at 100 CAD per month has a conservative LTV of 400-600 CAD over a four to six month engagement before churn. A monthly plan subscriber at 180-200 CAD per month has a higher LTV." },
      { type: 'p', text: "At 240 active subscribers, with an average LTV of 400-600 CAD, the total system value generated from a 6-7k CAD spend is not 4-8x. It is a multiple that continues rising with every month the subscriber stays, every referral they make, and every re-engagement from the 420-lead pipeline." },
      { type: 'metrics', items: [
        { num: '6-7k', label: 'Total ad spend', sub: 'Jun-Nov 2025 campaign' },
        { num: '240', label: 'Active subscribers', sub: 'At campaign pause' },
        { num: '420', label: 'Still in pipeline', sub: 'Warm, not yet closed' },
      ]},
      { type: 'heading', text: "Why agencies pitch ROAS instead of LTV" },
      { type: 'p', text: "ROAS is visible immediately. It appears in Ads Manager within seven days of the campaign running. It is a number clients recognize. Pitching it is easy." },
      { type: 'p', text: "LTV requires a longer frame, a CRM that tracks retention, and a client relationship long enough to see it accumulate. Most agency engagements do not last that long. Most agency measurement setups do not track that deep. So the metric that matters most is the one that gets reported least." },
      { type: 'p', text: "We pitch LTV because it is the number that determines whether a business is worth building. A 4-8x ROAS on a 6k spend is a solid campaign. A compounding subscriber base with a 400-600 CAD LTV per conversion, growing every month, is a business." },
      { type: 'cta-inline', text: "See the full Protein Pals engagement and what the system produced beyond the ROAS number.", label: "Read the case study", target: 'case' },
    ],
    cta: 'Build a system measured in LTV, not just ROAS', ctaTarget: 'apply',
    related: ['subscription-growth-compounding-system', 'demand-exceeds-capacity-campaign-success'],
  },

  /* 23: Competitive Whitespace (angle 34) */
  {
    id: 'first-mover-niche-meta-advertising',
    num: '23', date: 'May 2026', schemaDate: '2026-05-21',
    readTime: '5 min', tag: 'Strategy',
    title: "The market nobody was advertising to.",
    subtitle: "And why that made the first six months structurally cheaper than they will ever be again.",
    seoTitle: "First-Mover Advantage in Niche Meta Advertising | Daee Media",
    seoDesc: "When Protein Pals launched Meta lead gen for Indian meal delivery in the Toronto GTA in June 2025, no competitor was running in that space. Here's what first-mover advantage looks like in a paid acquisition context and why it compounds.",
    ogTitle: "The market nobody was advertising to.",
    ogDesc: "When Protein Pals launched in June 2025, no competitor was running Meta lead gen for Indian meal delivery in Toronto. Here's what an unsaturated niche looks like in a paid acquisition context.",
    keywords: "niche market Meta advertising UK USA Australia UAE, first mover advantage Meta ads, unsaturated market advertising service business, local niche service business advertising, Meta ads competitive advantage, how to find underserved market advertising, niche Facebook ads strategy, first mover paid advertising niche market",
    excerpt: "Every market reaches a state where the cost of paid acquisition reflects the competition for audience attention. The businesses that enter before that saturation point arrive pay structurally lower CPLs, build cleaner audience models, and establish themselves in the algorithm before any competitor can crowd them out. That window does not stay open.",
    body: [
      { type: 'p', text: "Every market reaches saturation." },
      { type: 'p', text: "When multiple competitors are running Meta ads to the same audience for the same offer, the auction becomes expensive. CPL rises. Audience fatigue sets in. The algorithm has too many similar signals to distinguish between. The businesses that entered before saturation built their models when the signal was clean and the audience was uncontested." },
      { type: 'p', text: "That window does not stay open. But it is often open longer than founders assume, in niches they are already in." },
      { type: 'heading', text: "The context: Indian meal delivery in the Toronto GTA, June 2025" },
      { type: 'p', text: "**Protein Pals** is a high-protein Indian meal delivery service in the Toronto GTA, serving South Asian working professionals and families in Vaughan, Markham, and Mississauga. When Daee Media launched their first paid campaigns in June 2025, there was no established competitor running Meta lead generation in this specific market." },
      { type: 'p', text: "The audience existed. The Toronto GTA has one of the largest South Asian diaspora populations in North America, with high household incomes in the suburban corridors Protein Pals served, and an established cultural familiarity with tiffin and home-cooked meal subscriptions. The demand was there. The supply of Meta ads competing for it was not." },
      { type: 'highlight', label: 'What an unsaturated niche looks like in the auction', text: "Low CPM because few advertisers are bidding for the same audience. Clean audience data because the algorithm has not seen thousands of competing conversion signals confusing the model. High ad relevance scores because the creative is not competing with near-identical ads from competitors. These three factors together produce a CPL floor that rises as more competitors enter." },
      { type: 'heading', text: "What first-mover advantage produced for Protein Pals" },
      { type: 'steps', items: [
        { n: '01', title: 'Lower CPL from day one', body: 'The launch CPL of $3.50 in June was already competitive for a new account with no prior conversion data. A saturated market with multiple established competitors would have produced a higher floor.' },
        { n: '02', title: 'Uncontested audience model building', body: 'The CAPI data Protein Pals fed back to Meta over four months built a lookalike model from clean, uncontested conversion signals. A competitor entering the same market today would be building their model against an audience already partially shaped by Protein Pals data.' },
        { n: '03', title: 'Algorithm priority in the auction', body: 'An account with four months of clean conversion history and a high relevance score wins more auctions at lower bid prices than a new entrant with no history. The head start compounds in the auction itself.' },
      ]},
      { type: 'p', text: "By October 2025, the account had enough history and conversion signal that the CPL had dropped from $3.50 to $1.13. A new competitor entering the market in October would start at a higher CPL floor and take months to build the same quality of audience model." },
      { type: 'heading', text: "The question this raises for your business" },
      { type: 'p', text: "Most niche service businesses assume they are too small for paid acquisition to be worth the investment. They wait until the business is larger. The irony is that waiting is exactly what allows competitors to establish themselves in the algorithm first." },
      { type: 'p', text: "The right question is not: are we large enough to advertise? It is: is there a competitor already building an audience model in our niche? If the answer is no, the window is open. The cost of entering it now is lower than the cost of entering it after someone else has." },
      { type: 'cta-inline', text: "See what six months of first-mover acquisition built for Protein Pals.", label: "Read the Protein Pals case study", target: 'case' },
    ],
    cta: 'Move before the window closes', ctaTarget: 'apply',
    related: ['roas-vs-ltv-subscription-marketing', 'instagram-pinned-post-offer-visibility'],
  },
];

const VIDEOS = [
  {
    id: 'video-1',
    url: 'https://www.instagram.com/p/DYe9yjDCDnn/',
    embedUrl: 'https://www.instagram.com/p/DYe9yjDCDnn/embed/',
    label: 'Featured',
    caption: 'Fall in love with them, not your idea',
  },
  {
    id: 'video-2',
    url: 'https://www.instagram.com/p/DYClm6TK_8X/',
    embedUrl: 'https://www.instagram.com/p/DYClm6TK_8X/embed/',
    label: 'Latest',
    caption: 'Built for those who serve others',
  },
];

/* ═══════════════════════════════════════════════════════
   INDEX
═══════════════════════════════════════════════════════ */
function ArticlesIndex({ onOpen, onApply, onArticle }) {
  useEffectArticles(() => {
    const prevTitle = document.title;
    document.title = 'Field Notes: Meta Ads & Lead Generation Insights | Daee Media';
    setMeta('meta[name="description"]', 'content', 'Field Notes from inside real Meta lead generation engagements. How the Conversion API works, why qualification matters, what creative bank strategy looks like, and how compounding systems outperform one-off campaigns. By Daee Media.');
    setMeta('link[rel="canonical"]', 'href', 'https://daeemedia.com/field-notes');
    setMeta('meta[property="og:title"]', 'content', 'Field Notes: Meta Ads & Lead Generation Insights | Daee Media');
    setMeta('meta[property="og:description"]', 'content', 'Notes from inside real Meta lead generation engagements for service businesses. What worked, what broke, and why. By Mohammed Saad Shaikh, Daee Media.');
    setMeta('meta[property="og:url"]', 'content', 'https://daeemedia.com/field-notes');

    /* JSON-LD for Field Notes index */
    const existing = document.getElementById('article-schema');
    if (existing) existing.remove();
    const el = document.createElement('script');
    el.type = 'application/ld+json';
    el.id = 'article-schema';
    el.textContent = JSON.stringify([
      {
        '@context': 'https://schema.org',
        '@type': 'Blog',
        name: 'Daee Media Field Notes',
        description: 'Notes from inside real Meta lead generation engagements. What worked, what failed, and the systems behind the numbers.',
        url: 'https://daeemedia.com/field-notes',
        publisher: { '@type': 'Organization', name: 'Daee Media', url: 'https://daeemedia.com' },
        author: { '@type': 'Person', name: 'Mohammed Saad Shaikh', url: 'https://www.linkedin.com/in/mohammed-saad-shaikh' },
        blogPost: ARTICLES.map(a => ({
          '@type': 'BlogPosting',
          headline: a.seoTitle || a.title,
          description: a.seoDesc || a.excerpt,
          datePublished: a.schemaDate,
          url: `https://daeemedia.com/field-notes/${a.id}`,
        })),
      },
    ]);
    document.head.appendChild(el);

    return () => {
      document.title = prevTitle;
      setMeta('meta[name="description"]', 'content', DEFAULT_DESC);
      setMeta('link[rel="canonical"]', 'href', 'https://daeemedia.com');
      setMeta('meta[property="og:title"]', 'content', DEFAULT_TITLE);
      setMeta('meta[property="og:description"]', 'content', 'We don\'t run ads. We build systems that earn revenue.');
      setMeta('meta[property="og:url"]', 'content', 'https://daeemedia.com');
      const schemaEl = document.getElementById('article-schema');
      if (schemaEl) schemaEl.remove();
    };
  }, []);

  return (
    <Section id="articles" pad={140} topRule>
      <Container>
        <Reveal>
          <div style={{ marginBottom: 72 }}>
            <Eyebrow>§ Field notes</Eyebrow>
            <h1 style={{
              fontFamily: 'var(--font-display)', fontSize: 'clamp(44px, 5.2vw, 72px)',
              lineHeight: 1.02, letterSpacing: '-0.02em', margin: '16px 0 0', fontWeight: 400,
            }}>
              Meta ads and lead gen,{' '}
              <em style={{ fontStyle: 'italic', color: 'var(--accent)' }}>from inside the work.</em>
            </h1>
            <p style={{ fontSize: 18, color: 'var(--fg-muted)', marginTop: 20, maxWidth: 560, lineHeight: 1.6 }}>
              Field notes on Meta advertising, lead qualification, CRM automation, and revenue systems for service businesses. What we tried, what worked, and what the numbers actually showed.
            </p>
          </div>
        </Reveal>

        <Reveal delay={60}>
          <div style={{ marginBottom: 96 }}>
            <div style={{
              fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.14em',
              color: 'var(--fg-subtle)', fontWeight: 500, marginBottom: 24,
            }}>§ From @saadshares</div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 24 }}>
              {VIDEOS.map(v => <VideoCard key={v.id} video={v}/>)}
            </div>
          </div>
        </Reveal>

        <div>
          {ARTICLES.map((a, i) => (
            <Reveal key={a.id} delay={i * 60}>
              <ArticleCard article={a} onClick={() => onArticle && onArticle(a.id)}/>
            </Reveal>
          ))}
        </div>
      </Container>
    </Section>
  );
}

/* ─── Video card ─────────────────────────────────────── */
function VideoCard({ video }) {
  return (
    <div>
      <div style={{
        fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.12em',
        color: 'var(--fg-subtle)', fontWeight: 500, marginBottom: 12,
        display: 'flex', alignItems: 'center', gap: 8,
      }}>
        <span style={{ width: 6, height: 6, borderRadius: 999, background: 'var(--accent)', display: 'inline-block' }}/>
        {video.label} · Instagram
      </div>
      <div style={{
        borderRadius: 4, overflow: 'hidden', border: '1px solid var(--border)',
        background: 'var(--paper-100)', minHeight: 480,
      }}>
        <iframe
          src={video.embedUrl} width="100%" height="540" frameBorder="0" scrolling="no"
          allowTransparency="true"
          allow="autoplay; clipboard-write; encrypted-media; picture-in-picture; web-share"
          style={{ display: 'block', border: 'none' }} title={video.caption}
        />
      </div>
      <div style={{ marginTop: 12, display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
        <span style={{ fontSize: 13, color: 'var(--fg-muted)' }}>{video.caption}</span>
        <a href={video.url} target="_blank" rel="noopener noreferrer"
          style={{ fontSize: 12, color: 'var(--fg-subtle)', textDecoration: 'none',
            borderBottom: '1px solid var(--border-strong)', paddingBottom: 1 }}>
          View on Instagram →
        </a>
      </div>
    </div>
  );
}

/* ─── Article card (index row) ───────────────────────── */
function ArticleCard({ article, onClick }) {
  const [hover, setHover] = useStateArticles(false);
  const isCase = ['04','05','06','07','08','09','10'].includes(article.num);
  return (
    <article
      onClick={onClick}
      onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      style={{
        display: 'grid', gridTemplateColumns: '120px 1fr auto',
        gap: 48, alignItems: 'start', padding: '44px 0',
        borderTop: '1px solid var(--border-strong)', cursor: 'pointer',
      }}>
      <div>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: hover ? 'var(--accent)' : 'var(--fg-subtle)', transition: 'color 180ms' }}>
          No.{article.num}
        </div>
        <div style={{ fontSize: 12, color: 'var(--fg-subtle)', marginTop: 8 }}>{article.date}</div>
        <div style={{ fontSize: 11, color: 'var(--fg-faint)', marginTop: 6 }}>{article.readTime} read</div>
        {isCase && (
          <div style={{
            marginTop: 10, fontSize: 10, color: 'var(--accent)',
            fontFamily: 'var(--font-mono)', textTransform: 'uppercase', letterSpacing: '0.1em',
          }}>Case-based</div>
        )}
      </div>
      <div>
        <div style={{ marginBottom: 14 }}>
          <span style={{
            fontSize: 11, padding: '3px 10px', borderRadius: 999,
            border: '1px solid var(--border-strong)', color: 'var(--fg-muted)',
            fontFamily: 'var(--font-sans)', textTransform: 'uppercase', letterSpacing: '0.1em',
          }}>{article.tag}</span>
        </div>
        <h2 style={{
          fontFamily: 'var(--font-display)', fontSize: 'clamp(26px, 2.8vw, 38px)',
          lineHeight: 1.08, letterSpacing: '-0.015em', margin: '0 0 12px', fontWeight: 400,
        }}>{article.title}</h2>
        <p style={{ fontSize: 16, lineHeight: 1.6, color: 'var(--fg-muted)', margin: 0, maxWidth: 600 }}>
          {article.excerpt}
        </p>
      </div>
      <div style={{
        fontSize: 13, color: hover ? 'var(--accent)' : 'var(--fg-muted)',
        display: 'flex', alignItems: 'center', gap: 6,
        transform: hover ? 'translateX(4px)' : 'none',
        transition: 'transform 220ms var(--ease-out), color 180ms',
        paddingTop: 4, whiteSpace: 'nowrap',
      }}>Read <span aria-hidden>→</span></div>
    </article>
  );
}

/* ═══════════════════════════════════════════════════════
   ARTICLE DETAIL
═══════════════════════════════════════════════════════ */
function ArticleDetail({ article, onBack, onSelect, onOpen, onApply }) {

  /* ── Full SEO + schema injection ── */
  useEffectArticles(() => {
    const prevTitle = document.title;
    const slug = `https://daeemedia.com/field-notes/${article.id}`;

    document.title = article.seoTitle || `${article.title} | Daee Media`;
    setMeta('meta[name="description"]',      'content', article.seoDesc || article.excerpt);
    setMeta('meta[name="keywords"]',          'content', article.keywords || '');
    setMeta('link[rel="canonical"]',          'href',    slug);
    setMeta('meta[property="og:title"]',      'content', article.ogTitle || article.title);
    setMeta('meta[property="og:description"]','content', article.ogDesc  || article.excerpt);
    setMeta('meta[property="og:url"]',        'content', slug);
    setMeta('meta[property="og:type"]',       'content', 'article');
    setMeta('meta[name="twitter:title"]',     'content', article.ogTitle || article.title);
    setMeta('meta[name="twitter:description"]','content',article.ogDesc  || article.excerpt);

    /* JSON-LD schema */
    const faqBlocks = (article.body || []).filter(b => b.type === 'faq');
    const schema = [{
      '@context': 'https://schema.org',
      '@type': 'Article',
      headline: article.seoTitle,
      description: article.seoDesc,
      datePublished: article.schemaDate,
      dateModified: article.schemaDate,
      author: {
        '@type': 'Person',
        name: 'Mohammed Saad Shaikh',
        url: 'https://www.linkedin.com/in/mohammed-saad-shaikh',
        jobTitle: 'Founder',
        worksFor: { '@type': 'Organization', name: 'Daee Media', url: 'https://daeemedia.com' },
      },
      publisher: {
        '@type': 'Organization', name: 'Daee Media', url: 'https://daeemedia.com',
        logo: { '@type': 'ImageObject', url: 'https://daeemedia.com/assets/og-image.png' },
      },
      mainEntityOfPage: { '@type': 'WebPage', '@id': slug },
      keywords: article.keywords,
    }, {
      '@context': 'https://schema.org',
      '@type': 'BreadcrumbList',
      itemListElement: [
        { '@type': 'ListItem', position: 1, name: 'Home', item: 'https://daeemedia.com' },
        { '@type': 'ListItem', position: 2, name: 'Field Notes', item: 'https://daeemedia.com/field-notes' },
        { '@type': 'ListItem', position: 3, name: article.title, item: slug },
      ],
    }];

    if (faqBlocks.length > 0) {
      schema.push({
        '@context': 'https://schema.org',
        '@type': 'FAQPage',
        mainEntity: faqBlocks.flatMap(b => b.items.map(item => ({
          '@type': 'Question',
          name: item.q,
          acceptedAnswer: { '@type': 'Answer', text: item.a },
        }))),
      });
    }

    const existing = document.getElementById('article-schema');
    if (existing) existing.remove();
    const el = document.createElement('script');
    el.type = 'application/ld+json';
    el.id = 'article-schema';
    el.textContent = JSON.stringify(schema);
    document.head.appendChild(el);

    return () => {
      document.title = prevTitle;
      setMeta('meta[name="description"]',       'content', DEFAULT_DESC);
      setMeta('meta[name="keywords"]',           'content', '');
      setMeta('link[rel="canonical"]',           'href',    'https://daeemedia.com');
      setMeta('meta[property="og:title"]',       'content', DEFAULT_TITLE);
      setMeta('meta[property="og:description"]', 'content', 'We don\'t run ads. We build systems that earn revenue.');
      setMeta('meta[property="og:url"]',         'content', 'https://daeemedia.com');
      setMeta('meta[property="og:type"]',        'content', 'website');
      setMeta('meta[name="twitter:title"]',      'content', DEFAULT_TITLE);
      setMeta('meta[name="twitter:description"]','content', 'We don\'t run ads. We build systems that earn revenue.');
      const schemaEl = document.getElementById('article-schema');
      if (schemaEl) schemaEl.remove();
    };
  }, [article.id]);

  const related = ARTICLES.filter(a => article.related && article.related.includes(a.id));

  return (
    <Section id="article-detail" pad={80} topRule>
      <Container narrow>

        {/* Back nav */}
        <Reveal>
          <button onClick={onBack} style={{
            background: 'none', border: 'none', cursor: 'pointer',
            fontSize: 13, color: 'var(--fg-subtle)', padding: 0,
            display: 'flex', alignItems: 'center', gap: 6, marginBottom: 56,
          }}>← Back to field notes</button>
        </Reveal>

        {/* Header */}
        <Reveal delay={40}>
          <div style={{ marginBottom: 12 }}>
            <span style={{
              fontSize: 11, padding: '3px 10px', borderRadius: 999,
              border: '1px solid var(--border-strong)', color: 'var(--fg-muted)',
              textTransform: 'uppercase', letterSpacing: '0.1em',
            }}>{article.tag}</span>
          </div>
          <div style={{ fontSize: 13, color: 'var(--fg-subtle)', margin: '12px 0 20px' }}>
            {article.date} · {article.readTime} read · By Mohammed Saad Shaikh
          </div>
          <h1 style={{
            fontFamily: 'var(--font-display)', fontSize: 'clamp(38px, 5vw, 62px)',
            lineHeight: 1.04, letterSpacing: '-0.02em', margin: '0 0 16px', fontWeight: 400,
          }}>{article.title}</h1>
          <p style={{
            fontFamily: 'var(--font-display)', fontSize: 'clamp(19px, 2.2vw, 28px)',
            lineHeight: 1.2, letterSpacing: '-0.01em', margin: '0 0 48px',
            color: 'var(--fg-muted)', fontStyle: 'italic',
          }}>{article.subtitle}</p>
        </Reveal>

        {/* Body */}
        <div style={{ borderTop: '1px solid var(--border)', paddingTop: 48 }}>
          {article.body.map((block, i) => (
            <Reveal key={i} delay={Math.min(i * 25, 180)}>
              <ArticleBlock block={block} onApply={onApply} onOpen={onOpen} onSelect={onSelect}/>
            </Reveal>
          ))}
        </div>

        {/* Related reading */}
        {related.length > 0 && (
          <Reveal delay={80}>
            <div style={{ marginTop: 64, paddingTop: 32, borderTop: '1px solid var(--border)' }}>
              <div style={{
                fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.14em',
                color: 'var(--fg-subtle)', fontWeight: 500, marginBottom: 20,
              }}>Also in Field Notes</div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                {related.map(r => (
                  <a key={r.id} href={`/field-notes/${r.id}`}
                    onClick={(e) => { e.preventDefault(); onSelect(r.id); }}
                    style={{
                      background: 'var(--paper-100)', border: '1px solid var(--border)',
                      borderRadius: 4, padding: '16px 20px', cursor: 'pointer',
                      textAlign: 'left', display: 'flex', justifyContent: 'space-between',
                      alignItems: 'center', gap: 16, transition: 'border-color 180ms',
                      textDecoration: 'none',
                    }}>
                    <div>
                      <div style={{ fontSize: 11, color: 'var(--fg-subtle)', fontFamily: 'var(--font-mono)', marginBottom: 4 }}>No.{r.num} · {r.tag}</div>
                      <span style={{
                        fontFamily: 'var(--font-display)', fontSize: 17, color: 'var(--fg)',
                        lineHeight: 1.2, letterSpacing: '-0.01em',
                      }}>{r.title}</span>
                    </div>
                    <span style={{ fontSize: 16, color: 'var(--accent)', flexShrink: 0 }}>→</span>
                  </a>
                ))}
              </div>
            </div>
          </Reveal>
        )}

        {/* Author + CTA footer */}
        <Reveal delay={100}>
          <div style={{
            marginTop: 56, paddingTop: 40, borderTop: '1px solid var(--border)',
            display: 'flex', justifyContent: 'space-between', alignItems: 'center',
            flexWrap: 'wrap', gap: 20,
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
              <img src="/assets/IMG_1129.PNG" alt="Mohammed Saad Shaikh, Founder of Daee Media"
                style={{ width: 44, height: 44, borderRadius: 999, objectFit: 'cover', objectPosition: 'center top',
                  border: '2px solid var(--border-strong)' }}/>
              <div>
                <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--fg)' }}>Mohammed Saad Shaikh</div>
                <div style={{ fontSize: 12, color: 'var(--fg-subtle)' }}>Founder, Daee Media</div>
              </div>
              {article.linkedinUrl && (
                <a href={article.linkedinUrl} target="_blank" rel="noopener noreferrer"
                  style={{ fontSize: 12, color: 'var(--fg-subtle)', textDecoration: 'none',
                    borderBottom: '1px solid var(--border-strong)', paddingBottom: 1, marginLeft: 4 }}>
                  View on LinkedIn →
                </a>
              )}
            </div>
            <Button onClick={article.ctaTarget === 'apply' ? onApply : () => onOpen && onOpen(article.ctaTarget)}>
              {article.cta} →
            </Button>
          </div>
        </Reveal>

      </Container>
    </Section>
  );
}

/* ═══════════════════════════════════════════════════════
   BLOCK RENDERER
═══════════════════════════════════════════════════════ */
function ArticleBlock({ block, onApply, onOpen, onSelect }) {
  switch (block.type) {

    case 'heading': return (
      <h2 style={{
        fontFamily: 'var(--font-display)', fontSize: 'clamp(24px, 2.4vw, 30px)',
        fontWeight: 400, letterSpacing: '-0.01em', lineHeight: 1.2,
        margin: '52px 0 20px', color: 'var(--fg)',
      }}>{block.text}</h2>
    );

    case 'subheading': return (
      <h3 style={{
        fontFamily: 'var(--font-display)', fontSize: 20, fontWeight: 400,
        letterSpacing: '-0.005em', lineHeight: 1.3, margin: '36px 0 14px',
        color: 'var(--fg)', fontStyle: 'italic',
      }}>{block.text}</h3>
    );

    case 'p': return (
      <p style={{ fontSize: 18, lineHeight: 1.78, color: 'var(--fg-muted)', margin: '0 0 26px' }}>
        {rt(block.text)}
      </p>
    );

    case 'list': return (
      <ul style={{ padding: '0 0 0 22px', margin: '0 0 26px', display: 'flex', flexDirection: 'column', gap: 12 }}>
        {block.items.map((item, i) => (
          <li key={i} style={{ fontSize: 18, lineHeight: 1.65, color: 'var(--fg-muted)' }}>{rt(item)}</li>
        ))}
      </ul>
    );

    case 'pullquote': return (
      <blockquote style={{
        margin: '40px 0', padding: '28px 32px',
        background: 'var(--paper-100)', borderLeft: '3px solid var(--accent)', borderRadius: 2,
        position: 'relative',
      }}>
        <div aria-hidden style={{
          position: 'absolute', top: 6, right: 16, fontFamily: 'var(--font-display)',
          fontSize: 56, lineHeight: 1, color: 'var(--accent)', opacity: 0.15,
        }}>"</div>
        <p style={{
          fontFamily: 'var(--font-display)', fontStyle: 'italic',
          fontSize: 20, lineHeight: 1.45, color: 'var(--fg)', margin: 0, fontWeight: 400,
        }}>{block.text}</p>
        {block.attribution && (
          <div style={{ marginTop: 14, fontSize: 13, color: 'var(--fg-subtle)' }}>
            {block.attribution}
          </div>
        )}
      </blockquote>
    );

    case 'highlight': return (
      <div style={{
        margin: '36px 0', padding: '28px 32px',
        background: 'var(--accent-subtle)', borderRadius: 4,
        border: '1px solid var(--border-strong)',
      }}>
        {block.label && (
          <div style={{
            fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--accent)',
            textTransform: 'uppercase', letterSpacing: '0.16em', marginBottom: 14,
          }}>{block.label}</div>
        )}
        <p style={{
          fontSize: 17, lineHeight: 1.7, color: 'var(--fg)', margin: 0,
          fontFamily: 'var(--font-display)', whiteSpace: 'pre-line',
        }}>{block.text}</p>
      </div>
    );

    case 'metrics': return (
      <div style={{
        display: 'grid', gridTemplateColumns: `repeat(${block.items.length}, 1fr)`,
        gap: 20, margin: '36px 0',
      }}>
        {block.items.map((item, i) => (
          <div key={i} style={{
            padding: '24px 20px', background: 'var(--bg-elevated)',
            border: '1px solid var(--border-strong)', borderRadius: 4,
            textAlign: 'center',
          }}>
            <div style={{
              fontFamily: 'var(--font-display)', fontSize: 'clamp(32px, 3.5vw, 48px)',
              letterSpacing: '-0.02em', lineHeight: 1, color: 'var(--fg)', marginBottom: 8,
            }}>{item.num}</div>
            <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--fg)', marginBottom: 4 }}>{item.label}</div>
            <div style={{ fontSize: 11, color: 'var(--fg-subtle)' }}>{item.sub}</div>
          </div>
        ))}
      </div>
    );

    case 'steps': return (
      <div style={{ margin: '36px 0', display: 'flex', flexDirection: 'column', gap: 0,
        border: '1px solid var(--border-strong)', borderRadius: 4, overflow: 'hidden' }}>
        {block.items.map((step, i) => (
          <div key={i} style={{
            display: 'grid', gridTemplateColumns: '64px 1fr', gap: 20,
            padding: '22px 24px',
            background: i % 2 === 0 ? 'var(--bg-elevated)' : 'var(--paper-100)',
            borderTop: i === 0 ? 'none' : '1px solid var(--border)',
          }}>
            <div style={{
              fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--accent)',
              letterSpacing: '0.1em', paddingTop: 3, fontWeight: 600,
            }}>{step.n}</div>
            <div>
              <div style={{
                fontFamily: 'var(--font-display)', fontSize: 18, lineHeight: 1.25,
                color: 'var(--fg)', marginBottom: 6, letterSpacing: '-0.005em',
              }}>{step.title}</div>
              <div style={{ fontSize: 15, lineHeight: 1.6, color: 'var(--fg-muted)' }}>
                {rt(step.body)}
              </div>
            </div>
          </div>
        ))}
      </div>
    );

    case 'screenshot': return (
      <figure style={{
        margin: '40px auto', maxWidth: 680,
        boxShadow: '0 8px 24px -8px rgba(20,19,15,0.14), 0 0 0 1px var(--border-strong)',
        borderRadius: 6, overflow: 'hidden', background: 'var(--bg-elevated)',
      }} role="img" aria-label={block.alt}>
        <div style={{
          padding: '10px 14px', borderBottom: '1px solid var(--border)',
          background: 'var(--paper-100)', display: 'flex', gap: 6, alignItems: 'center',
        }}>
          {['#FF5F57','#FFBD2E','#27C93F'].map((c, i) => (
            <span key={i} style={{ width: 8, height: 8, borderRadius: 999, background: c }}/>
          ))}
          <span style={{ marginLeft: 12, fontSize: 11, color: 'var(--fg-subtle)', fontFamily: 'var(--font-mono)' }}>
            {block.variant === 'ads' ? 'business.facebook.com / ads-manager' :
             block.variant === 'crm' ? 'crm.zoho.in / protein-pals' :
             block.variant === 'capi' ? 'leadchain.io / dashboard' : 'daee, internal'}
          </span>
        </div>
        <img src={block.src} alt={block.alt} style={{ width: '100%', display: 'block' }} loading="lazy"/>
        <figcaption style={{
          padding: '12px 16px', fontSize: 12, color: 'var(--fg-subtle)',
          borderTop: '1px solid var(--border)', textAlign: 'center',
        }}>{block.caption}</figcaption>
      </figure>
    );

    case 'whatsapp': return (
      <figure style={{
        margin: '40px auto', maxWidth: 360,
        boxShadow: '0 12px 32px -8px rgba(20,19,15,0.18), 0 0 0 1px var(--border-strong)',
        borderRadius: 20, overflow: 'hidden',
      }}>
        <img src={block.src} alt={block.caption} style={{ width: '100%', display: 'block' }} loading="lazy"/>
        <figcaption style={{
          padding: '12px 16px', fontSize: 12, color: 'var(--fg-subtle)',
          borderTop: '1px solid var(--border)', textAlign: 'center',
          background: 'var(--bg-elevated)',
        }}>{block.caption}</figcaption>
      </figure>
    );

    case 'faq': return (
      <div style={{ margin: '48px 0' }}>
        <div style={{
          fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.14em',
          color: 'var(--fg-subtle)', fontWeight: 500, marginBottom: 20,
        }}>Frequently asked</div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 0 }}>
          {block.items.map((item, i) => (
            <FaqItem key={i} q={item.q} a={item.a} borderTop={i === 0}/>
          ))}
        </div>
      </div>
    );

    case 'cta-inline': return (
      <div style={{
        margin: '48px 0', padding: '32px 28px',
        background: 'var(--accent-subtle)', borderRadius: 4,
        display: 'flex', justifyContent: 'space-between',
        alignItems: 'center', gap: 24, flexWrap: 'wrap',
      }}>
        <p style={{
          fontFamily: 'var(--font-display)', fontSize: 20, lineHeight: 1.35,
          color: 'var(--fg)', margin: 0, fontWeight: 400,
          letterSpacing: '-0.005em', maxWidth: 420,
        }}>{block.text}</p>
        <button
          onClick={block.target === 'case'
            ? () => onOpen && onOpen('protein-pals')
            : onApply}
          style={{
            background: 'var(--accent)', color: 'var(--bg)', border: 'none',
            borderRadius: 4, padding: '12px 22px', fontSize: 14, cursor: 'pointer',
            fontWeight: 600, whiteSpace: 'nowrap',
            transition: 'background 180ms',
          }}>
          {block.label} →
        </button>
      </div>
    );

    default: return null;
  }
}

/* ─── FAQ accordion item ─────────────────────────────── */
function FaqItem({ q, a, borderTop }) {
  const [open, setOpen] = useStateArticles(false);
  return (
    <div style={{ borderTop: '1px solid var(--border)', borderBottom: '1px solid transparent' }}>
      <button
        onClick={() => setOpen(o => !o)}
        style={{
          width: '100%', background: 'none', border: 'none', cursor: 'pointer',
          padding: '18px 0', display: 'flex', justifyContent: 'space-between',
          alignItems: 'center', gap: 16, textAlign: 'left',
        }}>
        <span style={{
          fontFamily: 'var(--font-display)', fontSize: 17, lineHeight: 1.3,
          color: 'var(--fg)', letterSpacing: '-0.005em',
        }}>{q}</span>
        <span style={{
          fontSize: 18, color: 'var(--accent)', flexShrink: 0,
          transform: open ? 'rotate(45deg)' : 'none', transition: 'transform 200ms',
        }}>+</span>
      </button>
      {open && (
        <div style={{
          fontSize: 16, lineHeight: 1.7, color: 'var(--fg-muted)',
          paddingBottom: 20, maxWidth: 640,
        }}>{a}</div>
      )}
    </div>
  );
}

window.ArticlesIndex  = ArticlesIndex;
window.ArticleDetail  = ArticleDetail;
window.ARTICLES       = ARTICLES;
