// CaseStudies v4, "CASE STUDIES" label, punchy 2-3 sentence summaries, rich story modals
const { useRef: useCsRef, useEffect: useCsEffect, useState: useCsState } = React;

const ALL_CASES = [
  // REAL (verified)
  {
    id: 'b2b-outbound',
    tag: '// B2B MARKETING & SALES',
    industry: 'B2B SaaS',
    headline: 'Tripled qualified pipeline at a fraction of SDR cost.',
    summary: 'Their SDR team was writing 200 emails a week and booking 3 meetings. We built an AI personalization engine that reads intent signals, crafts first-touch messages per persona, and routes warm replies straight to closers. Pipeline tripled. The team now only closes.',
    metric: '$85K', metricNum: 85, metricDecimal: false,
    subMetric: '3× qualified leads · higher reply rates',
    color: '#00D9A0',
    status: 'Live in production',
    verified: true,
    detail: {
      situation: 'A growth-stage B2B SaaS company with a 4-person SDR team. Strong product, strong ICP, but pipeline was inconsistent and cost-per-meeting was climbing month on month. Reps were spending more time on research and outreach than on calls.',
      problem: 'Manual prospecting is a solved problem, AI can do it better, faster, and at scale. But this team was still writing bespoke sequences by hand, guessing at persona fit, and letting warm replies sit in an inbox for 6–12 hours. Senior AEs were context-switching between closing deals and chasing cold leads. The pipeline wasn\'t the problem. The system feeding it was.',
      built: [
        'LLM personalization layer crafting first-touch emails per prospect using firmographic + intent signals, not mail-merge, actual reasoning about why this person, why now',
        'Apify-based enrichment pipeline pulling prospect data from 5+ sources and scoring against ICP criteria automatically',
        'Multi-step sequence orchestration across email and LinkedIn, timing, channel mix, and follow-up logic all handled by the system',
        'Intent-based reply classifier routing warm signals to AEs instantly, cold replies to nurture tracks, unsubscribes handled automatically',
        'Weekly feedback loop: reply pattern analysis feeds back into the system, improving open rates and messaging quality over time',
      ],
      impact: [
        '3× increase in qualified pipeline within 90 days of launch',
        'Reply rates up, cost-per-meeting down significantly',
        'SDR team fully shifted from prospecting to closing, zero manual outreach',
        'System runs 24/7 with no human input beyond weekly review',
      ],
      delivered: [
        'Production AI outbound system, deployed, running, fully owned by client',
        'Prospect enrichment pipeline (Apify + firmographic sources)',
        'LinkedIn + email sequence orchestration engine',
        'Reply classification and routing system',
        'Weekly performance dashboard with LLM-generated insights',
      ],
      outcome: 'The SDR team became a closing team. Prospecting stopped being a headcount problem and became a system problem, which we solved once, permanently.',
      stack: ['Anthropic Claude', 'Apify', 'Gmail API', 'LinkedIn API', 'PostgreSQL', 'HubSpot'],
    },
  },
  {
    id: 'workforce-risk',
    tag: '// LOGISTICS & SUPPLY CHAIN',
    industry: 'Logistics',
    headline: '$1.2M recovered in 6 months by a risk system that never sleeps.',
    summary: 'Six workforce systems feeding data into spreadsheets nobody trusted. By the time ops teams spotted a pattern, the damage was already absorbed, $200K+ per incident. We built a risk intelligence layer that watches everything in real time, surfaces anomalies before they escalate, and replaced four hours of manual reporting with one live dashboard.',
    metric: '$1.2M', metricNum: 1.2, metricDecimal: true,
    subMetric: '68% fewer incidents · 40% less manual ops',
    color: '#8B5CF6',
    status: 'Live · 6 months running',
    verified: true,
    detail: {
      situation: 'A logistics operator managing 800+ field workers across multiple regions. Six separate systems, workforce scheduling, route management, incident logging, HR, payroll, and a CRM, none of them talking to each other. Ops managers were running end-of-day reports by hand and making decisions on yesterday\'s data.',
      problem: 'Risk in logistics is a timing problem. By the time a human spots a pattern, a driver cluster with rising incident rates, a scheduling anomaly correlating with overtime costs, a region trending toward compliance risk, the cost is already absorbed. The team knew they had a data problem. They didn\'t know they had an AI problem until we mapped it.',
      built: [
        'Real-time data ingestion layer connecting all 6 workforce and scheduling systems into a unified event stream',
        'LLM-powered anomaly detection engine that surfaces risk signals with plain-language explanations, not just alerts, but "here\'s why this matters and what to do"',
        'Custom risk dashboard with live feeds, regional drill-down, and incident trend visualisation, built for ops managers who don\'t have time to learn new software',
        'Automated weekly risk briefing replacing 4+ hours of manual work, delivered every Monday at 7am, actionable by 8am',
        'Proactive escalation system routing high-priority signals to the right manager within minutes of detection',
      ],
      impact: [
        '$1.2M in direct cost recovery in the first 6 months',
        '68% reduction in preventable incidents quarter-on-quarter',
        '40% reduction in manual ops workload across the team',
        'Average response time to risk signals cut from 14 hours to under 30 minutes',
      ],
      delivered: [
        'Production risk intelligence system, live, monitored, 99.97% uptime',
        'Unified data ingestion pipeline across 6 source systems',
        'LLM anomaly detection and explanation engine',
        'Live risk dashboard (React + FastAPI)',
        'Automated weekly briefing pipeline',
        'Alert routing and escalation system',
      ],
      outcome: 'Operations shifted from reactive to predictive. The team stopped absorbing costs after the fact and started intervening before incidents happen. The system paid for itself in week three.',
      stack: ['Anthropic Claude', 'Python', 'FastAPI', 'PostgreSQL', 'React', 'AWS', 'Langfuse'],
    },
  },
  {
    id: 'ai-recruitment',
    tag: '// STAFFING & RECRUITMENT',
    industry: 'Staffing',
    headline: 'Time-to-hire cut in half with an AI recruiter that works 24/7.',
    summary: 'Recruiters were spending 70% of their week on tasks that don\'t require a human, sourcing, screening, scheduling. The best candidates were moving on while still sitting in the inbox. We replaced that with a three-agent pipeline that runs around the clock, only handing off to humans when a candidate genuinely needs one.',
    metric: '$124K+', metricNum: 124, metricDecimal: false,
    subMetric: '50% faster time-to-hire',
    color: '#F59E0B',
    status: 'Live in production',
    verified: true,
    detail: {
      situation: 'A staffing agency placing mid-to-senior roles across tech and operations. 6 recruiters handling 40+ active roles at any time. Strong candidate relationships, but the front end of the funnel (sourcing, initial screening, scheduling) was eating time that should have gone into placement strategy.',
      problem: 'Recruiter throughput is capped by the number of hours in a day. Sourcing 5 platforms, writing personalised outreach, screening 80 CVs, and coordinating 20 interview schedules, every week, by hand. The best candidates were making decisions in 48 hours. The team\'s average first-touch response was longer than that. They weren\'t losing on quality. They were losing on speed.',
      built: [
        'Sourcing agent that pulls candidates from 5+ platforms (LinkedIn, Indeed, GitHub, AngelList, internal DB) against a structured role specification, ranked by weighted criteria, not keyword matching',
        'Screening agent that evaluates CVs with explicit reasoning: strengths, gaps, fit score, and a plain-language brief for the recruiter to review in 2 minutes',
        'Scheduling agent that handles all interview coordination via calendar APIs, availability checks, slot proposals, confirmations, and reminders, zero human involvement',
        'ATS sync keeping all candidate data in the existing system of record, no parallel database, no extra login, no change management problem',
      ],
      impact: [
        '50% reduction in time-to-hire across all active roles',
        'Recruiter capacity effectively doubled without a single new hire',
        'Candidate experience measurably improved, faster responses, more consistent communication',
        '$124K+ in efficiency gains in year one, with compounding returns as volume scales',
      ],
      delivered: [
        'Three-agent recruitment pipeline, sourcing, screening, scheduling',
        'Multi-platform candidate sourcing system (5 sources)',
        'LLM-powered CV screening with explainable reasoning',
        'Calendar API integration for end-to-end scheduling automation',
        'ATS sync (existing system of record)',
        'Recruiter review dashboard with override controls',
      ],
      outcome: 'Recruiter capacity doubled without adding headcount. The team now focuses on relationships, negotiation, and placement strategy, the work that actually requires a human. The pipeline feeds itself.',
      stack: ['OpenAI', 'Python', 'FastAPI', 'Calendar APIs', 'LinkedIn API', 'PostgreSQL'],
    },
  },
  // REPRESENTATIVE BUILDS
  {
    id: 'medspa-rebooking',
    tag: '// MED SPA',
    industry: 'Med Spa',
    headline: 'AI receptionist eliminated 40% of no-shows and fills every cancellation gap.',
    summary: 'Every missed call during a treatment is a $400 appointment walking straight to a competitor. After-hours DMs go cold. No-shows crater daily revenue with no system to recover them. We built an AI receptionist that answers every channel 24/7, recovers no-shows within 10 minutes, and fills cancellation gaps automatically, without touching front desk time.',
    metric: '$180K', metricNum: 180, metricDecimal: false,
    subMetric: '40% fewer no-shows · 300+ bookings/month automated',
    color: '#00D9A0',
    status: 'Representative build',
    verified: false,
    detail: {
      situation: 'A high-volume med spa with 3 locations doing 600+ appointments per month. Talented practitioners, strong repeat business, but the front desk was the bottleneck. Calls during treatments went unanswered. Instagram DMs accumulated overnight. No-shows were happening daily with no automated recovery.',
      problem: 'Every missed call during a treatment is a lost booking, a $300–$600 appointment that goes to the next option on Google. After-hours inquiries went cold because nobody was there to respond. No-shows happened, revenue evaporated, and the gap stayed unfilled because there was no system to broadcast availability to a waitlist. The front desk was running at full capacity doing work that didn\'t need a human.',
      built: [
        '24/7 AI receptionist handling inbound calls, SMS, and Instagram DMs, qualifies interest, answers common questions, and completes bookings without human involvement',
        'No-show recovery agent that detects a missed appointment and fires a rebooking sequence within 10 minutes, personalised by client history, not a generic blast',
        'Pre-visit confirmation and upsell sequences tailored to each client\'s service history, sent at the right time without staff involvement',
        'Cancellation gap-filler that broadcasts open slots to the waitlist automatically the moment a booking is cancelled, average gap-fill time under 20 minutes',
      ],
      impact: [
        '40% reduction in no-shows within 60 days of launch',
        '300+ bookings per month handled fully autonomously',
        'Front desk time on booking management reduced by ~60%',
        'After-hours leads converted at the same rate as business-hours inquiries',
      ],
      delivered: [
        'AI receptionist system (call, SMS, Instagram DM)',
        'No-show detection and rebooking automation',
        'Waitlist gap-filling broadcast system',
        'Pre-visit and upsell sequence engine',
        'Booking platform integration (GoHighLevel)',
      ],
      outcome: 'The front desk stopped being the bottleneck. Every lead gets a response. Every cancellation gets filled. Every no-show gets a recovery attempt within minutes. The system pays for itself every week.',
      stack: ['Twilio', 'Anthropic Claude', 'GoHighLevel', 'n8n', 'Firebase'],
    },
  },
  {
    id: 'realestate-leads',
    tag: '// REAL ESTATE',
    industry: 'Real Estate',
    headline: '90-second lead response time. 3× more qualified showings. Same team.',
    summary: '78% of buyers sign with the first agent who responds, this team\'s average was 4 hours. Listing descriptions were taking 2 hours each. Transaction coordinators were drowning in scheduling. We rebuilt the entire acquisition pipeline around AI: instant qualification, auto-generated listings, fully coordinated showings. Same team. Three times the output.',
    metric: '$240K', metricNum: 240, metricDecimal: false,
    subMetric: '< 90s response · 3× qualified showings booked',
    color: '#8B5CF6',
    status: 'Representative build',
    verified: false,
    detail: {
      situation: 'A real estate team doing 80+ transactions per year across residential and investment properties. Strong market reputation, but lead response times were inconsistent, listing production was slow, and transaction coordinators were spending most of their time on logistics rather than client experience.',
      problem: 'In real estate, response speed is a revenue lever. Research shows 78% of buyers work with the first agent who responds. This team\'s average response time was 4 hours. On evenings and weekends, when most buyer inquiries come in, it was longer. Listing descriptions were consuming 2 hours per property. Transaction coordination was drowning in scheduling emails that a system should be handling.',
      built: [
        'Lead qualification agent that responds to web and portal inquiries in under 90 seconds, 24/7, qualifies intent, budget, and timeline before the agent even sees the lead',
        'MLS-connected listing description generator that produces publication-ready copy from raw data and photos in minutes, not hours',
        'Showing scheduler that syncs to all agent calendars, handles availability coordination with buyers, and sends automated reminders, zero admin time',
        'Post-showing follow-up sequences personalised to each buyer\'s stated preferences and viewing history',
      ],
      impact: [
        'Lead response time cut from 4 hours to under 90 seconds, 24/7',
        '3× increase in qualified showings per agent per week',
        'Listing description time reduced from 2 hours to under 10 minutes',
        'Transaction coordinator capacity freed up from scheduling to client experience',
      ],
      delivered: [
        'Lead qualification and instant-response system (SMS + email)',
        'MLS-connected listing description generator',
        'Calendar-integrated showing scheduler',
        'Post-showing personalised follow-up engine',
        'Agent performance dashboard',
      ],
      outcome: 'The team went from losing leads on response speed to having a sustainable acquisition engine. The agents close. The system handles everything before the first handshake.',
      stack: ['Anthropic Claude', 'MLS API', 'Twilio', 'Google Calendar API', 'Zapier', 'Salesforce'],
    },
  },
  {
    id: 'lawfirm-intake',
    tag: '// LAW FIRM',
    industry: 'Law Firm',
    headline: 'Client intake reduced from 3 days to 4 hours. Zero extra headcount.',
    summary: 'New client intake was a 6-step manual process spread across email, DocuSign, and a CRM no one trusted. Each matter took 3 days from enquiry to signed engagement letter, time partners were billing out at £400/hr doing admin. We automated the entire flow. Partners now spend zero time on intake. It runs itself.',
    metric: '12 hrs/wk', metricNum: 12, metricDecimal: false,
    subMetric: '3 days → 4 hours intake · 0 extra staff',
    color: '#F59E0B',
    status: 'Representative build',
    verified: false,
    detail: {
      situation: 'A mid-size law firm handling commercial, property, and employment matters. 12 fee earners, strong client relationships, but new client intake was visibly broken. Partners knew it, paralegals hated it, and prospective clients were forming their first impression through a process that made the firm look disorganised.',
      problem: 'Six manual steps: initial enquiry email, conflict check (manual), engagement letter draft (from a template, by hand), DocuSign send, follow-up chase, CRM entry. Average time from enquiry to signed engagement: 3 days. Partners at £400/hr were doing data entry. Paralegals were chasing electronic signatures. New clients were waiting 72 hours to formally start a matter.',
      built: [
        'Intake bot that collects matter details via a structured conversation, runs conflict check against the firm\'s database, and generates an engagement letter draft, all before a human is involved',
        'E-sign integration that pushes documents automatically on intake completion, with smart chase sequences if the client doesn\'t sign within 24 hours',
        'Client portal syncing matter status in real time, eliminates the "where are we?" calls that were consuming 2+ paralegal hours per week',
        'Contract first-draft assistant that cuts senior associate drafting time by 60% on standard matters, not a template, an LLM that understands the matter context',
      ],
      impact: [
        'Intake-to-engagement letter cut from 3 days to under 4 hours',
        'Partners spend zero time on intake administration',
        '"Where are we?" client calls eliminated, portal handles all status queries',
        'Senior associate contract drafting time reduced by ~60% on standard matters',
      ],
      delivered: [
        'New client intake automation (conflict check → engagement letter → e-sign)',
        'Automated e-sign pipeline with smart chase sequences',
        'Client matter status portal',
        'Contract first-draft assistant',
        'Clio CRM integration',
      ],
      outcome: 'Partners redirected from admin to billable work. New clients experience a firm that responds in hours, not days. Intake now runs without human involvement on standard matters.',
      stack: ['Anthropic Claude', 'Clio', 'DocuSign API', 'Twilio', 'n8n', 'PostgreSQL'],
    },
  },
  {
    id: 'cpa-tax',
    tag: '// CPA / ACCOUNTING',
    industry: 'CPA',
    headline: '15+ hours saved per partner weekly during tax season. No new hires.',
    summary: 'Tax season meant every partner buried in workpaper review, 40+ hours of pattern recognition that didn\'t need their expertise. Client onboarding was an email nightmare. IRS notices piled up while staff handled routine queries. We built an AI tax assistant that handles all three, freeing partners to do the advisory work they actually bill for.',
    metric: '$95K', metricNum: 95, metricDecimal: false,
    subMetric: '15+ hrs/partner/week · 99.2% flag accuracy',
    color: '#00D9A0',
    status: 'Representative build',
    verified: false,
    detail: {
      situation: 'A CPA firm with 8 partners handling tax, advisory, and bookkeeping for 200+ business clients. Strong relationships, strong retention, but during tax season, every partner was working 60+ hour weeks and still falling behind. The work wasn\'t hard. It was high-volume and repetitive.',
      problem: 'Workpaper review is mostly pattern recognition, spotting anomalies, checking consistency, flagging items that don\'t add up. That\'s exactly what AI is good at. Instead, partners were doing it by hand, line by line, on hundreds of client files. Client onboarding was a 12-email chain. IRS notices sat in a shared inbox until someone had time. The firm wasn\'t understaffed. It was under-automated.',
      built: [
        'AI workpaper assistant that reviews documents, flags anomalies against prior-year comparisons, surfaces inconsistencies, and produces a prioritised review brief, partners only see what needs their judgment',
        'Client onboarding agent that takes a new engagement from intake to signed letter to first document request, fully automated, with status tracking for the client throughout',
        'IRS/HMRC notice triage system that classifies every notice by urgency and type, drafts a response framework, and routes to the right partner with full context',
        'Client portal with real-time matter status, eliminates status-update calls that were consuming 3+ staff hours per week during peak season',
      ],
      impact: [
        '15+ hours per partner reclaimed weekly during tax season',
        '99.2% flag accuracy on workpaper anomaly detection vs. manual review',
        'Client onboarding reduced from days to same-day',
        'IRS notice response time cut from 3–5 days to under 4 hours',
      ],
      delivered: [
        'AI workpaper review system (anomaly detection + partner brief)',
        'Client onboarding automation pipeline',
        'IRS/HMRC notice classification and response drafting system',
        'Client matter status portal',
        'QuickBooks + Xero integration',
      ],
      outcome: 'Partners redirected 15 hours per week from review to advisory. They stopped doing the work that software should do, and started doing the work that builds the practice.',
      stack: ['Anthropic Claude', 'QuickBooks API', 'Xero API', 'Python', 'FastAPI', 'Azure'],
    },
  },
];

function ReadModal({ cs, onClose }) {
  useCsEffect(() => {
    const handler = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', handler);
    document.body.style.overflow = 'hidden';
    return () => {
      window.removeEventListener('keydown', handler);
      document.body.style.overflow = '';
    };
  }, [onClose]);

  return (
    <div
      onClick={e => { if (e.target === e.currentTarget) onClose(); }}
      style={{
        position: 'fixed', inset: 0, zIndex: 300,
        background: 'rgba(0,0,0,0.75)', backdropFilter: 'blur(10px)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        padding: '20px',
        animation: 'modal-bg-in 0.2s ease',
      }}
    >
      <div style={{
        background: 'var(--bg-secondary)',
        border: `1px solid ${cs.color}40`,
        borderTop: `3px solid ${cs.color}`,
        borderRadius: 18,
        width: '100%', maxWidth: 720,
        maxHeight: '90vh', overflowY: 'auto',
        padding: '40px',
        animation: 'modal-in 0.3s cubic-bezier(0.16,1,0.3,1)',
        scrollbarWidth: 'thin',
      }}>
        {/* Header */}
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 28 }}>
          <div style={{ flex: 1, paddingRight: 20 }}>
            <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 10, color: cs.color, letterSpacing: '0.1em', marginBottom: 10 }}>{cs.tag}</div>
            <h2 style={{ fontFamily: 'Syne, sans-serif', fontSize: 'clamp(20px,2.5vw,28px)', fontWeight: 700, letterSpacing: '-0.02em', lineHeight: 1.2, color: 'var(--text-primary)' }}>{cs.headline}</h2>
          </div>
          <button onClick={onClose} style={{
            background: 'var(--bg-tertiary)', border: '1px solid var(--border-subtle)',
            cursor: 'pointer', color: 'var(--text-tertiary)',
            width: 32, height: 32, borderRadius: 8, flexShrink: 0,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontSize: 16, transition: 'all 0.2s',
          }}
          onMouseEnter={e => { e.currentTarget.style.color = 'var(--text-primary)'; e.currentTarget.style.borderColor = 'var(--border-emphasis)'; }}
          onMouseLeave={e => { e.currentTarget.style.color = 'var(--text-tertiary)'; e.currentTarget.style.borderColor = 'var(--border-subtle)'; }}
          >✕</button>
        </div>

        {/* Metric */}
        <div style={{ display: 'flex', gap: 32, flexWrap: 'wrap', padding: '22px 26px', background: `${cs.color}0A`, border: `1px solid ${cs.color}30`, borderRadius: 12, marginBottom: 32 }}>
          <div>
            <div style={{ fontFamily: 'Syne, sans-serif', fontSize: 52, fontWeight: 700, color: cs.color, lineHeight: 1, letterSpacing: '-0.02em' }}>{cs.metric}</div>
            <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 12, color: 'var(--text-tertiary)', marginTop: 5 }}>{cs.subMetric}</div>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', gap: 6 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 7 }}>
              <span style={{ width: 7, height: 7, borderRadius: '50%', background: cs.verified ? cs.color : 'var(--text-tertiary)', boxShadow: cs.verified ? `0 0 8px ${cs.color}` : 'none' }} />
              <span style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 11, color: cs.verified ? cs.color : 'var(--text-tertiary)' }}>{cs.status}</span>
            </div>
            {!cs.verified && <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 10, color: 'var(--text-tertiary)', paddingLeft: 14 }}>Numbers are representative of this build type</div>}
          </div>
        </div>

        {/* Situation */}
        <ModalSection label="// THE SITUATION" color={cs.color}>
          <p style={{ fontFamily: 'Inter, sans-serif', fontSize: 15, color: 'var(--text-secondary)', lineHeight: 1.75 }}>{cs.detail.situation}</p>
        </ModalSection>

        {/* Problem */}
        <ModalSection label="// THE PROBLEM" color={cs.color}>
          <p style={{ fontFamily: 'Inter, sans-serif', fontSize: 15, color: 'var(--text-secondary)', lineHeight: 1.75 }}>{cs.detail.problem}</p>
        </ModalSection>

        {/* What we built */}
        <ModalSection label="// WHAT WE BUILT" color={cs.color}>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
            {cs.detail.built.map((item, i) => (
              <div key={i} style={{ display: 'flex', gap: 14, alignItems: 'flex-start' }}>
                <span style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 11, color: cs.color, opacity: 0.8, minWidth: 22, marginTop: 2, flexShrink: 0 }}>0{i+1}</span>
                <span style={{ fontFamily: 'Inter, sans-serif', fontSize: 14, color: 'var(--text-primary)', lineHeight: 1.65 }}>{item}</span>
              </div>
            ))}
          </div>
        </ModalSection>

        {/* What they achieved */}
        <ModalSection label="// WHAT THEY ACHIEVED" color={cs.color}>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }} className="modal-achievements">
            {cs.detail.impact.map((item, i) => (
              <div key={i} style={{ display: 'flex', gap: 10, alignItems: 'flex-start', padding: '12px 14px', background: `${cs.color}08`, border: `1px solid ${cs.color}20`, borderRadius: 8 }}>
                <span style={{ color: cs.color, fontSize: 12, marginTop: 1, flexShrink: 0 }}>✓</span>
                <span style={{ fontFamily: 'Inter, sans-serif', fontSize: 13, color: 'var(--text-primary)', lineHeight: 1.5 }}>{item}</span>
              </div>
            ))}
          </div>
        </ModalSection>

        {/* What we delivered */}
        <ModalSection label="// WHAT WE DELIVERED" color={cs.color}>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
            {cs.detail.delivered.map((item, i) => (
              <span key={i} style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 11, color: 'var(--text-secondary)', padding: '6px 13px', border: `1px solid ${cs.color}35`, borderRadius: 6, background: `${cs.color}08` }}>{item}</span>
            ))}
          </div>
        </ModalSection>

        {/* Bottom line */}
        <div style={{ padding: '18px 22px', background: `${cs.color}08`, border: `1px solid ${cs.color}25`, borderLeft: `3px solid ${cs.color}`, borderRadius: '0 8px 8px 0', marginBottom: 28 }}>
          <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 10, color: cs.color, marginBottom: 8, letterSpacing: '0.08em' }}>// THE BOTTOM LINE</div>
          <p style={{ fontFamily: 'Inter, sans-serif', fontSize: 15, color: 'var(--text-primary)', lineHeight: 1.65, fontStyle: 'italic' }}>{cs.detail.outcome}</p>
        </div>

        {/* Stack */}
        <ModalSection label="// STACK USED" color={cs.color}>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
            {cs.detail.stack.map((s, i) => (
              <span key={i} style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 11, color: 'var(--text-secondary)', padding: '5px 12px', border: '1px solid var(--border-subtle)', borderRadius: 6, background: 'var(--bg-tertiary)' }}>{s}</span>
            ))}
          </div>
        </ModalSection>

        {/* CTA */}
        <a href="https://cal.com/ratan-kumar/ai-automation-startegy-call-with-ratan-quantaeight"
          target="_blank" rel="noopener"
          style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, padding: '14px 24px', background: cs.color, color: '#0A0A0B', borderRadius: 10, textDecoration: 'none', fontFamily: 'Inter, sans-serif', fontSize: 14, fontWeight: 700, transition: 'opacity 0.2s ease' }}
          onMouseEnter={e => e.currentTarget.style.opacity = '0.88'}
          onMouseLeave={e => e.currentTarget.style.opacity = '1'}
        >Build something like this for my business →</a>
      </div>

      <style>{`
        @keyframes modal-bg-in { from{opacity:0} to{opacity:1} }
        @keyframes modal-in { from{opacity:0;transform:translateY(16px) scale(0.97)} to{opacity:1;transform:translateY(0) scale(1)} }
        @media (max-width: 600px) { .modal-achievements { grid-template-columns: 1fr !important; } }
      `}</style>
    </div>
  );
}

function ModalSection({ label, color, children }) {
  return (
    <div style={{ marginBottom: 28 }}>
      <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 10, color: color, letterSpacing: '0.1em', marginBottom: 12 }}>{label}</div>
      {children}
    </div>
  );
}

function CaseCard({ cs, onRead, compact }) {
  const [hov, setHov] = useCsState(false);
  return (
    <div
      onMouseEnter={() => setHov(true)} onMouseLeave={() => setHov(false)}
      onClick={() => onRead(cs)}
      style={{
        background: hov ? 'var(--bg-tertiary)' : 'var(--bg-card)',
        border: `1px solid ${hov ? cs.color + '55' : 'var(--border-subtle)'}`,
        borderRadius: 14, padding: compact ? '24px' : '28px',
        cursor: 'pointer',
        transition: 'all 0.3s cubic-bezier(0.16,1,0.3,1)',
        transform: hov ? 'translateY(-5px)' : 'translateY(0)',
        boxShadow: hov ? `0 14px 44px ${cs.color}12` : 'var(--shadow-card)',
        display: 'flex', flexDirection: 'column',
        position: 'relative', overflow: 'hidden', height: '100%',
      }}
    >
      <div style={{ position: 'absolute', top: 0, left: 0, right: 0, height: 2, background: `linear-gradient(90deg, transparent, ${cs.color}, transparent)`, opacity: hov ? 1 : 0, transition: 'opacity 0.3s ease' }} />

      <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 10, color: cs.color, letterSpacing: '0.1em', marginBottom: compact ? 12 : 16, opacity: 0.9 }}>{cs.tag}</div>

      <div style={{ fontFamily: 'Syne, sans-serif', fontSize: compact ? 'clamp(28px,3vw,40px)' : 'clamp(34px,4vw,52px)', fontWeight: 700, lineHeight: 1, color: cs.color, letterSpacing: '-0.02em', marginBottom: 5, textShadow: hov ? `0 0 28px ${cs.color}50` : 'none', transition: 'text-shadow 0.3s ease' }}>{cs.metric}</div>

      <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 11, color: 'var(--text-tertiary)', marginBottom: compact ? 10 : 14, letterSpacing: '0.03em' }}>{cs.subMetric}</div>

      <h3 style={{ fontFamily: 'Syne, sans-serif', fontSize: compact ? 15 : 17, fontWeight: 600, color: 'var(--text-primary)', lineHeight: 1.35, letterSpacing: '-0.01em', marginBottom: 10 }}>{cs.headline}</h3>

      {/* Punchy 2-3 sentence summary */}
      <p style={{ fontFamily: 'Inter, sans-serif', fontSize: 13, color: 'var(--text-secondary)', lineHeight: 1.65, flex: 1, marginBottom: compact ? 12 : 16 }}>{cs.summary}</p>

      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', paddingTop: 14, borderTop: `1px solid ${hov ? cs.color + '25' : 'var(--border-subtle)'}`, transition: 'border-color 0.3s ease' }}>
        <span style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 10, color: cs.verified ? cs.color : 'var(--text-tertiary)', opacity: 0.8, display: 'flex', alignItems: 'center', gap: 5 }}>
          <span style={{ width: 5, height: 5, borderRadius: '50%', background: cs.verified ? cs.color : 'var(--text-tertiary)', boxShadow: cs.verified ? `0 0 5px ${cs.color}` : 'none' }} />
          {cs.status}
        </span>
        <span style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 11, color: cs.color, display: 'flex', alignItems: 'center', gap: 4, transform: hov ? 'translateX(4px)' : 'translateX(0)', transition: 'transform 0.25s ease' }}>Read the case study →</span>
      </div>
    </div>
  );
}

const NICHE_GROUPS = [
  { label: 'All builds',   ids: ALL_CASES.map(c => c.id) },
  { label: 'Med Spa',      ids: ['medspa-rebooking'] },
  { label: 'Real Estate',  ids: ['realestate-leads'] },
  { label: 'Law Firm',     ids: ['lawfirm-intake'] },
  { label: 'CPA',          ids: ['cpa-tax'] },
  { label: 'Logistics',    ids: ['workforce-risk'] },
  { label: 'Staffing',     ids: ['ai-recruitment'] },
  { label: 'B2B SaaS',     ids: ['b2b-outbound'] },
];

function CaseStudies() {
  const [revealed, setRevealed] = useCsState(false);
  const [expanded, setExpanded] = useCsState(false);
  const [activeNiche, setActiveNiche] = useCsState('All builds');
  const [readCase, setReadCase] = useCsState(null);
  const sectionRef = useCsRef(null);

  useCsEffect(() => {
    const obs = new IntersectionObserver(([e]) => { if (e.isIntersecting) setRevealed(true); }, { threshold: 0.08 });
    if (sectionRef.current) obs.observe(sectionRef.current);
    return () => obs.disconnect();
  }, []);

  const nicheGroup = NICHE_GROUPS.find(g => g.label === activeNiche);
  const visibleIds = nicheGroup ? nicheGroup.ids : ALL_CASES.map(c => c.id);
  const topCases = expanded
    ? ALL_CASES.filter(c => visibleIds.includes(c.id))
    : ALL_CASES.filter(c => visibleIds.includes(c.id)).slice(0, 3);

  useCsEffect(() => {
    window.__filterCaseStudies = (niche) => {
      setExpanded(true); setActiveNiche(niche);
      sectionRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' });
    };
    return () => { delete window.__filterCaseStudies; };
  }, []);

  return (
    <section id="work" ref={sectionRef} style={{ padding: '120px 0', background: 'var(--bg-primary)' }}>
      <div style={{ maxWidth: 1280, margin: '0 auto', padding: '0 48px' }}>
        <div style={{ marginBottom: 40, opacity: revealed ? 1 : 0, transform: revealed ? 'translateY(0)' : 'translateY(24px)', transition: 'all 0.6s cubic-bezier(0.16,1,0.3,1)', display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', flexWrap: 'wrap', gap: 20 }}>
          <div>
            <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 13, color: 'var(--accent-mint-text)', letterSpacing: '0.12em', textTransform: 'uppercase', marginBottom: 12 }}>// CASE STUDIES</div>
            <h2 style={{ fontFamily: 'Syne, sans-serif', fontSize: 'clamp(28px,3.8vw,52px)', fontWeight: 700, letterSpacing: '-0.02em', lineHeight: 1.1 }}>
              Real problems. Real systems.<br />
              <span style={{ color: 'var(--text-secondary)', fontWeight: 500 }}>Real results in production.</span>
            </h2>
          </div>
          <p style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 12, color: 'var(--text-tertiary)', maxWidth: 280, lineHeight: 1.6 }}>Verified builds marked live. Representative builds show what's possible for your industry.</p>
        </div>

        <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 32, opacity: revealed ? 1 : 0, transition: 'opacity 0.5s ease 0.1s' }}>
          {NICHE_GROUPS.map(g => {
            const isOn = activeNiche === g.label;
            return (
              <button key={g.label} onClick={() => { setActiveNiche(g.label); setExpanded(true); }} style={{
                padding: '7px 16px', borderRadius: 20,
                border: `1px solid ${isOn ? 'var(--border-emphasis)' : 'var(--border-subtle)'}`,
                background: isOn ? 'var(--bg-tertiary)' : 'transparent',
                color: isOn ? 'var(--text-primary)' : 'var(--text-secondary)',
                fontFamily: 'JetBrains Mono, monospace', fontSize: 11,
                fontWeight: isOn ? 600 : 400,
                cursor: 'pointer', transition: 'all 0.2s ease', whiteSpace: 'nowrap',
                position: 'relative',
                boxShadow: isOn ? 'inset 0 1px 0 rgba(255,255,255,0.05)' : 'none',
              }}>
                {isOn && (
                  <span style={{
                    position: 'absolute', left: 10, top: '50%', transform: 'translateY(-50%)',
                    width: 5, height: 5, borderRadius: '50%',
                    background: 'var(--accent-mint)', boxShadow: '0 0 6px var(--accent-mint)',
                  }} />
                )}
                <span style={{ paddingLeft: isOn ? 12 : 0, transition: 'padding 0.25s ease' }}>{g.label}</span>
              </button>
            );
          })}
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: `repeat(${Math.min(topCases.length, 3)}, 1fr)`, gap: 20 }} className="cs-grid">
          {topCases.map((cs, i) => (
            <div key={cs.id} style={{ opacity: revealed ? 1 : 0, transform: revealed ? 'translateY(0)' : 'translateY(32px)', transition: `all 0.6s cubic-bezier(0.16,1,0.3,1) ${0.08 + i * 0.07}s` }}>
              <CaseCard cs={cs} onRead={setReadCase} compact={topCases.length > 4} />
            </div>
          ))}
        </div>

        {!expanded && ALL_CASES.filter(c => visibleIds.includes(c.id)).length > 3 && (
          <div style={{ marginTop: 32, textAlign: 'center', opacity: revealed ? 1 : 0, transition: 'opacity 0.6s ease 0.4s' }}>
            <button onClick={() => setExpanded(true)} style={{ background: 'transparent', cursor: 'pointer', fontFamily: 'JetBrains Mono, monospace', fontSize: 12, color: 'var(--text-secondary)', display: 'inline-flex', alignItems: 'center', gap: 8, padding: '10px 20px', border: '1px solid var(--border-subtle)', borderRadius: 8, transition: 'all 0.2s ease' }}
              onMouseEnter={e => { e.currentTarget.style.borderColor = 'var(--accent-mint)'; e.currentTarget.style.color = 'var(--accent-mint)'; }}
              onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--border-subtle)'; e.currentTarget.style.color = 'var(--text-secondary)'; }}
            >View all {ALL_CASES.filter(c => visibleIds.includes(c.id)).length} case studies ↓</button>
          </div>
        )}
        {expanded && topCases.length > 3 && (
          <div style={{ marginTop: 24, textAlign: 'center' }}>
            <button onClick={() => setExpanded(false)} style={{ background: 'transparent', cursor: 'pointer', fontFamily: 'JetBrains Mono, monospace', fontSize: 11, color: 'var(--text-tertiary)', border: 'none', padding: '8px' }}>Show less ↑</button>
          </div>
        )}
      </div>

      {readCase && <ReadModal cs={readCase} onClose={() => setReadCase(null)} />}

      <style>{`
        @media (max-width: 900px) { .cs-grid { grid-template-columns: 1fr 1fr !important; } }
        @media (max-width: 600px) { .cs-grid { grid-template-columns: 1fr !important; } }
      `}</style>
    </section>
  );
}

Object.assign(window, { CaseStudies });
