// Afford-X · ALM agent — unique brand mark, state machine, floating chat.
const { useState, useRef, useEffect, useCallback, createContext, useContext } = React;

/* ============================================================
   The ALM mark — an Afford-X spark.
   A 4-point star rotated to read as the brand "X", with a green
   gradient core and an orbiting micro-spark (red accent nod to
   the Afford-X "X"). Distinct from any third-party logo.
   ============================================================ */
const STAR = 'M12 1.6C12.7 6.9 17.1 11.3 22.4 12C17.1 12.7 12.7 17.1 12 22.4C11.3 17.1 6.9 12.7 1.6 12C6.9 11.3 11.3 6.9 12 1.6Z';

function AlmMark({ size = 26, state = 'idle', tone = 'green', id = 'm' }) {
  const gid = `almg-${id}`;
  const core = tone === 'white' ? '#fff' : `url(#${gid})`;
  const sat = tone === 'white' ? 'rgba(255,255,255,0.9)' : 'var(--afx-red-bright)';
  return (
    <span className={`alm-mark alm-state-${state}`} aria-hidden="true">
      <svg width={size} height={size} viewBox="0 0 24 24">
        <defs>
          <linearGradient id={gid} x1="0" y1="0" x2="1" y2="1">
            <stop offset="0" stopColor="#74C07F" />
            <stop offset="0.55" stopColor="var(--afx-green-500)" />
            <stop offset="1" stopColor="var(--afx-green-700)" />
          </linearGradient>
        </defs>
        <g className="alm-core" style={{ transform: 'rotate(45deg)', transformOrigin: '12px 12px' }}>
          <path d={STAR} fill={core} />
        </g>
        <g className="alm-orbit">
          <path d={STAR} fill={sat} transform="translate(20.5 4) scale(0.26)" />
        </g>
      </svg>
    </span>
  );
}

/* ============================================================
   Agent state machine (shared via context)
   phase: idle | engaged | listening | thinking | answering
   ============================================================ */
const GREETING = "Hi — I'm ALM, the Affordability Language Model behind Afford-X. Ask me anything about exclusion filters, segments, or how we make intent better.";
const SUGGESTIONS = [
  'What is the Exclusion Filter?',
  'How does ALM score affordability?',
  'Which industries do you serve?',
];

const SYS_PROMPT = `You are ALM, the Affordability Language Model — the AI agent that powers Afford-X, a martech platform.
Afford-X scores audiences on real purchasing power (not just intent) and offers a first-in-market one-click exclusion filter that removes window-shoppers before a campaign launches.
Key facts you can draw on: nearly 1 billion U.S. MAIDs and HEMs across 100+ data segments (income, credit, purchase behavior, intent); a Dollar Scoring Framework; GDPR/CCPA/LGPD compliant, consented/pseudonymized signals; verticals served include auto, luxury, financial services and e-commerce; tagline "We Make Intent Better."
Voice: confident, modern, benefit-led B2B. Speak to the visitor as "you", refer to Afford-X as "we". Keep replies under 70 words, no emoji, no markdown headers. Be concrete and helpful.`;

const AgentCtx = createContext(null);
const useAgent = () => useContext(AgentCtx);
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

function AgentProvider({ children }) {
  const [open, setOpen] = useState(false);
  const [phase, setPhase] = useState('idle');
  const [messages, setMessages] = useState([{ role: 'assistant', content: GREETING }]);
  const [draft, setDraft] = useState('');
  const busyRef = useRef(false);

  const openWidget = useCallback(() => {
    setOpen(true);
    setPhase((p) => (p === 'idle' ? 'engaged' : p));
  }, []);
  const closeWidget = useCallback(() => {
    setOpen(false);
    if (!busyRef.current) setPhase('idle');
  }, []);

  // listening reacts to visitor typing
  const onDraft = useCallback((v) => {
    setDraft(v);
    if (busyRef.current) return;
    setPhase(v.trim() ? 'listening' : 'engaged');
  }, []);

  const ask = useCallback(async (qRaw) => {
    const q = (qRaw == null ? draft : qRaw).trim();
    if (!q || busyRef.current) return;
    busyRef.current = true;
    setDraft('');
    setMessages((m) => [...m, { role: 'user', content: q }]);
    setPhase('thinking');

    // build short conversation context
    const history = messages.filter((m) => m.role === 'user' || m.role === 'assistant').slice(-6)
      .map((m) => `${m.role === 'user' ? 'Visitor' : 'ALM'}: ${m.content}`).join('\n');
    const prompt = `${SYS_PROMPT}\n\n${history ? 'Conversation so far:\n' + history + '\n\n' : ''}Visitor: ${q}\nALM:`;

    let reply = '';
    try {
      if (window.claude && window.claude.complete) {
        reply = await window.claude.complete(prompt);
      } else {
        throw new Error('no-api');
      }
    } catch (e) {
      reply = "We narrow your intent audience down to people with real purchasing power — our one-click Exclusion Filter removes window-shoppers before launch, so every ad dollar works harder. (Live answers activate when this page is shared.)";
      await sleep(900);
    }
    reply = (reply || '').trim();

    // stream the reply word-by-word for the "answering" state
    setPhase('answering');
    setMessages((m) => [...m, { role: 'assistant', content: '' }]);
    const parts = reply.split(/(\s+)/);
    let acc = '';
    for (const w of parts) {
      acc += w;
      setMessages((m) => { const c = m.slice(); c[c.length - 1] = { role: 'assistant', content: acc }; return c; });
      await sleep(24);
    }
    busyRef.current = false;
    setPhase(open ? 'engaged' : 'idle');
  }, [draft, messages, open]);

  const value = { open, phase, messages, draft, openWidget, closeWidget, onDraft, ask, busy: () => busyRef.current };
  return <AgentCtx.Provider value={value}>{children}</AgentCtx.Provider>;
}

/* ============================================================
   Header indicator — "Ask ALM" pill that reflects live state
   ============================================================ */
const LABELS = {
  idle: 'Ask ALM',
  engaged: 'ALM is here',
  listening: 'Listening…',
  thinking: 'Thinking…',
  answering: 'Answering…',
};
const DOT_COLOR = {
  idle: 'var(--afx-gray-400)',
  engaged: 'var(--afx-green-500)',
  listening: 'var(--afx-green-500)',
  thinking: 'var(--afx-yellow)',
  answering: 'var(--afx-green-500)',
};

function HeaderAgent() {
  const { phase, open, openWidget, closeWidget } = useAgent();
  const active = phase !== 'idle';
  return (
    <button
      onClick={open ? closeWidget : openWidget}
      style={{
        display: 'inline-flex', alignItems: 'center', gap: 9, cursor: 'pointer',
        height: 40, padding: '0 14px 0 10px', borderRadius: 999,
        border: `1.5px solid ${active ? 'var(--afx-green-500)' : 'var(--afx-gray-200)'}`,
        background: active ? 'var(--afx-green-50)' : '#fff',
        fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 14,
        color: 'var(--afx-ink)', transition: 'border-color 0.18s ease, background 0.18s ease',
      }}
    >
      <AlmMark size={22} state={phase} id="hdr" />
      <span style={{ minWidth: 78, textAlign: 'left' }}>{LABELS[phase]}</span>
      <span className={active ? 'alm-dot' : ''} style={{ width: 8, height: 8, borderRadius: '50%', background: DOT_COLOR[phase], color: DOT_COLOR[phase], display: 'inline-block' }} />
    </button>
  );
}

/* ============================================================
   Floating widget — bottom-right bubble + chat panel
   ============================================================ */
function Bubble() {
  const { open, phase, openWidget } = useAgent();
  if (open) return null;
  const busy = phase === 'thinking' || phase === 'answering';
  return (
    <button
      onClick={openWidget}
      aria-label="Open ALM assistant"
      style={{
        position: 'fixed', right: 26, bottom: 26, zIndex: 60,
        width: 62, height: 62, borderRadius: '50%', cursor: 'pointer', border: 'none',
        background: 'linear-gradient(135deg, var(--afx-green-400), var(--afx-green-600))',
        boxShadow: '0 10px 28px rgba(42,87,52,0.34)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}
    >
      {!busy && <span className="alm-bubble-ring" />}
      <AlmMark size={32} state={phase} tone="white" id="bub" />
    </button>
  );
}

function SubLine({ phase }) {
  if (phase === 'thinking') return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
      Thinking <span className="alm-think-dots"><span></span><span></span><span></span></span>
    </span>
  );
  if (phase === 'answering') return <span>Answering…</span>;
  if (phase === 'listening') return <span>Listening…</span>;
  return <span>Online · replies in seconds</span>;
}

function Panel() {
  const { open, phase, messages, draft, closeWidget, onDraft, ask, busy } = useAgent();
  const scrollRef = useRef(null);
  const inputRef = useRef(null);
  useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [messages, phase, open]);
  useEffect(() => { if (open && inputRef.current) inputRef.current.focus(); }, [open]);
  if (!open) return null;
  const isBusy = busy();

  return (
    <div className="alm-panel" style={{
      position: 'fixed', right: 26, bottom: 26, zIndex: 60,
      width: 380, maxWidth: 'calc(100vw - 32px)', height: 560, maxHeight: 'calc(100vh - 52px)',
      background: '#fff', borderRadius: 18, overflow: 'hidden',
      border: '1px solid var(--afx-gray-200)', boxShadow: '0 24px 60px rgba(5,7,8,0.22)',
      display: 'flex', flexDirection: 'column',
    }}>
      {/* header */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '14px 16px', background: 'linear-gradient(135deg, #0c2414, #061a0e)', color: '#fff' }}>
        <div style={{ width: 42, height: 42, borderRadius: 12, background: 'rgba(255,255,255,0.08)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <AlmMark size={26} state={phase} tone="white" id="pnl" />
        </div>
        <div style={{ flex: 1, lineHeight: 1.2 }}>
          <div style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 16 }}>ALM</div>
          <div style={{ fontSize: 12, opacity: 0.85 }}><SubLine phase={phase} /></div>
        </div>
        <button onClick={closeWidget} aria-label="Close" style={{ background: 'rgba(255,255,255,0.1)', border: 'none', color: '#fff', width: 30, height: 30, borderRadius: 8, cursor: 'pointer', fontSize: 18, lineHeight: 1 }}>×</button>
      </div>

      {/* messages */}
      <div ref={scrollRef} className="alm-scroll" style={{ flex: 1, overflowY: 'auto', padding: '18px 16px', background: 'var(--afx-gray-50)', display: 'flex', flexDirection: 'column', gap: 12 }}>
        {messages.map((m, i) => (
          <div key={i} className="alm-msg" style={{ display: 'flex', justifyContent: m.role === 'user' ? 'flex-end' : 'flex-start' }}>
            <div style={{
              maxWidth: '82%', padding: '10px 13px', fontSize: 14, lineHeight: 1.5,
              fontFamily: 'var(--font-body)',
              borderRadius: m.role === 'user' ? '14px 14px 4px 14px' : '14px 14px 14px 4px',
              background: m.role === 'user' ? 'var(--afx-green-500)' : '#fff',
              color: m.role === 'user' ? '#fff' : 'var(--afx-gray-700)',
              border: m.role === 'user' ? 'none' : '1px solid var(--afx-gray-200)',
              boxShadow: m.role === 'user' ? 'none' : '0 1px 2px rgba(5,7,8,0.04)',
            }}>{m.content || '\u200b'}</div>
          </div>
        ))}
        {phase === 'thinking' && (
          <div className="alm-msg" style={{ display: 'flex', justifyContent: 'flex-start' }}>
            <div style={{ padding: '12px 14px', background: '#fff', border: '1px solid var(--afx-gray-200)', borderRadius: '14px 14px 14px 4px', display: 'flex', alignItems: 'center', gap: 4 }}>
              <span className="alm-think-dots"><span></span><span></span><span></span></span>
            </div>
          </div>
        )}
        {messages.length <= 1 && (
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginTop: 4 }}>
            {SUGGESTIONS.map((s) => (
              <button key={s} className="alm-chip" onClick={() => ask(s)} style={{
                padding: '7px 12px', borderRadius: 999, fontSize: 13, fontFamily: 'var(--font-body)',
                background: '#fff', border: '1px solid var(--afx-gray-300)', color: 'var(--afx-green-700)', cursor: 'pointer',
              }}>{s}</button>
            ))}
          </div>
        )}
      </div>

      {/* input */}
      <form onSubmit={(e) => { e.preventDefault(); ask(); }} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: 12, borderTop: '1px solid var(--afx-gray-200)', background: '#fff' }}>
        <input
          ref={inputRef}
          value={draft}
          onChange={(e) => onDraft(e.target.value)}
          placeholder={isBusy ? 'ALM is responding…' : 'Ask about Afford-X…'}
          disabled={isBusy}
          style={{
            flex: 1, height: 42, padding: '0 14px', borderRadius: 999, fontSize: 14, fontFamily: 'var(--font-body)',
            border: '1.5px solid var(--afx-gray-200)', outline: 'none', color: 'var(--afx-ink)', background: 'var(--afx-gray-50)',
          }}
          onFocus={(e) => (e.target.style.borderColor = 'var(--afx-green-500)')}
          onBlur={(e) => (e.target.style.borderColor = 'var(--afx-gray-200)')}
        />
        <button type="submit" disabled={isBusy || !draft.trim()} aria-label="Send" style={{
          width: 42, height: 42, borderRadius: '50%', border: 'none', flexShrink: 0,
          cursor: isBusy || !draft.trim() ? 'default' : 'pointer',
          background: !draft.trim() || isBusy ? 'var(--afx-gray-200)' : 'var(--afx-green-500)',
          color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center',
          transition: 'background 0.15s ease',
        }}>
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
        </button>
      </form>
    </div>
  );
}

function AgentWidget() {
  return <><Bubble /><Panel /></>;
}

Object.assign(window, { AgentProvider, useAgent, HeaderAgent, AgentWidget, AlmMark });
// Afford-X · shared site chrome for blog pages (header + footer).
const { Button } = window.AffordXDesignSystem_998110;
const { HeaderAgent } = window;
const CHROME_A = 'assets/';
// resolve assets via the inliner's __resources when bundled offline, else fall back to the file path
const CHROME_RES = (id, path) => (window.__resources && window.__resources[id]) || path;

const SITE_NAV = [
  { label: 'Product Highlights', href: '/' },
  { label: 'How Afford-X Works', href: '/' },
  { label: 'Blog', href: '/blog' },
  { label: 'Pricing', href: '/pricing' },
];

function SiteHeader({ current }) {
  return (
    <header style={{ position: 'sticky', top: 0, zIndex: 30, background: 'rgba(255,255,255,0.92)', backdropFilter: 'blur(8px)', borderBottom: '1px solid var(--afx-gray-200)' }}>
      <div style={{ maxWidth: 1200, margin: '0 auto', padding: '0 28px', height: 72, display: 'flex', alignItems: 'center', gap: 32 }}>
        <a href="/"><img src={CHROME_RES('logo', CHROME_A + 'logo.png')} alt="Afford-X" style={{ height: 30, display: 'block' }} /></a>
        <nav style={{ display: 'flex', gap: 28, marginLeft: 12 }}>
          {SITE_NAV.map((l) => {
            const active = l.label === current;
            return <a key={l.label} href={l.href} style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 14, color: active ? 'var(--afx-green-700)' : 'var(--afx-gray-600)', textDecoration: 'none' }}>{l.label}</a>;
          })}
        </nav>
        <div style={{ marginLeft: 'auto', display: 'flex', gap: 12, alignItems: 'center' }}>
          <HeaderAgent />
          <Button variant="primary" size="sm">Contact us</Button>
        </div>
      </div>
    </header>
  );
}

function SiteFooter() {
  return (
    <footer style={{ background: 'var(--afx-black)', color: 'var(--afx-gray-400)' }}>
      <div style={{ maxWidth: 1200, margin: '0 auto', padding: '48px 28px', display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 24, flexWrap: 'wrap' }}>
        <div style={{ background: '#fff', borderRadius: 'var(--radius-md)', padding: '12px 18px' }}><img src={CHROME_RES('logo', CHROME_A + 'logo.png')} alt="Afford-X" style={{ height: 26, display: 'block' }} /></div>
        <div style={{ display: 'flex', gap: 24, fontFamily: 'var(--font-display)', fontSize: 14 }}>
          {['Product Highlights', 'How Afford-X Works', 'Terms & Conditions', 'Privacy Policy'].map((l) => <a key={l} href="#" style={{ color: 'var(--afx-gray-400)', textDecoration: 'none' }}>{l}</a>)}
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <span style={{ fontSize: 13 }}>Find us on</span>
          <span style={{ width: 34, height: 34, borderRadius: 'var(--radius-sm)', background: '#fff', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
            <img src={CHROME_RES('linkedin', CHROME_A + 'linkedin.svg')} alt="LinkedIn" style={{ width: 18, height: 18 }} />
          </span>
        </div>
      </div>
    </footer>
  );
}

function CtaBand() {
  return (
    <section style={{ background: 'var(--afx-green-500)' }}>
      <div style={{ maxWidth: 1000, margin: '0 auto', padding: '60px 28px', textAlign: 'center', color: '#fff' }}>
        <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 36, letterSpacing: '-0.02em', margin: '0 0 12px', color: '#fff' }}>Affordability Makes Intent Better</h2>
        <p style={{ fontSize: 17, opacity: 0.95, margin: '0 0 26px' }}>Your efficiency accelerator — because real buyers drive real results.</p>
        <div style={{ display: 'flex', gap: 12, justifyContent: 'center' }}>
          <Button variant="danger" size="lg">Free Evaluation</Button>
          <Button variant="secondary" size="lg" style={{ background: 'rgba(255,255,255,0.12)', borderColor: '#fff', color: '#fff' }}>Contact us</Button>
        </div>
      </div>
    </section>
  );
}

// shared category tones + avatar
const CAT_TONE = { Perspective: 'neutral', Product: 'green', 'Data Science': 'slate', Industry: 'yellow', Privacy: 'red' };
function Avatar({ name, size = 38 }) {
  const initials = name.split(' ').map((p) => p[0]).slice(0, 2).join('');
  return (
    <span style={{ width: size, height: size, borderRadius: '50%', flexShrink: 0, background: 'var(--afx-green-100)', color: 'var(--afx-green-700)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: size * 0.36 }}>{initials}</span>
  );
}

Object.assign(window, { SiteHeader, SiteFooter, CtaBand, CAT_TONE, Avatar });
// Afford-X · blog article (content) page.
const { Badge, Button } = window.AffordXDesignSystem_998110;
const { AgentProvider, AgentWidget, SiteHeader, SiteFooter, CtaBand, CAT_TONE, Avatar, useAgent } = window;
const POSTS = window.AFX_POSTS;
const POST = POSTS.find((p) => p.slug === 'intent-isnt-enough');
const BLOG = '/blog';

function ArticleHero() {
  return (
    <header style={{ maxWidth: 760, margin: '0 auto', padding: '56px 28px 28px', textAlign: 'center', position: 'relative' }}>
      <a href={BLOG} style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 13.5, color: 'var(--afx-green-700)', textDecoration: 'none' }}>← Back to the Journal</a>
      <div style={{ display: 'flex', justifyContent: 'center', marginTop: 22, marginBottom: 18 }}>
        <Badge tone={CAT_TONE[POST.cat]}>{POST.cat}</Badge>
      </div>
      <h1 style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 46, lineHeight: 1.1, letterSpacing: '-0.03em', color: 'var(--afx-ink)', margin: '0 0 18px' }}>{POST.title}</h1>
      <p style={{ fontSize: 19, lineHeight: 1.6, color: 'var(--afx-gray-600)', margin: '0 auto', maxWidth: 600 }}>
        Most campaigns still target the people most likely to be <em>interested</em>. The ones that win target the people most likely to <em>buy</em>.
      </p>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 12, marginTop: 26 }}>
        <Avatar name={POST.author} size={44} />
        <div style={{ textAlign: 'left', lineHeight: 1.35 }}>
          <div style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 15, color: 'var(--afx-ink)' }}>{POST.author}</div>
          <div style={{ fontSize: 13, color: 'var(--afx-gray-500)' }}>{POST.role} · {POST.date} · {POST.read}</div>
        </div>
      </div>
    </header>
  );
}

function StatCallout() {
  const stats = [['~1B', 'U.S. MAIDs & HEMs scored'], ['100+', 'behavioral & financial segments'], ['1 click', 'to exclude window-shoppers']];
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 16, margin: '36px 0' }}>
      {stats.map(([n, l]) => (
        <div key={l} style={{ background: 'var(--afx-green-50)', border: '1px solid var(--afx-green-100)', borderRadius: 14, padding: '22px 18px', textAlign: 'center' }}>
          <div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 32, letterSpacing: '-0.02em', color: 'var(--afx-green-700)' }}>{n}</div>
          <div style={{ fontSize: 13.5, color: 'var(--afx-gray-600)', marginTop: 4, lineHeight: 1.4 }}>{l}</div>
        </div>
      ))}
    </div>
  );
}

function PullQuote({ children }) {
  return (
    <blockquote style={{ margin: '36px 0', padding: '6px 0 6px 26px', borderLeft: '4px solid var(--afx-green-500)' }}>
      <p style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 24, lineHeight: 1.35, letterSpacing: '-0.01em', color: 'var(--afx-ink)', margin: 0 }}>{children}</p>
    </blockquote>
  );
}

function AskAlmInline() {
  const agent = useAgent();
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 16, background: 'linear-gradient(135deg,#0c2414,#061a0e)', borderRadius: 16, padding: '22px 24px', margin: '40px 0', color: '#fff' }}>
      <window.AlmMark size={34} state="engaged" tone="white" id="art" />
      <div style={{ flex: 1 }}>
        <div style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 16 }}>Curious how this applies to your campaign?</div>
        <div style={{ fontSize: 13.5, opacity: 0.82 }}>Ask ALM — it can size the affordability lift for your audience.</div>
      </div>
      <Button size="md" style={{ background: '#fff', color: 'var(--afx-green-700)', border: 'none' }} onClick={() => agent.openWidget()}>Ask ALM</Button>
    </div>
  );
}

function ArticleBody() {
  return (
    <article className="prose" style={{ maxWidth: 720, margin: '0 auto', padding: '0 28px' }}>
      <p>For a decade, intent has been the gold standard of audience targeting. Someone searches for a mid-size SUV, reads three reviews, and lands in an in-market segment. The logic feels airtight: interest predicts action. But anyone who has watched a high-intent campaign underdeliver knows the uncomfortable truth — <strong>interest and ability are not the same thing</strong>.</p>
      <p>A shopper can want a $58,000 vehicle and have no realistic path to financing it. Multiply that across an audience and a meaningful slice of every "high-intent" buy is spent reaching people who were never going to convert. Intent platforms can't see this, because the signal they're built on stops at curiosity.</p>

      <StatCallout />

      <h2>The window-shopper problem</h2>
      <p>Window-shoppers don't look any different from buyers in an intent model. They click, they compare, they linger — they generate exactly the behavioral signals intent targeting rewards. The result is an audience that looks strong on paper and dilutes the moment budget meets reality.</p>
      <ul>
        <li>Impressions are spent on people who can browse but not buy.</li>
        <li>Conversion rates sag, so CPA climbs even when intent looks healthy.</li>
        <li>Optimization algorithms chase the wrong signal and reinforce it.</li>
      </ul>

      <PullQuote>"Intent tells you who is looking. Affordability tells you who can act. The gap between the two is where ad budgets quietly leak."</PullQuote>

      <h2>Adding the missing layer</h2>
      <p>The fix isn't to throw out intent — it's to add the layer intent was always missing. The <strong>Affordability Language Model (ALM)</strong> scores each user on real purchasing power by combining privacy-compliant financial signals with behavioral and purchase-history data through our <a href="#">Dollar Scoring Framework</a>.</p>
      <p>From there, the first-in-market <strong>Exclusion Filter</strong> does the obvious thing intent platforms can't: it removes the people who can't realistically convert <em>before</em> the campaign launches. One click narrows an intent audience down to the share with genuine ability to buy.</p>

      <AskAlmInline />

      <h2>What changes when you target ability</h2>
      <p>When affordability sits alongside intent, the same media budget reaches a denser, more convertible audience. Sharper targeting raises efficiency, segments get simpler, and optimization finally chases a signal that maps to revenue instead of curiosity.</p>
      <p>Intent isn't wrong. It's just incomplete. Pair it with affordability and you stop paying to reach people who were only ever browsing — and start spending where real buyers are.</p>
    </article>
  );
}

function AuthorBio() {
  return (
    <div style={{ maxWidth: 720, margin: '44px auto 0', padding: '0 28px' }}>
      <div style={{ display: 'flex', gap: 16, alignItems: 'center', background: 'var(--afx-gray-50)', border: '1px solid var(--afx-gray-200)', borderRadius: 16, padding: '22px 24px' }}>
        <Avatar name={POST.author} size={56} />
        <div>
          <div style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 16, color: 'var(--afx-ink)' }}>{POST.author}</div>
          <div style={{ fontSize: 13.5, color: 'var(--afx-green-700)', marginBottom: 6 }}>{POST.role}, Afford-X</div>
          <p style={{ fontSize: 14, lineHeight: 1.55, color: 'var(--afx-gray-600)', margin: 0 }}>Maya leads product at Afford-X, where she's focused on turning affordability signals into one-click decisions for advertisers.</p>
        </div>
      </div>
    </div>
  );
}

function Related() {
  const items = POSTS.filter((p) => p.slug !== POST.slug).slice(0, 3);
  return (
    <section style={{ maxWidth: 1120, margin: '64px auto 0', padding: '0 28px' }}>
      <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 24, letterSpacing: '-0.02em', color: 'var(--afx-ink)', margin: '0 0 22px' }}>Keep reading</h2>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 22 }}>
        {items.map((p) => (
          <a key={p.slug} href="/blog-posts" className="blog-card" style={{ display: 'flex', flexDirection: 'column', textDecoration: 'none', background: '#fff', border: '1px solid var(--afx-gray-200)', borderRadius: 16, overflow: 'hidden' }}>
            <div className="blog-thumb">
              <image-slot id={'blog-thumb-' + p.slug} shape="rect" placeholder="Drop post image" style={{ display: 'block', width: '100%', height: 160, background: 'var(--afx-green-50)' }}></image-slot>
            </div>
            <div style={{ padding: '18px 18px 20px' }}>
              <Badge tone={CAT_TONE[p.cat]} style={{ marginBottom: 10 }}>{p.cat}</Badge>
              <h3 className="blog-title" style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 17, lineHeight: 1.25, letterSpacing: '-0.015em', color: 'var(--afx-ink)', margin: 0, transition: 'color 0.15s ease' }}>{p.title}</h3>
              <div style={{ fontSize: 12.5, color: 'var(--afx-gray-500)', marginTop: 10 }}>{p.date} · {p.read}</div>
            </div>
          </a>
        ))}
      </div>
    </section>
  );
}

function ArticlePage() {
  return (
    <AgentProvider>
      <div style={{ background: '#fff' }}>
        <SiteHeader current="Blog" />
        <ArticleHero />
        <div style={{ maxWidth: 1000, margin: '0 auto', padding: '0 28px 40px' }}>
          <image-slot id="article-cover" shape="rounded" radius="18" placeholder="Drop cover image" style={{ display: 'block', width: '100%', height: 440, background: 'var(--afx-green-50)' }}></image-slot>
        </div>
        <ArticleBody />
        <AuthorBio />
        <Related />
        <div style={{ height: 64 }} />
        <CtaBand />
        <SiteFooter />
      </div>
      <AgentWidget />
    </AgentProvider>
  );
}

Object.assign(window, { ArticlePage });

// auto-render
document.body.innerHTML = '<div id="afx-root"></div>';
ReactDOM.createRoot(document.getElementById('afx-root')).render(<window.ArticlePage />);
