---
import Layout from '../layouts/Layout.astro';
import HeroAtmosphere from '../components/HeroAtmosphere.astro';
import Icon from '../components/Icon.astro';
import CTA from '../components/CTA.astro';

// Every number on this page is a real default from the codebase:
//   internal/config/constants.go
//   internal/scheduler/{campaign,email,warmup}_scheduler.go
//   internal/app/warmup/service.go  (health bands)
//   internal/repository/pg_warmup.go
//   internal/app/worker/wmail/ratelimit.go
//   internal/app/advanced/service.go  (suppression)
//   internal/infrastructure/db/migrations/000001_baseline.up.sql  (free/premium pools)

// =========================================================================
// What rides along with a single mailbox (the model-section card).
// =========================================================================
const attached = [
  { k: 'Cap',         v: '50 / day',       d: 'The most cold email this mailbox sends in a day.' },
  { k: 'Pace',        v: '600s apart',     d: 'At least ten minutes between any two sends.' },
  { k: 'Warmup',      v: '10 to 40 / day', d: 'Opens at 10, adds one a day, holds at 40.' },
  { k: 'Health',      v: 'rolling 7 days', d: 'A score built from spam, complaints, and bounces.' },
  { k: 'Auth',        v: 'SPF DKIM DMARC', d: 'Re-checked daily, not just at setup.' },
  { k: 'Suppression', v: 'workspace-wide', d: 'One bounce or complaint stops every campaign.' },
];

// Workers the mailbox can run on. Just infrastructure; the mailbox carries
// its own reputation regardless of which one it sits on.
const workers = [
  { id: 'w-01', ip: '192.0.2.14',   dots: ['bg-emerald-500', 'bg-emerald-500', 'bg-amber-500'] },
  { id: 'w-02', ip: '198.51.100.7', dots: ['bg-emerald-500', 'bg-emerald-500', 'bg-emerald-500'] },
  { id: 'w-03', ip: '203.0.113.9',  dots: ['bg-emerald-500', 'bg-amber-500'] },
];

// The mailbox lifecycle shown on the left of the model section. Each step
// pairs with a control on the card to the right.
const lifecycle = [
  { t: 'Connect and verify auth',        d: 'SPF, DKIM, and DMARC have to resolve before the mailbox can send.' },
  { t: 'Warm up 10 to 40',               d: 'Opens at 10 a day, adds one a day, holds at 40.' },
  { t: 'Send within caps, watch health', d: '50 a day, 600s apart, scored on a rolling 7 days.' },
  { t: 'If it slips, pull and recover',  d: 'Out of the pool it cools off, then requalifies before it sends again.' },
];

// =========================================================================
// The product defaults. Real numbers from internal/config/constants.go
// =========================================================================
const defaults = [
  { k: 'Cold campaign cap', v: '50 / day',   why: 'The ceiling for cold email from one mailbox. You can raise it to 100, but only with a reason worth defending.' },
  { k: 'Minimum send gap',  v: '600s',       why: 'Ten minutes between sends, even when the queue is full. People do not fire off mail in bursts.' },
  { k: 'Warmup start',      v: '10 / day',   why: 'Where warmup begins. Low enough to read like a normal person sending mail.' },
  { k: 'Warmup ceiling',    v: '40 / day',   why: 'Warmup stops climbing here. Pushing past it buys no extra reputation.' },
  { k: 'Warmup ramp',       v: '+1 / day',   why: 'One more warmup message per day. Faster ramps look odd to the receiver.' },
  { k: 'Sync burst limit',  v: '100 / 5m',   why: 'If a mailbox pulls in more than 100 new messages in five minutes, the worker throttles it.' },
  { k: 'Sync hourly limit', v: '500 / hr',   why: 'Past this we pause the mailbox ourselves, before the provider has to.' },
  { k: 'Invalid token block', v: '3 / 24h',  why: 'Three malformed warmup tokens in a day drop the mailbox from the pool.' },
];

// =========================================================================
// Auto-quarantine bands. Spam-placement thresholds, per-mailbox window.
// Matches the health states in internal/app/warmup/service.go.
// =========================================================================
const bands = [
  {
    name: 'Healthy',     tone: 'emerald',
    spam: 'under 10%',   complaint: 'under 0.03%', bounce: 'under 5%',
    action: 'Normal. Keeps warming up and stays in the pool.',
  },
  {
    name: 'Watch',       tone: 'amber',
    spam: 'at or above 10%', complaint: 'at or above 0.03%', bounce: 'not used',
    action: 'Volume eases back and the gaps widen, more so as it climbs. Stays in the pool.',
  },
  {
    name: 'Quarantined', tone: 'rose',
    spam: 'at or above 20%', complaint: 'at or above 0.10%', bounce: 'at or above 5%',
    action: 'Out of the shared pool for 7 days. Cools off in recovery.',
  },
  {
    name: 'Blocked',     tone: 'rose-dark',
    spam: 'at or above 40%', complaint: 'at or above 0.30%', bounce: 'at or above 10%',
    action: 'Blocked for 30 days. Cold sending pauses, and a person clears it before re-entry.',
  },
  {
    name: 'Catastrophic', tone: 'rose-dark',
    spam: 'at or above 80%', complaint: 'severe', bounce: 'severe',
    action: 'Long block and a full reputation reset. No automatic way back in.',
  },
];

const toneClass = (t: string) => {
  if (t === 'emerald')   return { dot: 'bg-emerald-500', chip: 'bg-emerald-50 text-emerald-700', bar: 'bg-emerald-500' };
  if (t === 'amber')     return { dot: 'bg-amber-500',   chip: 'bg-amber-50 text-amber-700',     bar: 'bg-amber-500'   };
  if (t === 'rose-dark') return { dot: 'bg-rose-700',    chip: 'bg-rose-100 text-rose-800',      bar: 'bg-rose-700'    };
  return { dot: 'bg-rose-500', chip: 'bg-rose-50 text-rose-700', bar: 'bg-rose-500' };
};

// =========================================================================
// Two warmup pools (free, premium) plus the handling around them:
// recovery is a cooldown state, dedicated is isolated infrastructure.
// =========================================================================
const pools = [
  {
    name: 'Free pool',     accent: '#94a3b8',
    when: 'Free trial',
    summary: 'Trial mailboxes only, held to the same thresholds as paid ones.',
    rules: [
      'Only warms up with other free-plan mailboxes.',
      'Never sends to a premium mailbox.',
      'Kept out of the premium health scoring.',
    ],
  },
  {
    name: 'Premium pool', accent: '#0284c7', featured: true,
    when: 'Starter, Grow, Business',
    summary: 'Vetted paid mailboxes, with tighter bands and less room to drift.',
    rules: [
      'Only warms up with other healthy premium mailboxes.',
      'A mailbox that crosses a band drops to recovery and earns its way back.',
      'Spam placement and complaints are scored per mailbox over rolling windows.',
    ],
  },
  {
    name: 'Recovery',     accent: '#d97706',
    when: 'A cooldown state',
    summary: 'Where a mailbox sits while it cools off after crossing a band. Healthy traffic never sees it.',
    rules: [
      '7 days after a quarantine, 30 days after a hard block.',
      'Comes back at reduced volume for a few days, then gets re-scored.',
      'Authentication and bounce checks have to pass first.',
    ],
  },
  {
    name: 'Dedicated',    accent: '#0f172a',
    when: 'Enterprise infrastructure',
    summary: 'Your own worker and IP. It still warms up inside the premium pool.',
    rules: [
      'One worker process and IP for one organisation.',
      'Reputation is still earned per mailbox.',
      'Same thresholds apply. Your own IP is not a free pass.',
    ],
  },
];

// =========================================================================
// Authentication coverage. SPF, DKIM, DMARC, PTR.
// =========================================================================
const auth = [
  { name: 'SPF',   tag: 'TXT record',
    body: 'We read the domain SPF record and confirm both your mailbox provider and any third-party senders are allowed.',
    fail: 'If it is missing or wrong, the mailbox cannot leave the connection wizard.' },
  { name: 'DKIM',  tag: 'Selector + key',
    body: 'We find the provider DKIM selector, confirm the public key parses, and require at least 1024 bits.',
    fail: 'A missing selector shows you the exact record to publish, ready to copy.' },
  { name: 'DMARC', tag: 'Policy + alignment',
    body: 'We read the policy, the alignment mode, and the reporting address, and flag p=none clearly.',
    fail: 'Reports can point at a Warmbly inbox so they surface inside the dashboard.' },
  { name: 'PTR',   tag: 'Reverse DNS',
    body: 'For your own SMTP, we check the sending IP reverse DNS resolves back to the same hostname.',
    fail: 'A mismatched PTR is one of the fastest ways into the spam folder.' },
];

// =========================================================================
// Suppression engine. Real codepaths (internal/app/advanced/service.go).
// Workspace + email scope only; auto-actions default on per org settings.
// =========================================================================
const suppression = [
  { trigger: 'Bounce',                scope: 'workspace',  source: 'consumer.deliverability',   note: 'When a send bounces, the recipient is dropped across every campaign in the workspace, and nothing else queues to them.' },
  { trigger: 'Complaint (FBL / ARF)', scope: 'workspace',  source: 'consumer.deliverability',   note: 'A Gmail or Microsoft spam complaint suppresses the recipient and nudges the mailbox health score down.' },
  { trigger: 'One-click unsubscribe', scope: 'workspace',  source: 'tracking.unsubscribe',      note: 'RFC 8058 one-click. The recipient is gone before the confirmation page even loads.' },
  { trigger: 'Reply: STOP / REMOVE',  scope: 'workspace',  source: 'consumer.reply.classifier', note: 'Common opt-out phrases in replies are caught and suppressed without anyone in the loop.' },
  { trigger: 'Manual suppression',    scope: 'workspace',  source: 'api / dashboard',           note: 'Suppress by recipient or an uploaded list. CSV uploads are deduplicated against what is already there.' },
];

// =========================================================================
// Recommended cold sending posture.
// =========================================================================
const posture = [
  { stage: 'New mailbox',   range: '10 to 20 / day', note: 'Fresh or just connected. The first couple of weeks are for reputation; pipeline comes later.' },
  { stage: 'Ramping',       range: '+5 / week',      note: 'Add a little each week while complaints and bounces stay clean. Back off the moment they climb.' },
  { stage: 'Stable band',   range: '30 to 50 / day', note: 'The normal range for most cold mailboxes. The default cap sits at the top of it.' },
  { stage: 'Above default', range: 'needs a look',   note: 'Going past 50 / day on one mailbox takes clean signals and a real reason first.' },
];

// =========================================================================
// How we landed differently from most of the category.
// =========================================================================
const approach = [
  { h: 'Sending is spread out on purpose.',
    b: 'Throughput per server is the wrong thing to optimise for. What burns reputation is sending too much from one mailbox, domain, or IP. We keep each mailbox under its own cap and spread the work across many of them, so the risk never piles up in one place.' },
  { h: 'Warmup has to prove itself.',
    b: 'Warmup only helps if it is real. Every warmup message carries a signed token that we check when the reply comes back, so a mailbox cannot fake good behaviour by quietly replying to itself.' },
  { h: 'We pull a mailbox before the provider does.',
    b: 'Once Google or SES throttles a domain, the damage has already gone out. We watch each mailbox on a rolling window and act on our own thresholds, which sit weeks earlier than the public ones.' },
  { h: 'Trials never share a pool with paying customers.',
    b: 'A trial account should never warm up in the same loop as a paying one. If it picks up bad habits, that is its own problem to work off in recovery.' },
];

// =========================================================================
// FAQ.
// =========================================================================
const faq = [
  ['Is deliverability tracked per mailbox or per account?',
   'Per mailbox. Each one is scored and capped on its own, so a single account can hold five mailboxes in five different states at once.'],
  ['What pulls a mailbox out of the pool automatically?',
   'Any of these: three bad warmup tokens in 24 hours, spam placement at or above 20% with at least 20 warmup deliveries in the last 7 days, a complaint rate at or above 0.10%, or a bounce rate at or above 5%.'],
  ['How does suppression carry across campaigns?',
   'Bounces, complaints, and unsubscribes are workspace-wide. Once someone is suppressed, every running campaign skips them on the next send, and nothing else ever queues to them.'],
  ['Why is the cap only 50 a day?',
   'Because 50 a day with a 600-second gap stays comfortably under provider scrutiny everywhere. You can raise it toward 100, but earn it mailbox by mailbox.'],
  ['What happens when a mailbox gets blocked?',
   'It leaves the shared pool, cold sending pauses, and it cools off in recovery: 7 days after a quarantine, 30 after a hard block. When the cooldown ends it comes back at reduced volume for a few days and has to re-pass the health checks before it sends normally again.'],
  ['Shared IPs or dedicated?',
   'Most plans share IPs, which is fine here because we track reputation on the mailbox itself. Enterprise plans can take a dedicated worker and IP, but the same per-mailbox limits still apply.'],
  ['Does warmup keep running once I start a campaign?',
   'Yes. Warmup runs alongside your cold sending to keep the mailbox active and conversational. Switching it off the day you go live is a good way to watch a mailbox go cold.'],
  ['How long before a new mailbox is ready?',
   'Plan on a few weeks. Warmup opens at 10 a day and adds one a day, so a fresh mailbox earns its way up to a normal cold volume instead of jumping straight there.'],
  ['Do you guarantee the inbox?',
   'No, and be careful with anyone who does. Placement also depends on your content, your list quality, and your domain history. What we control is the sending itself: how fast and how much each mailbox sends, whether its authentication is clean, and pulling it the moment it starts to slip.'],
];

// =========================================================================
// Astro JSX parser hoists. Keep any `<` or `<=` out of `{}`; pre-compute
// everything as data and iterate cleanly in JSX.
// =========================================================================
const gaugeTicks = [
  { pct: 0,   label: '0%' },
  { pct: 10,  label: '10%' },
  { pct: 20,  label: '20%' },
  { pct: 40,  label: '40%' },
  { pct: 80,  label: '80%' },
  { pct: 100, label: '100%' },
];

const numbers = [
  { v: '50',    u: '/ day',  l: 'cold cap per mailbox',     src: 'internal/config/constants.go' },
  { v: '600',   u: 's',      l: 'min gap between sends',    src: 'internal/scheduler/email_scheduler.go' },
  { v: '10',    u: '/ day',  l: 'warmup start volume',      src: 'internal/scheduler/warmup_scheduler.go' },
  { v: '40',    u: '/ day',  l: 'warmup ceiling',           src: 'internal/scheduler/warmup_scheduler.go' },
  { v: '+1',    u: '/ day',  l: 'warmup ramp',              src: 'internal/scheduler/warmup_scheduler.go' },
  { v: '500',   u: '/ hr',   l: 'worker sync hourly limit', src: 'internal/app/worker/wmail/ratelimit.go' },
];
---
<Layout
  title="Email deliverability, handled per mailbox | Warmbly"
  description="Warmbly scores and limits each mailbox on its own, and pulls a mailbox from the shared pool weeks before Gmail or Outlook would flag it."
>
  <!-- ============================================================
       HERO
  ============================================================ -->
  <section class="relative isolate overflow-hidden">
    <HeroAtmosphere />

    <!-- warmup fragments arranged as a diagonal ramp: starts low-left, arrives healthy top-right. The vertical middle stays clear of the headline. xl and up. -->
    <div class="hidden xl:block absolute inset-0 z-0 pointer-events-none select-none" aria-hidden="true">

      <!-- TOP-RIGHT · the destination: a warmed-up, healthy mailbox (focal, live dot) -->
      <div class="hero-float absolute top-[9%] right-[calc(50%_-_470px)] z-30" style="--drift:-11px;animation-duration:7.4s;animation-delay:-1.7s">
        <div class="relative rotate-[2deg] w-[182px] px-3.5 py-3 rounded-[12px] bg-white ring-1 ring-slate-900/5 shadow-[0_2px_4px_-2px_rgba(2,32,71,0.25),0_18px_36px_-12px_rgba(2,32,71,0.55)]">
          <span class="absolute -top-1 -right-1 inline-flex w-2.5 h-2.5">
            <span class="hero-float-ping absolute inset-0 rounded-full bg-emerald-400 opacity-70 animate-ping"></span>
            <span class="relative w-2.5 h-2.5 rounded-full bg-emerald-500 ring-2 ring-white"></span>
          </span>
          <div class="flex items-center gap-1.5">
            <span class="w-2 h-2 rounded-full bg-emerald-500 shrink-0"></span>
            <span class="font-mono text-[12px] font-semibold text-slate-800 truncate">ben@acme.com</span>
          </div>
          <div class="mt-1 font-mono text-[10.5px] text-slate-500 tabular-nums">healthy · 47/50 today</div>
          <div class="mt-2 h-1 w-full rounded-full bg-slate-100 overflow-hidden">
            <div class="h-full rounded-full bg-sky-500" style="width:94%"></div>
          </div>
        </div>
      </div>

      <!-- TOP-RIGHT · supporting chip just under the card -->
      <div class="hero-float absolute top-[25%] right-[calc(50%_-_432px)] z-20" style="--drift:-7px;animation-duration:8s;animation-delay:-0.9s">
        <div class="rotate-[-2deg] h-7 px-3 rounded-full bg-white/95 ring-1 ring-slate-900/5 shadow-[0_8px_20px_-10px_rgba(2,32,71,0.4)] inline-flex items-center gap-1.5">
          <span class="w-1.5 h-1.5 rounded-full bg-sky-500"></span>
          <span class="text-[11px] font-medium text-slate-600">premium pool</span>
        </div>
      </div>

      <!-- TOP-LEFT · a lone accent up high -->
      <div class="hero-float absolute top-[12%] left-[calc(50%_-_446px)] z-20" style="--drift:-9px;animation-duration:6.6s;animation-delay:-2.4s">
        <div class="rotate-[-2deg] px-3 py-2.5 rounded-[12px] bg-white ring-1 ring-slate-900/5 shadow-[0_2px_3px_-2px_rgba(2,32,71,0.2),0_14px_30px_-14px_rgba(2,32,71,0.45)]">
          <div class="flex items-center gap-2">
            <span class="w-4 h-4 rounded-full bg-emerald-50 ring-1 ring-emerald-200 inline-flex items-center justify-center shrink-0">
              <svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="#059669" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
            </span>
            <span class="text-[12px] font-semibold text-slate-800">signed token</span>
          </div>
        </div>
      </div>

      <!-- BOTTOM-LEFT · the start of the ramp: low volume, day one -->
      <div class="hero-float absolute top-[82%] left-[calc(50%_-_474px)] z-20" style="--drift:-10px;animation-duration:7.8s;animation-delay:-1.2s">
        <div class="rotate-[-3deg] w-[156px] px-3.5 py-3 rounded-[12px] bg-white ring-1 ring-slate-900/5 shadow-[0_2px_3px_-2px_rgba(2,32,71,0.2),0_14px_30px_-14px_rgba(2,32,71,0.45)]">
          <div class="flex items-center gap-2">
            <div class="flex items-end gap-[3px] h-5">
              <span class="w-1 h-2 rounded-[1px] bg-sky-400"></span>
              <span class="w-1 h-3 rounded-[1px] bg-sky-400"></span>
              <span class="w-1 h-3.5 rounded-[1px] bg-sky-400"></span>
              <span class="w-1 h-4 rounded-[1px] bg-sky-400"></span>
              <span class="w-1 h-5 rounded-[1px] bg-sky-500"></span>
            </div>
            <span class="font-mono text-[12px] font-semibold text-slate-800 tabular-nums">10 to 40</span>
          </div>
          <div class="mt-1.5 text-[10.5px] text-slate-500">starts at 10 a day</div>
        </div>
      </div>

      <!-- BOTTOM-LEFT · the ramp rule, tucked inboard -->
      <div class="hero-float absolute top-[88%] left-[calc(50%_-_322px)] z-10" style="--drift:-6px;animation-duration:8.3s;animation-delay:-3.4s">
        <div class="rotate-[4deg] h-7 px-3 rounded-full bg-white/95 ring-1 ring-slate-900/5 shadow-[0_8px_20px_-10px_rgba(2,32,71,0.4)] inline-flex items-center gap-1.5">
          <span class="font-mono text-[12px] font-semibold text-slate-800">+1</span>
          <span class="text-[10.5px] text-slate-500">/ day</span>
        </div>
      </div>

      <!-- BOTTOM-RIGHT · a warmup reply, low -->
      <div class="hero-float absolute top-[85%] right-[calc(50%_-_440px)] z-10" style="--drift:-8px;animation-duration:7.1s;animation-delay:-2.8s">
        <div class="rotate-[1.5deg] px-3.5 py-2.5 rounded-[12px] bg-white ring-1 ring-slate-900/5 shadow-[0_2px_3px_-2px_rgba(2,32,71,0.2),0_14px_30px_-14px_rgba(2,32,71,0.45)]">
          <div class="flex items-center gap-2">
            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" class="text-sky-400 shrink-0" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 17 4 12 9 7"/><path d="M20 18v-2a4 4 0 0 0-4-4H4"/></svg>
            <span class="text-[12px] text-slate-700">thanks, got it</span>
          </div>
        </div>
      </div>

    </div>

    <div class="container-page relative z-10 pt-20 md:pt-28 pb-32 md:pb-44 text-center">
      <div class="inline-flex items-center gap-2 h-7 pl-1 pr-3 rounded-full bg-white/15 backdrop-blur ring-1 ring-white/25 text-[12px] text-white/95 shadow-[0_4px_14px_-4px_rgba(0,0,0,0.25)]">
        <span class="inline-flex items-center h-5 px-1.5 rounded-full text-[10.5px] font-semibold uppercase tracking-[0.06em] bg-white" style="color:#0369a1;">
          Deliverability
        </span>
        The work that keeps you out of spam
      </div>

      <h1 class="mt-8 md:mt-10 text-[44px] sm:text-6xl md:text-[72px] lg:text-[80px] font-semibold tracking-[-0.04em] leading-[0.98] text-white max-w-4xl mx-auto">
        Keep every mailbox<br/>landing in the inbox.
      </h1>
      <p class="mt-6 text-[17px] md:text-[19px] text-white/80 max-w-2xl mx-auto leading-relaxed">
        Each mailbox is warmed up, capped, and scored on its own. When one starts drifting toward spam, we slow it down or pull it from the pool before Gmail or Outlook notices.
      </p>

      <div class="mt-8 flex flex-wrap items-center justify-center gap-3">
        <a href="https://app.warmbly.com/register" class="inline-flex h-11 px-5 items-center gap-2 rounded-[10px] text-[14.5px] font-semibold bg-white hover:bg-white hover:-translate-y-0.5 hover:shadow-[0_12px_28px_-6px_rgba(0,0,0,0.3)] transition-all duration-200 ease-out shadow-[0_4px_14px_-2px_rgba(0,0,0,0.18)]">
          <span style="color:#075985;">Audit a mailbox</span>
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#075985" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
            <path d="M5 12h14"/><path d="m12 5 7 7-7 7"/>
          </svg>
        </a>
        <a href="#approach" class="inline-flex h-11 px-5 items-center rounded-[10px] text-[14.5px] font-medium bg-white/10 backdrop-blur ring-1 ring-white/40 text-white hover:bg-white/20 hover:-translate-y-0.5 transition-all duration-200 ease-out">
          How we think about it
        </a>
      </div>
    </div>
  </section>

  <style>
    .hero-float { animation-name: heroFloat; animation-timing-function: ease-in-out; animation-iteration-count: infinite; animation-direction: alternate; will-change: transform; }
    @keyframes heroFloat { from { transform: translateY(0); } to { transform: translateY(var(--drift, -10px)); } }
    @media (prefers-reduced-motion: reduce) { .hero-float { animation: none; } .hero-float-ping { animation: none; } }
  </style>

  <!-- ============================================================
       APPROACH · what we do differently, in plain terms
  ============================================================ -->
  <section id="approach" class="border-y border-[color:var(--border)] bg-[color:var(--surface-1)]/40 py-20 md:py-28 scroll-mt-4">
    <div class="container-page">
      <div class="max-w-3xl mb-12">
        <div class="text-[11px] uppercase tracking-[0.18em] font-mono text-[#0284c7] mb-3">How we think about it</div>
        <h2 class="text-[32px] md:text-[44px] font-semibold tracking-[-0.03em] leading-[1.05] text-heading">
          A few decisions that shape the rest.
        </h2>
        <p class="mt-4 text-[15.5px] text-foreground/70 leading-relaxed">
          Deliverability decides whether the rest of the product matters, so we were opinionated about it early. Here is where we ended up differently from most of the category, and each one is a real choice in the code.
        </p>
      </div>

      <div class="grid md:grid-cols-2 gap-4 lg:gap-5">
        {approach.map((c, i) => (
          <div class="rounded-[14px] bg-white ring-1 ring-[color:var(--border)] p-6 md:p-7">
            <div class="flex items-baseline gap-3 mb-3">
              <span class="font-mono text-[11px] text-[#0284c7] font-semibold tabular-nums">{String(i + 1).padStart(2, '0')}</span>
              <div class="text-[16px] md:text-[17px] font-semibold tracking-[-0.015em] text-heading leading-snug">{c.h}</div>
            </div>
            <p class="text-[13.5px] text-foreground/70 leading-relaxed">{c.b}</p>
          </div>
        ))}
      </div>
    </div>
  </section>

  <!-- ============================================================
       MAILBOX MODEL · one mailbox, plainly explained
  ============================================================ -->
  <section id="model" class="border-b border-[color:var(--border)] py-20 md:py-28 scroll-mt-4">
    <div class="container-page">
      <div class="grid lg:grid-cols-[1fr_1.3fr] gap-12 lg:gap-20 items-start">
        <!-- LEFT: narrative + mailbox lifecycle -->
        <div class="lg:sticky lg:top-24" style="align-self: start;">
          <div class="text-[11px] uppercase tracking-[0.18em] font-mono text-[#0284c7] mb-3">How it works</div>
          <h2 class="text-[32px] md:text-[44px] font-semibold tracking-[-0.03em] leading-[1.05] text-heading">
            Everything rides on the mailbox.
          </h2>
          <p class="mt-4 text-[15.5px] text-foreground/70 leading-relaxed max-w-md">
            A mailbox's reputation is its own, so that is where we attach the controls: the cap, the pacing, the warmup schedule, the health score, and the suppression list. The worker and the IP are just the machine it sends through, and we spread mailboxes across many of them so one rough day never drags down the rest.
          </p>

          <div class="mt-8 text-[10.5px] uppercase tracking-[0.18em] font-mono text-muted-foreground mb-1">Mailbox lifecycle</div>
          <div>
            {lifecycle.map((s, i) => (
              <div class="grid grid-cols-[auto_1fr] gap-x-4 py-4 border-b border-[color:var(--border)] last:border-b-0 items-baseline">
                <span class="font-mono text-[12px] text-[#0284c7] font-semibold tabular-nums">{String(i + 1).padStart(2, '0')}</span>
                <div>
                  <div class="text-[14px] font-semibold tracking-[-0.015em] text-heading leading-snug">{s.t}</div>
                  <p class="mt-1 text-[12.5px] text-foreground/65 leading-snug">{s.d}</p>
                </div>
              </div>
            ))}
          </div>
        </div>

        <!-- RIGHT: the live mailbox card + worker spread -->
        <div>
          <!-- The mailbox card -->
          <div class="rounded-[16px] bg-white ring-1 ring-[color:var(--border)] overflow-hidden shadow-[0_24px_60px_-30px_rgba(2,32,71,0.25)]">
            <div class="px-6 py-4 border-b border-[color:var(--border)] flex items-center gap-3">
              <span class="w-9 h-9 rounded-full bg-[color:var(--sky-1)] text-[#0369a1] inline-flex items-center justify-center shrink-0">
                <Icon name="mail" size={16} />
              </span>
              <div class="min-w-0 flex-1">
                <div class="text-[15px] font-semibold text-heading truncate">ben@acme.com</div>
                <div class="text-[11.5px] font-mono text-muted-foreground">Google Workspace</div>
              </div>
              <span class="inline-flex items-center gap-1.5 h-6 px-2 rounded-md text-[11px] font-medium bg-emerald-50 text-emerald-700 shrink-0">
                <span class="w-1.5 h-1.5 rounded-full bg-emerald-500"></span>
                healthy
              </span>
              <div class="hidden sm:flex flex-col items-end gap-1 shrink-0">
                <span class="font-mono text-[12px] text-foreground/65 tabular-nums">47 / 50 today</span>
                <span class="h-1.5 w-20 rounded-full bg-[color:var(--surface-1)] overflow-hidden" aria-hidden="true">
                  <span class="block h-full rounded-full bg-[#0284c7]" style="width:94%"></span>
                </span>
              </div>
            </div>

            <div class="grid sm:grid-cols-2 gap-px bg-[color:var(--border)]">
              {attached.map((a) => (
                <div class="bg-white px-6 py-4">
                  <div class="flex items-baseline justify-between gap-3">
                    <span class="text-[10.5px] uppercase tracking-[0.16em] font-mono text-muted-foreground">{a.k}</span>
                    <span class="font-mono text-[12px] text-heading tabular-nums text-right">{a.v}</span>
                  </div>
                  <p class="mt-1.5 text-[12.5px] text-foreground/65 leading-snug">{a.d}</p>
                </div>
              ))}
            </div>

            <div class="px-6 py-3 border-t border-[color:var(--border)] bg-[color:var(--surface-1)]/60 text-[11.5px] text-muted-foreground leading-snug">
              Sending through worker <span class="font-mono text-foreground/75">w-01 · 192.0.2.14</span>. Move it to another worker or IP and nothing about the mailbox changes.
            </div>
          </div>

          <!-- Spread across workers -->
          <div class="mt-8">
            <div class="text-[10.5px] uppercase tracking-[0.18em] font-mono text-muted-foreground mb-3">Spread across workers and IPs</div>
            <div class="grid grid-cols-3 gap-3">
              {workers.map((w) => (
                <div class="rounded-[12px] bg-white ring-1 ring-[color:var(--border)] p-4">
                  <div class="text-[11.5px] font-mono font-semibold text-heading">{w.id}</div>
                  <div class="mt-3 flex items-center gap-1.5">
                    {w.dots.map((d) => (
                      <span class={`w-2.5 h-2.5 rounded-full ${d}`}></span>
                    ))}
                  </div>
                  <div class="mt-3 text-[10.5px] font-mono text-muted-foreground truncate">{w.ip}</div>
                </div>
              ))}
            </div>
            <p class="mt-4 text-[13px] text-foreground/65 leading-relaxed max-w-xl">
              A worker is one machine on one IP, and each dot is a mailbox it sends for. We keep them spread out so a problem on one machine never reaches the others.
            </p>
          </div>
        </div>
      </div>
    </div>
  </section>

  <!-- ============================================================
       DEFAULTS · the numbers we ship with
  ============================================================ -->
  <section class="bg-white py-20 md:py-28">
    <div class="container-page">
      <div class="max-w-2xl mb-12">
        <div class="text-[11px] uppercase tracking-[0.18em] text-muted-foreground font-mono mb-3">Defaults</div>
        <h2 class="text-[32px] md:text-[44px] font-semibold tracking-[-0.03em] leading-[1.05] text-heading">
          The numbers we ship with.
        </h2>
        <p class="mt-4 text-[15.5px] text-foreground/70 leading-relaxed">
          These are set for a normal mailbox on a normal provider. Override any of them per mailbox if you have a real reason. The right column is why each one sits where it does.
        </p>
      </div>

      <div class="grid md:grid-cols-2 gap-x-12 gap-y-px">
        {defaults.map((d, i) => (
          <div class="grid grid-cols-[1fr_auto] gap-6 py-6 border-b border-[color:var(--border)] items-baseline hover:bg-[color:var(--surface-1)]/40 -mx-3 px-3 rounded-[6px] transition-colors">
            <div>
              <div class="text-[10.5px] uppercase tracking-[0.22em] font-mono text-muted-foreground">
                {String(i + 1).padStart(2, '0')} · {d.k}
              </div>
              <p class="mt-2 text-[13.5px] text-foreground/65 leading-relaxed max-w-md">{d.why}</p>
            </div>
            <div class="text-right">
              <div class="text-[22px] md:text-[26px] font-semibold tracking-[-0.02em] text-heading font-mono whitespace-nowrap">{d.v}</div>
            </div>
          </div>
        ))}
      </div>

      <div class="mt-8 text-[11.5px] font-mono text-muted-foreground">
        Source: <span class="text-foreground/75">internal/config/constants.go</span> · <span class="text-foreground/75">internal/scheduler/email_scheduler.go</span> · <span class="text-foreground/75">internal/repository/pg_warmup.go</span>
      </div>
    </div>
  </section>

  <!-- ============================================================
       POOLS + ISOLATION
  ============================================================ -->
  <section class="border-y border-[color:var(--border)] bg-[color:var(--surface-1)]/40 py-20 md:py-28">
    <div class="container-page">
      <div class="max-w-2xl mb-12">
        <div class="text-[11px] uppercase tracking-[0.18em] text-muted-foreground font-mono mb-3">Pools and isolation</div>
        <h2 class="text-[28px] md:text-[40px] font-semibold tracking-[-0.025em] leading-[1.06] text-heading">
          How mailboxes stay separated.
        </h2>
        <p class="mt-4 text-[15px] text-foreground/70 leading-relaxed">
          There are two warmup pools, free and premium, and a mailbox does not move between them on its own. A trial warms up only with other trials. When a paid mailbox crosses a band it cools off in recovery before it touches healthy traffic again. Dedicated customers get their own worker and IP, and still warm up inside the premium pool.
        </p>
      </div>

      <div class="grid md:grid-cols-2 gap-4 lg:gap-5">
        {pools.map((p) => (
          <div class={`relative rounded-[14px] bg-white overflow-hidden ${p.featured ? 'ring-2 ring-[#0284c7]/35 shadow-[0_20px_40px_-20px_rgba(2,132,199,0.3)]' : 'ring-1 ring-[color:var(--border)]'}`}>
            <div class="h-1.5" style={`background:${p.accent}`}></div>
            {p.featured && (
              <div class="absolute top-1.5 right-4 inline-flex items-center h-5 px-2 rounded-b text-[10px] font-semibold uppercase tracking-[0.14em] font-mono bg-[#0284c7] text-white">
                Most paid plans
              </div>
            )}
            <div class="p-6">
              <div class="flex items-baseline justify-between mb-1">
                <div class={`text-[18px] font-semibold tracking-[-0.02em] ${p.featured ? 'text-[#0369a1]' : 'text-heading'}`}>{p.name}</div>
                <div class="text-[10.5px] font-mono uppercase tracking-[0.16em] text-muted-foreground">{p.when}</div>
              </div>
              <p class="mt-1 text-[13px] text-foreground/70 leading-snug">{p.summary}</p>
              <ul class="mt-4 space-y-2 text-[13px] text-foreground/75">
                {p.rules.map((r) => (
                  <li class="flex items-start gap-2">
                    <Icon name="check" size={12} class={p.featured ? 'text-[#0284c7] mt-1 shrink-0' : 'text-foreground/55 mt-1 shrink-0'} />
                    <span>{r}</span>
                  </li>
                ))}
              </ul>
            </div>
          </div>
        ))}
      </div>
    </div>
  </section>

  <!-- ============================================================
       HEALTH BANDS · auto-quarantine gauge + table
  ============================================================ -->
  <section class="py-20 md:py-28">
    <div class="container-page">
      <div class="max-w-2xl mb-12">
        <div class="text-[11px] uppercase tracking-[0.18em] text-muted-foreground font-mono mb-3">Auto-quarantine bands</div>
        <h2 class="text-[32px] md:text-[44px] font-semibold tracking-[-0.03em] leading-[1.05] text-heading">
          The bands, and when each fires.
        </h2>
        <p class="mt-4 text-[15.5px] text-foreground/70 leading-relaxed">
          We grade each mailbox on how often its mail lands in spam, over a rolling window. Our thresholds sit well to the left of where Google and SES start penalising senders, so a mailbox leaves the shared pool weeks before it would earn a public complaint.
        </p>
      </div>

      <div class="rounded-[14px] bg-white ring-1 ring-[color:var(--border)] p-7 md:p-10">
        <div class="flex items-baseline justify-between mb-7">
          <div class="text-[10.5px] uppercase tracking-[0.22em] font-mono text-muted-foreground">Spam placement · 0 to 100%</div>
          <div class="text-[10.5px] uppercase tracking-[0.22em] font-mono text-muted-foreground">Per-mailbox rolling window</div>
        </div>

        <!-- The gauge bar with 4 visible bands plus catastrophic gradient -->
        <div class="relative h-12 rounded-[6px] overflow-hidden flex">
          <div class="flex-[10] bg-emerald-100 relative">
            <div class="absolute inset-0 flex items-center px-3">
              <span class="text-[11px] font-mono font-semibold text-emerald-700">HEALTHY · 0 to 10%</span>
            </div>
          </div>
          <div class="flex-[10] bg-amber-100 relative">
            <div class="absolute inset-0 flex items-center px-3">
              <span class="text-[11px] font-mono font-semibold text-amber-700">WATCH · 10 to 20%</span>
            </div>
          </div>
          <div class="flex-[20] bg-rose-100 relative">
            <div class="absolute inset-0 flex items-center px-3">
              <span class="text-[11px] font-mono font-semibold text-rose-700">QUARANTINED · 20 to 40%</span>
            </div>
          </div>
          <div class="flex-[40] relative" style="background: linear-gradient(90deg, #fda4af 0%, #9f1239 100%);">
            <div class="absolute inset-0 flex items-center px-3">
              <span class="text-[11px] font-mono font-semibold text-white">BLOCKED · 40% to 80%</span>
            </div>
          </div>
          <div class="flex-[20] relative" style="background: linear-gradient(90deg, #881337 0%, #450a0a 100%);">
            <div class="absolute inset-0 flex items-center px-3">
              <span class="text-[11px] font-mono font-semibold text-white">CATASTROPHIC</span>
            </div>
          </div>
        </div>

        <!-- Tick marks below -->
        <div class="relative mt-1.5 h-3">
          {gaugeTicks.map((t) => (
            <div class="absolute" style={`left: ${t.pct}%; transform: translateX(-50%);`}>
              <div class="w-px h-2 bg-[color:var(--border)] mx-auto"></div>
              <div class="text-[10px] font-mono text-muted-foreground mt-1 text-center">{t.label}</div>
            </div>
          ))}
        </div>

        <!-- Band detail rows -->
        <div class="mt-10 grid md:grid-cols-2 lg:grid-cols-5 gap-px bg-[color:var(--border)] rounded-[10px] overflow-hidden ring-1 ring-[color:var(--border)]">
          {bands.map((b) => {
            const t = toneClass(b.tone);
            return (
              <div class="bg-white p-5">
                <div class="flex items-center gap-2">
                  <span class={`w-2 h-2 rounded-full ${t.dot}`}></span>
                  <span class="text-[13px] font-semibold text-heading">{b.name}</span>
                </div>
                <div class="mt-4 space-y-1.5 text-[11.5px] font-mono">
                  <div class="flex justify-between gap-2"><span class="text-muted-foreground">Spam</span><span class="text-heading font-semibold text-right">{b.spam}</span></div>
                  <div class="flex justify-between gap-2"><span class="text-muted-foreground">Complaint</span><span class="text-heading font-semibold text-right">{b.complaint}</span></div>
                  <div class="flex justify-between gap-2"><span class="text-muted-foreground">Bounce</span><span class="text-heading font-semibold text-right">{b.bounce}</span></div>
                </div>
                <p class="mt-4 pt-4 border-t border-[color:var(--border)] text-[12px] text-foreground/70 leading-snug">{b.action}</p>
              </div>
            );
          })}
        </div>

        <p class="mt-5 text-[11.5px] text-muted-foreground italic max-w-3xl">
          Between 10% and 20% the slow-down comes in two steps, watch then throttled, and the mailbox stays in the pool. Past 20% it comes out. A band only fires once there is enough to judge: at least 20 warmup deliveries in the past 7 days for spam placement, at least 100 delivered messages in the past 30 days for complaints. For reference, Google asks senders to keep spam below 0.1% and never reach 0.3%, and SES holds complaints below 0.1% and bounces below 5%.
        </p>
      </div>
    </div>
  </section>

  <!-- ============================================================
       AUTHENTICATION COVERAGE
  ============================================================ -->
  <section class="border-y border-[color:var(--border)] bg-[color:var(--surface-1)]/40 py-20 md:py-28">
    <div class="container-page">
      <div class="max-w-3xl mb-12">
        <div class="text-[11px] uppercase tracking-[0.18em] font-mono text-[#0284c7] mb-3">Authentication</div>
        <h2 class="text-[28px] md:text-[40px] font-semibold tracking-[-0.025em] leading-[1.06] text-heading">
          We check SPF, DKIM, DMARC, and PTR.
        </h2>
        <p class="mt-4 text-[15.5px] text-foreground/70 leading-relaxed">
          A mailbox cannot finish setup with broken authentication. We resolve every record live, show you exactly what to publish if something is missing, and re-check it daily once you are sending.
        </p>
      </div>

      <div class="grid md:grid-cols-2 lg:grid-cols-4 gap-px bg-[color:var(--border)] rounded-[14px] overflow-hidden ring-1 ring-[color:var(--border)]" style="box-shadow: var(--shadow-sm);">
        {auth.map((a) => (
          <div class="bg-white p-6">
            <div class="text-[10.5px] uppercase tracking-[0.18em] font-mono text-[#0284c7] mb-3">{a.tag}</div>
            <div class="text-[18px] font-semibold text-heading">{a.name}</div>
            <p class="mt-2 text-[13px] text-foreground/70 leading-relaxed">{a.body}</p>
            <p class="mt-3 pt-3 border-t border-[color:var(--border)] text-[12px] text-foreground/60 leading-snug">
              <span class="font-mono uppercase tracking-[0.14em] text-[10px] text-muted-foreground block mb-1">if it fails</span>
              {a.fail}
            </p>
          </div>
        ))}
      </div>
    </div>
  </section>

  <!-- ============================================================
       SUPPRESSION ENGINE
  ============================================================ -->
  <section class="bg-white py-20 md:py-28">
    <div class="container-page">
      <div class="grid lg:grid-cols-[1fr_1.8fr] gap-12 lg:gap-20 items-start">
        <div class="lg:sticky lg:top-24" style="align-self: start;">
          <div class="text-[11px] uppercase tracking-[0.18em] text-muted-foreground font-mono mb-3">Suppression</div>
          <h2 class="text-[28px] md:text-[40px] font-semibold tracking-[-0.025em] leading-[1.06] text-heading">
            When something goes wrong, we stop sending.
          </h2>
          <p class="mt-4 text-[15px] text-foreground/70 leading-relaxed max-w-md">
            The quickest way to handle a bad signal is to stop adding to it. By default a bounce, a complaint, an unsubscribe, or a STOP reply takes the recipient off every campaign before the next send goes out.
          </p>
          <ul class="mt-6 space-y-2 text-[13.5px] text-foreground/80">
            <li class="flex items-start gap-2"><Icon name="check" size={13} class="text-[#0284c7] mt-1 shrink-0" /><span>Workspace-wide. Every campaign skips a suppressed recipient on the next send.</span></li>
            <li class="flex items-start gap-2"><Icon name="check" size={13} class="text-[#0284c7] mt-1 shrink-0" /><span>One-click unsubscribe handled the moment it is clicked, per RFC 8058.</span></li>
            <li class="flex items-start gap-2"><Icon name="check" size={13} class="text-[#0284c7] mt-1 shrink-0" /><span>Replies like "stop" or "remove" are caught and suppressed on their own.</span></li>
          </ul>
        </div>

        <div class="rounded-[14px] bg-white ring-1 ring-[color:var(--border)] overflow-hidden">
          <div class="grid grid-cols-[minmax(0,1.4fr)_90px_minmax(0,1.8fr)_minmax(0,2.5fr)] px-5 py-3 bg-[color:var(--surface-1)] border-b border-[color:var(--border)] text-[10px] uppercase tracking-[0.18em] font-mono text-muted-foreground">
            <div>Trigger</div>
            <div>Scope</div>
            <div>Source</div>
            <div>What happens</div>
          </div>
          {suppression.map((s) => (
            <div class="grid grid-cols-[minmax(0,1.4fr)_90px_minmax(0,1.8fr)_minmax(0,2.5fr)] px-5 py-3.5 border-b border-[color:var(--border)] last:border-b-0 items-baseline gap-3">
              <div class="text-[13px] font-medium text-heading">{s.trigger}</div>
              <div>
                <span class="inline-flex items-center h-5 px-1.5 rounded text-[10px] font-mono uppercase tracking-[0.08em] bg-[color:var(--sky-1)] text-[#0369a1]">{s.scope}</span>
              </div>
              <div class="font-mono text-[11.5px] text-foreground/65 truncate">{s.source}</div>
              <div class="text-[12.5px] text-foreground/70 leading-snug">{s.note}</div>
            </div>
          ))}
        </div>
      </div>
    </div>
  </section>

  <!-- ============================================================
       RECOMMENDED POSTURE FOR COLD SENDING
  ============================================================ -->
  <section class="border-y border-[color:var(--border)] bg-[color:var(--surface-1)]/40 py-20 md:py-28">
    <div class="container-page">
      <div class="grid lg:grid-cols-[1fr_1.4fr] gap-12 lg:gap-20 items-start">
        <div class="lg:sticky lg:top-24" style="align-self: start;">
          <div class="text-[11px] uppercase tracking-[0.18em] text-muted-foreground font-mono mb-3">Cold sending posture</div>
          <h2 class="text-[28px] md:text-[40px] font-semibold tracking-[-0.025em] leading-[1.06] text-heading">
            How to ramp a cold mailbox.
          </h2>
          <p class="mt-4 text-[15px] text-foreground/70 leading-relaxed max-w-md">
            These are habits we have seen work, not guarantees. They line up with what the major receivers reward. Treat the default 50 / day cap as a ceiling to stay under.
          </p>
        </div>

        <div class="space-y-px">
          {posture.map((r, i) => (
            <div class="grid grid-cols-[140px_auto_1fr] gap-6 items-baseline py-5 border-b border-[color:var(--border)] last:border-b-0">
              <div class="text-[11px] uppercase tracking-[0.18em] font-mono text-muted-foreground">{r.stage}</div>
              <div class="flex items-baseline gap-1.5">
                <span class={`text-[28px] md:text-[36px] font-semibold tracking-[-0.025em] leading-none font-mono ${i === 2 ? 'text-[#0369a1]' : 'text-heading'}`}>{r.range}</span>
              </div>
              <p class="text-[13.5px] text-foreground/65 leading-relaxed">{r.note}</p>
            </div>
          ))}

          <div class="pt-6 flex flex-wrap items-center gap-x-6 gap-y-1 text-[11.5px] font-mono text-muted-foreground">
            <span>600s minimum gap, always</span>
            <span class="w-1 h-1 rounded-full bg-[color:var(--border)]"></span>
            <span>Business hours by recipient time zone</span>
            <span class="w-1 h-1 rounded-full bg-[color:var(--border)]"></span>
            <span>Warmup runs in parallel with cold</span>
          </div>
        </div>
      </div>
    </div>
  </section>

  <!-- ============================================================
       BY THE NUMBERS · real product defaults
  ============================================================ -->
  <section class="bg-white py-16 md:py-20">
    <div class="container-page">
      <div class="max-w-2xl mb-10">
        <div class="text-[11px] uppercase tracking-[0.18em] text-muted-foreground font-mono mb-3">By the numbers</div>
        <h2 class="text-[26px] md:text-[34px] font-semibold tracking-[-0.025em] leading-[1.06] text-heading">
          The whole safety policy, in one row.
        </h2>
        <p class="mt-3 text-[14px] text-foreground/65 leading-relaxed">
          Every number here is pulled straight from the code.
        </p>
      </div>

      <div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-px bg-[color:var(--border)] rounded-[14px] overflow-hidden ring-1 ring-[color:var(--border)]">
        {numbers.map((n) => (
          <div class="bg-white p-5 md:p-6">
            <div class="flex items-baseline gap-1">
              <span class="text-[28px] md:text-[34px] font-semibold tracking-[-0.025em] font-mono text-heading">{n.v}</span>
              <span class="text-[12px] text-muted-foreground">{n.u}</span>
            </div>
            <div class="mt-2 text-[11.5px] uppercase tracking-[0.14em] font-mono text-foreground/70">{n.l}</div>
            <div class="mt-3 pt-3 border-t border-[color:var(--border)] text-[10.5px] font-mono text-muted-foreground truncate">{n.src}</div>
          </div>
        ))}
      </div>
    </div>
  </section>

  <!-- ============================================================
       FAQ · sticky title + accordion
  ============================================================ -->
  <section class="bg-[color:var(--surface-1)]/40 border-y border-[color:var(--border)] py-20 md:py-24">
    <div class="container-page grid lg:grid-cols-[1fr_1.8fr] gap-12 lg:gap-20 items-start">
      <div class="lg:sticky lg:top-24" style="align-self: start;">
        <div class="text-[11px] uppercase tracking-[0.18em] text-muted-foreground font-mono mb-3">Deliverability FAQ</div>
        <h2 class="text-[28px] md:text-[36px] font-semibold tracking-[-0.025em] leading-[1.08] text-heading">
          The questions we get a lot.
        </h2>
        <p class="mt-4 text-[14.5px] text-foreground/70 leading-relaxed">
          There is more in the <a class="text-[#0369a1] hover:text-[#075985] font-medium" href="https://docs.warmbly.com/learn/deliverability/">deliverability handbook</a>.
        </p>
      </div>

      <div class="divide-y divide-[color:var(--border)]" data-faq>
        {faq.map(([q, a]) => (
          <div class="faq-row py-2">
            <button type="button" class="faq-trigger group w-full flex items-start justify-between gap-4 py-3 text-left" aria-expanded="false">
              <span class="text-[15.5px] font-medium text-heading group-hover:text-[#0369a1] transition-colors">{q}</span>
              <span class="faq-icon shrink-0 inline-flex items-center justify-center w-7 h-7 rounded-full bg-white ring-1 ring-[color:var(--border)] text-foreground/60 transition-transform duration-300 ease-out">
                <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14"/><path d="M5 12h14"/></svg>
              </span>
            </button>
            <div class="faq-panel grid grid-rows-[0fr] transition-[grid-template-rows] duration-300 ease-out">
              <div class="overflow-hidden">
                <p class="pb-4 pr-12 text-[14px] text-foreground/75 leading-relaxed max-w-2xl">{a}</p>
              </div>
            </div>
          </div>
        ))}
      </div>

      <script is:inline>
        (function () {
          const faq = document.querySelector('[data-faq]');
          if (!faq) return;
          faq.querySelectorAll('.faq-trigger').forEach(function (btn) {
            btn.addEventListener('click', function () {
              const row   = btn.closest('.faq-row');
              const panel = row.querySelector('.faq-panel');
              const icon  = btn.querySelector('.faq-icon');
              const open  = btn.getAttribute('aria-expanded') === 'true';
              btn.setAttribute('aria-expanded', String(!open));
              panel.style.gridTemplateRows = open ? '0fr' : '1fr';
              if (icon) icon.style.transform = open ? 'rotate(0deg)' : 'rotate(45deg)';
            });
          });
        })();
      </script>
    </div>
  </section>

  <CTA
    title="See where your mailbox really stands."
    description="Connect one and get a full SPF, DKIM, DMARC, and PTR report, plus its current health, in a few minutes."
    primaryLabel="Run a free audit"
    primaryHref="https://app.warmbly.com/register"
    secondaryLabel="Read the handbook"
    secondaryHref="https://docs.warmbly.com/learn/deliverability/"
  />
</Layout>
