// Integrations — editorial atlas of connections.

const { useState: useIntState, useMemo: useIntMemo, useEffect: useIntEffect } = React;

const INT_CATEGORIES = [
  { id: 'all',           label: 'All' },
  { id: 'comm',          label: 'Chat & comms' },
  { id: 'productivity',  label: 'Productivity' },
  { id: 'docs',          label: 'Docs & files' },
  { id: 'code',          label: 'Code & dev' },
  { id: 'crm',           label: 'CRM & sales' },
  { id: 'calendar',      label: 'Calendar & email' },
  { id: 'design',        label: 'Design' },
  { id: 'data',          label: 'Data & analytics' },
  { id: 'marketing',     label: 'Marketing' },
];

// status: 'live' | 'beta' | 'soon'
const INTEGRATIONS = [
  // Chat & comms — the surfaces Octodus lives in
  { id: 'telegram',   name: 'Telegram',          cat: 'comm',         status: 'live', initial: 'T',  bg: '#229ED9', desc: 'Octodus’ native home. DMs, groups and channels.' },
  { id: 'slack',      name: 'Slack',             cat: 'comm',         status: 'beta', initial: '#',  bg: '#4A154B', desc: 'Mention @octodus in any channel. Threads, DMs, slash commands.' },
  { id: 'discord',    name: 'Discord',           cat: 'comm',         status: 'beta', initial: 'D',  bg: '#5865F2', desc: 'Server-aware bot — gets community context, follows rules.' },
  { id: 'whatsapp',   name: 'WhatsApp',          cat: 'comm',         status: 'beta', initial: 'W',  bg: '#25D366', desc: 'Voice notes and groups. Octodus replies like a coworker.' },
  { id: 'teams',      name: 'Microsoft Teams',   cat: 'comm',         status: 'soon', initial: 'M',  bg: '#5059C9', desc: 'Channel and chat support. SSO-friendly.' },

  // Productivity
  { id: 'notion',     name: 'Notion',            cat: 'productivity', status: 'live', initial: 'N',  bg: '#0F0F0F', desc: 'Reads & writes pages, syncs database rows.' },
  { id: 'linear',     name: 'Linear',            cat: 'productivity', status: 'live', initial: 'L',  bg: '#5E6AD2', desc: 'Files issues, updates statuses, schedules cycles.' },
  { id: 'asana',      name: 'Asana',             cat: 'productivity', status: 'beta', initial: 'A',  bg: '#F06A6A', desc: 'Create tasks from chat, follow up automatically.' },
  { id: 'clickup',    name: 'ClickUp',           cat: 'productivity', status: 'beta', initial: 'C',  bg: '#7B68EE', desc: 'Two-way sync across spaces, lists and tasks.' },
  { id: 'trello',     name: 'Trello',            cat: 'productivity', status: 'beta', initial: 'T',  bg: '#0079BF', desc: 'Move cards, add comments, set due dates.' },
  { id: 'airtable',   name: 'Airtable',          cat: 'productivity', status: 'live', initial: 'A',  bg: '#FCB400', desc: 'Read & write records, build views in chat.' },

  // Docs & files
  { id: 'gdrive',     name: 'Google Drive',      cat: 'docs',         status: 'live', initial: 'G',  bg: '#0F9D58', desc: 'Find, read, share. Octodus follows your folder rules.' },
  { id: 'gdocs',      name: 'Google Docs',       cat: 'docs',         status: 'live', initial: 'D',  bg: '#4285F4', desc: 'Drafts edits inline, takes meeting notes, version aware.' },
  { id: 'dropbox',    name: 'Dropbox',           cat: 'docs',         status: 'beta', initial: 'D',  bg: '#0061FF', desc: 'Cross-team file ops. Smart links in chat.' },
  { id: 'onedrive',   name: 'OneDrive',          cat: 'docs',         status: 'soon', initial: 'O',  bg: '#0364B8', desc: 'Personal & enterprise file access.' },

  // Code & dev
  { id: 'github',     name: 'GitHub',            cat: 'code',         status: 'live', initial: 'G',  bg: '#0D1117', desc: 'PRs, issues, releases. Reviews while you sleep.' },
  { id: 'gitlab',     name: 'GitLab',            cat: 'code',         status: 'beta', initial: 'G',  bg: '#FC6D26', desc: 'Pipelines, MRs, infra-as-code reviews.' },
  { id: 'vercel',     name: 'Vercel',            cat: 'code',         status: 'beta', initial: 'V',  bg: '#000000', desc: 'Deploys, env vars, preview URLs in chat.' },
  { id: 'sentry',     name: 'Sentry',            cat: 'code',         status: 'beta', initial: 'S',  bg: '#362D59', desc: 'Triages errors, assigns, drafts fixes.' },
  { id: 'datadog',    name: 'Datadog',           cat: 'code',         status: 'soon', initial: 'D',  bg: '#632CA6', desc: 'Reads metrics & logs to diagnose live.' },

  // CRM & sales
  { id: 'hubspot',    name: 'HubSpot',           cat: 'crm',          status: 'live', initial: 'H',  bg: '#FF7A59', desc: 'Logs hot leads from chat, drafts follow-ups.' },
  { id: 'salesforce', name: 'Salesforce',        cat: 'crm',          status: 'beta', initial: 'S',  bg: '#00A1E0', desc: 'Update accounts, opportunities, contacts.' },
  { id: 'pipedrive',  name: 'Pipedrive',         cat: 'crm',          status: 'beta', initial: 'P',  bg: '#1A1A1A', desc: 'Move deals, schedule activities, post receipts.' },
  { id: 'intercom',   name: 'Intercom',          cat: 'crm',          status: 'soon', initial: 'I',  bg: '#1F8DED', desc: 'Read inbox, draft replies, escalate as needed.' },

  // Calendar & email
  { id: 'gcal',       name: 'Google Calendar',   cat: 'calendar',     status: 'live', initial: 'G',  bg: '#4285F4', desc: 'Schedules, reschedules, finds time across humans.' },
  { id: 'gmail',      name: 'Gmail',             cat: 'calendar',     status: 'live', initial: 'M',  bg: '#EA4335', desc: 'Drafts, follows up, triages important threads.' },
  { id: 'outlook',    name: 'Outlook',           cat: 'calendar',     status: 'beta', initial: 'O',  bg: '#0078D4', desc: 'Email + calendar, enterprise SSO.' },

  // Design
  { id: 'figma',      name: 'Figma',             cat: 'design',       status: 'beta', initial: 'F',  bg: '#1E1E1E', desc: 'Reads files, drops comments, exports assets.' },
  { id: 'canva',      name: 'Canva',             cat: 'design',       status: 'soon', initial: 'C',  bg: '#00C4CC', desc: 'Generate brand-safe one-pagers in chat.' },

  // Data
  { id: 'snowflake',  name: 'Snowflake',         cat: 'data',         status: 'soon', initial: 'S',  bg: '#29B5E8', desc: 'Run SQL from chat, post results.' },
  { id: 'bigquery',   name: 'BigQuery',          cat: 'data',         status: 'soon', initial: 'B',  bg: '#4285F4', desc: 'Querying & dashboards via natural language.' },

  // Marketing
  { id: 'mailchimp',  name: 'Mailchimp',         cat: 'marketing',    status: 'beta', initial: 'M',  bg: '#FFE01B', fg: '#000', desc: 'Draft campaigns, segment audiences, schedule sends.' },
  { id: 'webflow',    name: 'Webflow',           cat: 'marketing',    status: 'soon', initial: 'W',  bg: '#146EF5', desc: 'CMS reads & writes. Stage and publish from chat.' },
];

const FEATURED = ['telegram', 'github', 'notion', 'slack', 'gcal'];

// Short scope hint per integration — surfaces the OAuth story without legal-ese.
const SCOPE_HINTS = {
  telegram:  'Native · no OAuth',
  slack:     'Channels · DMs',
  discord:   'Servers · DMs',
  whatsapp:  'Voice · groups',
  teams:     'SSO · channels',
  notion:    'Read & write',
  linear:    'Issues · cycles',
  asana:     'Tasks · follow-ups',
  clickup:   'Two-way sync',
  trello:    'Cards · comments',
  airtable:  'Records · views',
  gdrive:    'Find · share',
  gdocs:     'Draft · edit',
  dropbox:   'Files · links',
  onedrive:  'Personal · ent',
  github:    'PRs · reviews',
  gitlab:    'Pipelines · MRs',
  vercel:    'Deploys · envs',
  sentry:    'Triage · fix',
  datadog:   'Metrics · logs',
  hubspot:   'Leads · drafts',
  salesforce:'Accounts · opps',
  pipedrive: 'Deals · activity',
  intercom:  'Inbox · replies',
  gcal:      'Schedule · find time',
  gmail:     'Draft · triage',
  outlook:   'Email · calendar',
  figma:     'Files · comments',
  canva:     'One-pagers',
  snowflake: 'SQL · results',
  bigquery:  'NL queries',
  mailchimp: 'Drafts · sends',
  webflow:   'CMS · publish',
};

// Simple Icons slugs for real brand glyphs (rendered white on the brand tile).
const LOGO_SLUG = {
  telegram: 'telegram', slack: 'slack', discord: 'discord', whatsapp: 'whatsapp',
  teams: 'microsoftteams', notion: 'notion', linear: 'linear', asana: 'asana',
  clickup: 'clickup', trello: 'trello', airtable: 'airtable',
  gdrive: 'googledrive', gdocs: 'googledocs', dropbox: 'dropbox', onedrive: 'microsoftonedrive',
  github: 'github', gitlab: 'gitlab', vercel: 'vercel', sentry: 'sentry', datadog: 'datadog',
  hubspot: 'hubspot', salesforce: 'salesforce', pipedrive: 'pipedrive', intercom: 'intercom',
  gcal: 'googlecalendar', gmail: 'gmail', outlook: 'microsoftoutlook',
  figma: 'figma', canva: 'canva', snowflake: 'snowflake', bigquery: 'googlebigquery',
  mailchimp: 'mailchimp', webflow: 'webflow',
};

const LOGO_ICONIFY = {
  slack: 'logos/slack-icon',
  teams: 'logos/microsoft-teams',
  onedrive: 'logos/microsoft-onedrive',
  outlook: 'vscode-icons/file-type-outlook',
  salesforce: 'logos/salesforce',
  pipedrive: 'logos/pipedrive',
  canva: 'devicon/canva',
};

function connectHref(item) {
  if (item.status === 'soon') {
    return `https://calend.ly/emdx`;
  }
  return 'https://calend.ly/emdx';
}

function connectLabel(item) {
  if (item.status === 'soon') return 'Notify me';
  if (item.status === 'beta') return 'Try in beta';
  return 'Connect';
}

function IntStatusBadge({ status }) {
  const map = {
    live: { label: 'Live', cls: 'live' },
    beta: { label: 'Beta', cls: 'beta' },
    soon: { label: 'Soon', cls: 'soon' },
  };
  const it = map[status];
  return <span className={`int-status int-status-${it.cls}`}>{it.label}</span>;
}

function IntLogo({ item, size = 44 }) {
  const [errored, setErrored] = React.useState(false);
  const iconify = LOGO_ICONIFY[item.id];
  const slug = LOGO_SLUG[item.id];

  if (iconify && !errored) {
    return (
      <div
        className="int-logo int-logo-white"
        style={{ width: size, height: size, fontSize: size * 0.42, color: '#1A1A1A' }}
        aria-hidden="true"
      >
        <img
          className="int-logo-img"
          src={`https://api.iconify.design/${iconify}.svg`}
          alt=""
          style={{ width: size * 0.6, height: size * 0.6 }}
          onError={() => setErrored(true)}
        />
      </div>
    );
  }

  const fg = item.fg || '#fff';
  const glyphColor = (item.fg ? '000000' : 'ffffff');
  return (
    <div
      className="int-logo"
      style={{
        width: size, height: size,
        background: item.bg,
        color: fg,
        fontSize: size * 0.42,
      }}
      aria-hidden="true"
    >
      {slug && !errored ? (
        <img
          className="int-logo-img"
          src={`https://cdn.simpleicons.org/${slug}/${glyphColor}`}
          alt=""
          style={{ width: size * 0.54, height: size * 0.54 }}
          onError={() => setErrored(true)}
        />
      ) : (
        item.initial
      )}
    </div>
  );
}

// ───────────────────────────────────────────────────────────────────────────
// 1. HERO
// ───────────────────────────────────────────────────────────────────────────

function IntegrationsHero({ query, setQuery, total, liveCount, betaCount, soonCount }) {
  const stats = [
    { k: total,     v: 'connections' },
    { k: liveCount, v: 'live now' },
    { k: betaCount, v: 'in beta' },
    { k: 'OAuth',   v: 'only' },
  ];

  return (
    <section className="page-hero int-hero">
      <div className="container page-hero-body">
        <div className="eyebrow" data-reveal data-reveal-eager>The Atlas · vol. 01</div>
        <h1 data-reveal data-reveal-eager>
          Lives where<br/>
          <em>the work already is.</em>
        </h1>
        <p className="page-hero-sub" data-reveal data-reveal-eager>
          Octodus plugs into the tools your team uses every day. OAuth-only, scoped per-team,
          revocable in one click — {total} connections and counting, new ones shipping weekly.
        </p>

        <div className="int-search" data-reveal data-reveal-eager>
          <span className="int-search-icon">{Icons.search({ width: 18, height: 18 })}</span>
          <input
            type="search"
            placeholder="Search the atlas — Telegram, GitHub, Notion…"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            aria-label="Search integrations"
          />
          {query
            ? <button className="int-search-clear" onClick={() => setQuery('')} aria-label="Clear search">×</button>
            : <kbd className="int-search-kbd">/</kbd>}
        </div>

        <dl className="int-stats" data-reveal data-reveal-eager>
          {stats.map((s, i) => (
            <div className="int-stat" key={i}>
              <dt>{s.k}</dt>
              <dd>{s.v}</dd>
            </div>
          ))}
        </dl>
      </div>

      <style>{`
        .int-hero { padding-bottom: 72px; }
        .int-hero .eyebrow { display: inline-flex; align-items: center; gap: 10px; }
        .int-hero .eyebrow::before {
          content: "";
          display: inline-block;
          width: 28px; height: 1px;
          background: var(--accent);
        }

        .int-search {
          margin-top: 36px;
          display: flex;
          align-items: center;
          gap: 12px;
          padding: 14px 16px 14px 20px;
          background: var(--bg-card);
          border: 1px solid var(--border-light);
          border-radius: 999px;
          max-width: 560px;
          transition: border-color 200ms var(--ease-out), background 200ms var(--ease-out), box-shadow 220ms var(--ease-out);
          box-shadow: 0 8px 22px -16px rgba(58, 49, 32, 0.35);
        }
        .int-search:focus-within {
          border-color: var(--accent-tint-50);
          background: var(--bg-card-hover);
          box-shadow: 0 0 0 4px var(--accent-soft), 0 8px 22px -16px var(--accent-tint-50);
        }
        .int-search-icon { color: var(--text-muted); display: inline-flex; }
        .int-search input {
          flex: 1;
          background: transparent;
          border: none;
          color: var(--text);
          font-family: var(--font-sans);
          font-size: 15.5px;
          outline: none;
        }
        .int-search input::placeholder { color: var(--text-muted); }
        .int-search-kbd {
          font-family: var(--font-mono);
          font-size: 11px;
          font-weight: 600;
          padding: 4px 9px;
          border: 1px solid var(--border-light);
          border-radius: 6px;
          color: var(--text-muted);
          background: var(--bg);
          letter-spacing: 0.04em;
        }
        .int-search-clear {
          width: 26px; height: 26px;
          border-radius: 50%;
          background: var(--bg-elev);
          border: none;
          color: var(--text-secondary);
          font-size: 17px;
          line-height: 1;
        }
        .int-search-clear:hover { color: var(--accent-light); }

        .int-stats {
          margin-top: 36px;
          display: flex;
          flex-wrap: wrap;
          gap: 0;
          border-top: 1px solid var(--border);
          padding-top: 22px;
          max-width: 720px;
        }
        .int-stat {
          flex: 1 1 auto;
          min-width: 130px;
          padding-right: 28px;
          padding-left: 0;
          border-left: none;
          display: flex;
          flex-direction: column;
          gap: 4px;
        }
        .int-stat + .int-stat {
          padding-left: 28px;
          position: relative;
        }
        .int-stat + .int-stat::before {
          content: "";
          position: absolute;
          left: 0; top: 6px; bottom: 6px;
          width: 1px;
          background: var(--border);
        }
        .int-stat dt {
          font-family: var(--font-heading);
          font-size: 30px;
          font-weight: 700;
          letter-spacing: -0.04em;
          color: var(--text);
          line-height: 1;
        }
        .int-stat dd {
          font-family: var(--font-mono);
          font-size: 11px;
          font-weight: 500;
          letter-spacing: 0.14em;
          text-transform: uppercase;
          color: var(--text-muted);
        }
        @media (max-width: 720px) {
          .int-hero { padding-bottom: 56px; }
          .int-search { max-width: 100%; }
          .int-stats { gap: 18px 0; }
          .int-stat { min-width: calc(50% - 0px); padding-right: 16px; }
          .int-stat + .int-stat::before { display: none; }
          .int-stat:nth-child(odd) { padding-left: 0; }
          .int-stat:nth-child(even) { padding-left: 18px; border-left: 1px solid var(--border); }
        }
      `}</style>
    </section>
  );
}

// ───────────────────────────────────────────────────────────────────────────
// 2. KINETIC LOGO MARQUEE — section separator
// ───────────────────────────────────────────────────────────────────────────

function LogoMarquee() {
  const row = [...INTEGRATIONS, ...INTEGRATIONS];
  return (
    <section className="logo-marquee" aria-hidden="true">
      <div className="logo-marquee-fade logo-marquee-fade-l" />
      <div className="logo-marquee-track">
        {row.map((it, i) => (
          <span className="logo-marquee-cell" key={i}>
            <IntLogo item={it} size={28} />
            <span className="logo-marquee-name">{it.name}</span>
          </span>
        ))}
      </div>
      <div className="logo-marquee-fade logo-marquee-fade-r" />

      <style>{`
        .logo-marquee {
          padding: 26px 0;
          position: relative;
          overflow: hidden;
          border-top: 1px solid var(--border);
          border-bottom: 1px solid var(--border);
          background: var(--bg-elev);
        }
        .logo-marquee-track {
          display: flex;
          gap: 14px;
          width: max-content;
          animation: oct-marquee 80s linear infinite;
        }
        @keyframes oct-marquee {
          from { transform: translateX(0); }
          to   { transform: translateX(-50%); }
        }
        .logo-marquee:hover .logo-marquee-track {
          animation-play-state: paused;
        }
        .logo-marquee-cell {
          display: inline-flex;
          align-items: center;
          gap: 10px;
          padding: 6px 14px 6px 6px;
          background: var(--bg-card);
          border: 1px solid var(--border);
          border-radius: 999px;
          white-space: nowrap;
          transition: border-color 180ms var(--ease-out);
        }
        .logo-marquee-cell:hover {
          border-color: var(--accent-tint-30);
        }
        .logo-marquee-cell .int-logo {
          border-radius: 999px;
          box-shadow: none;
          border: 1px solid var(--border);
        }
        .logo-marquee-cell .int-logo-white {
          border: 1px solid var(--border-light);
        }
        .logo-marquee-name {
          font-family: var(--font-mono);
          font-size: 11.5px;
          font-weight: 500;
          letter-spacing: 0.04em;
          color: var(--text-secondary);
        }
        .logo-marquee-fade {
          position: absolute;
          top: 0; bottom: 0;
          width: 140px;
          z-index: 1;
          pointer-events: none;
        }
        .logo-marquee-fade-l {
          left: 0;
          background: linear-gradient(90deg, var(--bg-elev) 20%, transparent);
        }
        .logo-marquee-fade-r {
          right: 0;
          background: linear-gradient(270deg, var(--bg-elev) 20%, transparent);
        }
        @media (prefers-reduced-motion: reduce) {
          .logo-marquee-track { animation: none; }
        }
      `}</style>
    </section>
  );
}

// ───────────────────────────────────────────────────────────────────────────
// 3. FEATURED ATLAS — editorial bento (1 hero + 4 supporting)
// ───────────────────────────────────────────────────────────────────────────

function FeaturedAtlas() {
  const items = FEATURED.map(id => INTEGRATIONS.find(i => i.id === id)).filter(Boolean);
  const [hero, ...supporting] = items;

  return (
    <section className="atlas">
      <div className="container">
        <div className="atlas-head" data-reveal>
          <div>
            <div className="eyebrow">
              <span className="eyebrow-rule" />
              Most-used
            </div>
            <h2>Where teams plug in first.</h2>
          </div>
          <a className="atlas-jump" href="#integrations-directory">
            See all {INTEGRATIONS.length} →
          </a>
        </div>

        <div className="atlas-grid" data-stagger>
          <a
            className="atlas-cell atlas-cell--hero"
            href={connectHref(hero)}
            target={hero.status === 'soon' ? '_self' : '_blank'}
            rel="noopener"
            style={{ '--i': 0 }}
          >
            <div className="atlas-watermark" aria-hidden="true">01</div>
            <div className="atlas-cell-top">
              <IntLogo item={hero} size={64} />
              <IntStatusBadge status={hero.status} />
            </div>
            <div className="atlas-cell-body">
              <div className="atlas-hero-tag">— The native home</div>
              <div className="atlas-hero-name">{hero.name}</div>
              <p className="atlas-hero-desc">
                Octodus was born inside Telegram. DMs, group threads, channels and voice notes —
                one bot, your whole team, every message.
              </p>
            </div>
            <div className="atlas-cell-foot">
              <span className="atlas-scope">{SCOPE_HINTS[hero.id]}</span>
              <span className="atlas-cell-cta">Open in chat {Icons.arrow({ width: 13, height: 13 })}</span>
            </div>
          </a>

          {supporting.map((item, idx) => (
            <a
              className="atlas-cell atlas-cell--small"
              key={item.id}
              href={connectHref(item)}
              target={item.status === 'soon' ? '_self' : '_blank'}
              rel="noopener"
              style={{ '--i': idx + 1 }}
            >
              <div className="atlas-cell-top">
                <IntLogo item={item} size={42} />
                <IntStatusBadge status={item.status} />
              </div>
              <div className="atlas-small-name">{item.name}</div>
              <div className="atlas-cell-foot atlas-cell-foot--small">
                <span className="atlas-scope">{SCOPE_HINTS[item.id]}</span>
                <span className="atlas-cell-cta atlas-cell-cta--tiny">{Icons.arrow({ width: 12, height: 12 })}</span>
              </div>
            </a>
          ))}
        </div>
      </div>

      <style>{`
        .atlas { padding: 80px 0 56px; }

        .atlas-head {
          display: flex;
          justify-content: space-between;
          align-items: flex-end;
          gap: 24px;
          margin-bottom: 28px;
          flex-wrap: wrap;
        }
        .atlas-head h2 {
          font-size: clamp(1.9rem, 3.2vw, 2.6rem);
          letter-spacing: -0.035em;
          margin-top: 10px;
        }
        .atlas-head .eyebrow {
          display: inline-flex;
          align-items: center;
          gap: 10px;
        }
        .eyebrow-rule {
          display: inline-block;
          width: 22px; height: 1px;
          background: var(--accent);
        }
        .atlas-jump {
          font-family: var(--font-mono);
          font-size: 12px;
          letter-spacing: 0.06em;
          color: var(--text-secondary);
          padding: 8px 14px;
          border: 1px solid var(--border);
          border-radius: 999px;
          background: var(--bg-card);
          transition: color 180ms var(--ease-out), border-color 180ms var(--ease-out), background 180ms var(--ease-out);
        }
        .atlas-jump:hover {
          color: var(--accent);
          border-color: var(--accent-tint-40);
          background: var(--bg-card-hover);
        }

        .atlas-grid {
          display: grid;
          grid-template-columns: 1.55fr 1fr 1fr;
          grid-auto-rows: minmax(180px, auto);
          gap: 16px;
        }
        @media (max-width: 1000px) {
          .atlas-grid { grid-template-columns: 1fr 1fr; }
        }
        @media (max-width: 600px) {
          .atlas-grid { grid-template-columns: 1fr; }
        }

        .atlas-cell {
          position: relative;
          padding: 22px 22px 18px;
          background: var(--bg-card);
          border: 1px solid var(--border);
          border-radius: 22px;
          display: flex;
          flex-direction: column;
          gap: 14px;
          overflow: hidden;
          transition:
            border-color 240ms var(--ease-out),
            background 240ms var(--ease-out),
            transform 240ms var(--ease-out),
            box-shadow 280ms var(--ease-out);
        }
        .atlas-cell:hover {
          background: var(--bg-card-hover);
          border-color: var(--accent-tint-30);
          transform: translateY(-2px);
          box-shadow: 0 24px 40px -28px rgba(58, 49, 32, 0.30);
        }

        .atlas-cell--hero {
          grid-column: 1;
          grid-row: 1 / span 2;
          padding: 30px 30px 26px;
          background:
            radial-gradient(ellipse 80% 60% at 0% 0%, var(--accent-soft), transparent 60%),
            var(--bg-card);
        }
        @media (max-width: 1000px) {
          .atlas-cell--hero { grid-column: 1 / -1; grid-row: auto; min-height: 280px; }
        }

        .atlas-cell-top {
          display: flex;
          align-items: center;
          justify-content: space-between;
          gap: 12px;
        }

        .atlas-watermark {
          position: absolute;
          right: 22px; bottom: 18px;
          font-family: var(--font-heading);
          font-weight: 800;
          font-size: 120px;
          letter-spacing: -0.08em;
          line-height: 0.8;
          color: var(--accent-tint-08);
          pointer-events: none;
          user-select: none;
        }

        .atlas-cell-body {
          display: flex;
          flex-direction: column;
          gap: 8px;
          flex: 1;
          position: relative;
          z-index: 1;
        }
        .atlas-hero-tag {
          font-family: var(--font-mono);
          font-size: 11.5px;
          letter-spacing: 0.06em;
          color: var(--accent);
          text-transform: uppercase;
        }
        .atlas-hero-name {
          font-family: var(--font-heading);
          font-weight: 800;
          font-size: clamp(2rem, 3.2vw, 2.6rem);
          letter-spacing: -0.045em;
          line-height: 0.98;
          color: var(--text);
        }
        .atlas-hero-desc {
          font-size: 15px;
          line-height: 1.55;
          color: var(--text-secondary);
          max-width: 36ch;
          text-wrap: pretty;
        }

        .atlas-small-name {
          font-family: var(--font-heading);
          font-weight: 700;
          font-size: 18px;
          letter-spacing: -0.02em;
          color: var(--text);
          margin-top: -2px;
        }

        .atlas-cell-foot {
          display: flex;
          align-items: center;
          justify-content: space-between;
          gap: 10px;
          padding-top: 14px;
          border-top: 1px solid var(--border);
          position: relative;
          z-index: 1;
        }
        .atlas-cell-foot--small {
          padding-top: 12px;
          margin-top: auto;
        }
        .atlas-scope {
          font-family: var(--font-mono);
          font-size: 11px;
          letter-spacing: 0.05em;
          color: var(--text-muted);
        }
        .atlas-cell-cta {
          font-family: var(--font-mono);
          font-size: 11.5px;
          font-weight: 600;
          letter-spacing: 0.05em;
          color: var(--accent);
          display: inline-flex;
          align-items: center;
          gap: 6px;
          white-space: nowrap;
          transition: gap 180ms var(--ease-out);
        }
        .atlas-cell:hover .atlas-cell-cta { gap: 9px; }
        .atlas-cell-cta--tiny {
          padding: 5px 6px 5px 8px;
          border-radius: 999px;
          border: 1px solid var(--border);
          color: var(--text-secondary);
        }
        .atlas-cell:hover .atlas-cell-cta--tiny {
          color: var(--accent);
          border-color: var(--accent-tint-30);
        }
      `}</style>
    </section>
  );
}

// ───────────────────────────────────────────────────────────────────────────
// 4. CONNECTION FLOW — 3-step OAuth trust strip
// ───────────────────────────────────────────────────────────────────────────

function ConnectionFlow() {
  const steps = [
    {
      num: '01',
      title: 'Authorize',
      desc: 'Standard OAuth in a new tab. The provider asks you. Octodus never sees a password — only the token they hand back.',
    },
    {
      num: '02',
      title: 'Scope',
      desc: 'Per-team, least-privilege. Octodus requests only what an integration actually needs — no surprise scopes, no “read everything”.',
    },
    {
      num: '03',
      title: 'Revoke',
      desc: 'One click in the dashboard, or remove the bot from the workspace. Tokens die immediately. No support ticket required.',
    },
  ];

  return (
    <section className="flow">
      <div className="container">
        <div className="flow-head" data-reveal>
          <div className="eyebrow">
            <span className="eyebrow-rule" />
            Connections, demystified
          </div>
          <h2>Three doors. <em>One key.</em></h2>
          <p className="flow-sub">
            Same OAuth flow you&apos;ve done a hundred times. No tokens to paste, no JSON to copy, no manual API keys to babysit.
          </p>
        </div>

        <ol className="flow-steps" data-stagger>
          {steps.map((s, i) => (
            <li className="flow-step" key={s.num} style={{ '--i': i }}>
              <div className="flow-step-bar">
                <span className="flow-step-num">{s.num}</span>
                <span className="flow-step-rule" />
                {i < steps.length - 1 && <span className="flow-step-arrow">{Icons.arrow({ width: 14, height: 14 })}</span>}
              </div>
              <h3 className="flow-step-title">{s.title}</h3>
              <p className="flow-step-desc">{s.desc}</p>
            </li>
          ))}
        </ol>

        <div className="flow-footnote" data-reveal>
          <span className="flow-footnote-mark">{Icons.check({ width: 12, height: 12 })}</span>
          <span>SOC 2 in progress · GDPR compliant · EU + US data residency on request</span>
        </div>
      </div>

      <style>{`
        .flow { padding: 64px 0 80px; }
        .flow-head { max-width: 680px; margin-bottom: 48px; }
        .flow-head .eyebrow {
          display: inline-flex;
          align-items: center;
          gap: 10px;
          margin-bottom: 14px;
        }
        .flow-head h2 {
          font-size: clamp(2rem, 3.6vw, 3rem);
          letter-spacing: -0.04em;
          line-height: 1;
        }
        .flow-head h2 em {
          font-style: italic;
          font-family: 'Bricolage Grotesque', serif;
          font-weight: 600;
          color: var(--accent);
        }
        .flow-sub {
          font-size: 16px;
          line-height: 1.6;
          color: var(--text-secondary);
          margin-top: 16px;
          max-width: 56ch;
        }

        .flow-steps {
          list-style: none;
          display: grid;
          grid-template-columns: repeat(3, 1fr);
          gap: 28px;
          counter-reset: flow;
        }
        @media (max-width: 900px) {
          .flow-steps { grid-template-columns: 1fr; gap: 22px; }
        }

        .flow-step {
          padding: 26px 24px 28px;
          background: var(--bg-card);
          border: 1px solid var(--border);
          border-radius: 22px;
          display: flex;
          flex-direction: column;
          gap: 14px;
          position: relative;
          transition: border-color 220ms var(--ease-out), background 220ms var(--ease-out);
        }
        .flow-step:hover {
          border-color: var(--accent-tint-25);
          background: var(--bg-card-hover);
        }
        .flow-step-bar {
          display: flex;
          align-items: center;
          gap: 14px;
        }
        .flow-step-num {
          font-family: var(--font-heading);
          font-weight: 800;
          font-size: 46px;
          letter-spacing: -0.06em;
          line-height: 0.85;
          color: var(--accent);
          font-feature-settings: 'ss01', 'tnum';
        }
        .flow-step-rule {
          flex: 1;
          height: 1px;
          background: var(--border);
        }
        .flow-step-arrow {
          color: var(--text-muted);
          display: inline-flex;
        }
        .flow-step-title {
          font-family: var(--font-heading);
          font-weight: 700;
          font-size: 22px;
          letter-spacing: -0.025em;
          color: var(--text);
        }
        .flow-step-desc {
          font-size: 14.5px;
          line-height: 1.6;
          color: var(--text-secondary);
          text-wrap: pretty;
        }

        .flow-footnote {
          margin-top: 28px;
          padding: 14px 18px;
          display: inline-flex;
          align-items: center;
          gap: 10px;
          background: var(--bg-elev);
          border: 1px solid var(--border);
          border-radius: 999px;
          font-family: var(--font-mono);
          font-size: 11.5px;
          letter-spacing: 0.04em;
          color: var(--text-secondary);
        }
        .flow-footnote-mark {
          display: inline-flex;
          width: 18px; height: 18px;
          align-items: center; justify-content: center;
          background: var(--accent-soft);
          color: var(--accent);
          border-radius: 50%;
        }
      `}</style>
    </section>
  );
}

// ───────────────────────────────────────────────────────────────────────────
// 5. DIRECTORY — refined card grid + chip filter
// ───────────────────────────────────────────────────────────────────────────

function IntegrationCard({ item, idx }) {
  return (
    <article className="int-card" style={{ '--i': (idx || 0) % 12 }}>
      <div className="int-card-head">
        <IntLogo item={item} />
        <IntStatusBadge status={item.status} />
      </div>
      <div className="int-card-name">{item.name}</div>
      <p className="int-card-desc">{item.desc}</p>
      <div className="int-card-foot">
        <span className="int-card-scope">{SCOPE_HINTS[item.id] || INT_CATEGORIES.find(c => c.id === item.cat)?.label}</span>
        <a
          className="int-card-cta"
          href={connectHref(item)}
          target={item.status === 'soon' ? '_self' : '_blank'}
          rel="noopener"
          aria-label={`${connectLabel(item)} ${item.name}`}
        >
          {connectLabel(item)} {Icons.arrow({ width: 12, height: 12 })}
        </a>
      </div>

      <style>{`
        .int-card {
          padding: 22px 20px 18px;
          background: var(--bg-card);
          border: 1px solid var(--border);
          border-radius: 20px;
          display: flex;
          flex-direction: column;
          gap: 14px;
          transition:
            border-color 220ms var(--ease-out),
            background 220ms var(--ease-out),
            transform 220ms var(--ease-out),
            box-shadow 240ms var(--ease-out);
        }
        .int-card:hover {
          background: var(--bg-card-hover);
          border-color: var(--accent-tint-30);
          transform: translateY(-2px);
          box-shadow: 0 18px 36px -28px rgba(58, 49, 32, 0.25);
        }
        .int-card-head {
          display: flex;
          align-items: center;
          justify-content: space-between;
          gap: 12px;
        }
        .int-card-name {
          font-family: var(--font-heading);
          font-size: 19px;
          font-weight: 700;
          letter-spacing: -0.025em;
          color: var(--text);
        }
        .int-card-desc {
          font-size: 13.5px;
          line-height: 1.55;
          color: var(--text-secondary);
          flex: 1;
          text-wrap: pretty;
        }
        .int-card-foot {
          display: flex;
          align-items: center;
          justify-content: space-between;
          padding-top: 14px;
          border-top: 1px solid var(--border);
          gap: 10px;
        }
        .int-card-scope {
          font-family: var(--font-mono);
          font-size: 11px;
          letter-spacing: 0.05em;
          color: var(--text-muted);
        }
        .int-card-cta {
          font-family: var(--font-mono);
          font-size: 11.5px;
          font-weight: 600;
          letter-spacing: 0.05em;
          color: var(--accent);
          display: inline-flex;
          align-items: center;
          gap: 6px;
          white-space: nowrap;
          transition: gap 180ms var(--ease-out);
        }
        .int-card:hover .int-card-cta { gap: 9px; }
      `}</style>
    </article>
  );
}

function Directory({ query }) {
  const [cat, setCat] = useIntState('all');

  const filtered = useIntMemo(() => {
    const q = query.trim().toLowerCase();
    return INTEGRATIONS.filter((i) => {
      if (cat !== 'all' && i.cat !== cat) return false;
      if (q && !(i.name.toLowerCase().includes(q) || i.desc.toLowerCase().includes(q))) return false;
      return true;
    });
  }, [query, cat]);

  const counts = useIntMemo(() => {
    const out = { all: INTEGRATIONS.length };
    INT_CATEGORIES.forEach((c) => {
      if (c.id !== 'all') out[c.id] = INTEGRATIONS.filter((i) => i.cat === c.id).length;
    });
    return out;
  }, []);

  return (
    <section className="directory" id="integrations-directory">
      <div className="container">
        <header className="dir-head" data-reveal>
          <div>
            <div className="eyebrow">
              <span className="eyebrow-rule" />
              Directory · A–Z
            </div>
            <h2>Every integration, one place.</h2>
          </div>
          <div className="dir-count">
            <span className="dir-count-n">{filtered.length}</span>
            <span className="dir-count-l">{filtered.length === 1 ? 'showing' : 'showing'}</span>
          </div>
        </header>

        <div className="dir-chips" role="tablist">
          {INT_CATEGORIES.map((c) => (
            <button
              key={c.id}
              role="tab"
              aria-selected={cat === c.id}
              className={`dir-chip ${cat === c.id ? 'on' : ''}`}
              onClick={() => setCat(c.id)}
            >
              {c.label}
              <span className="dir-chip-count">{counts[c.id]}</span>
            </button>
          ))}
        </div>

        {filtered.length === 0 ? (
          <div className="dir-empty">
            <div className="dir-empty-mark">{Icons.search({ width: 36, height: 36 })}</div>
            <h3>Nothing matches that.</h3>
            <p>Try a different category, or tell us what you need — we&apos;ll ping you in chat when it ships.</p>
            <a className="btn btn-ghost" href="https://calend.ly/emdx" target="_blank" rel="noopener">
              Request an integration {Icons.arrow({ width: 14, height: 14 })}
            </a>
          </div>
        ) : (
          <div className="dir-grid">
            {filtered.map((item, idx) => <IntegrationCard item={item} idx={idx} key={item.id} />)}
          </div>
        )}
      </div>

      <style>{`
        .directory { padding: 24px 0 80px; }

        .dir-head {
          display: flex;
          justify-content: space-between;
          align-items: flex-end;
          margin-bottom: 24px;
          flex-wrap: wrap;
          gap: 18px;
        }
        .dir-head h2 {
          font-size: clamp(1.9rem, 3vw, 2.6rem);
          letter-spacing: -0.035em;
          margin-top: 10px;
        }
        .dir-head .eyebrow {
          display: inline-flex;
          align-items: center;
          gap: 10px;
        }

        .dir-count {
          display: flex;
          align-items: baseline;
          gap: 8px;
          padding: 12px 16px;
          background: var(--bg-card);
          border: 1px solid var(--border);
          border-radius: 999px;
        }
        .dir-count-n {
          font-family: var(--font-heading);
          font-weight: 700;
          font-size: 20px;
          letter-spacing: -0.03em;
          color: var(--accent);
          font-feature-settings: 'tnum';
        }
        .dir-count-l {
          font-family: var(--font-mono);
          font-size: 11px;
          letter-spacing: 0.1em;
          text-transform: uppercase;
          color: var(--text-muted);
        }

        .dir-chips {
          display: flex;
          gap: 6px;
          flex-wrap: wrap;
          margin-bottom: 32px;
          padding: 6px;
          background: var(--bg-card);
          border: 1px solid var(--border);
          border-radius: 16px;
        }
        .dir-chip {
          background: transparent;
          border: none;
          padding: 9px 14px;
          border-radius: 999px;
          color: var(--text-secondary);
          font-size: 13.5px;
          font-weight: 500;
          letter-spacing: -0.005em;
          display: inline-flex;
          align-items: center;
          gap: 8px;
          transition: color 180ms var(--ease-out), background 180ms var(--ease-out), box-shadow 220ms var(--ease-out);
        }
        .dir-chip:hover { color: var(--text); background: var(--bg-card-hover); }
        .dir-chip.on {
          background: var(--accent);
          color: var(--on-accent);
          font-weight: 600;
        }
        .dir-chip-count {
          font-family: var(--font-mono);
          font-size: 10.5px;
          padding: 1px 6px;
          background: var(--bg-elev);
          color: var(--text-muted);
          border-radius: 999px;
          letter-spacing: 0.04em;
        }
        .dir-chip.on .dir-chip-count {
          background: rgba(255, 255, 255, 0.18);
          color: var(--on-accent);
        }

        .dir-grid {
          display: grid;
          grid-template-columns: repeat(3, 1fr);
          gap: 14px;
        }
        @media (max-width: 1000px) { .dir-grid { grid-template-columns: repeat(2, 1fr); } }
        @media (max-width: 600px)  { .dir-grid { grid-template-columns: 1fr; } }

        .dir-empty {
          padding: 80px 24px;
          text-align: center;
          background: var(--bg-card);
          border: 1px dashed var(--border-light);
          border-radius: 22px;
          display: flex;
          flex-direction: column;
          align-items: center;
          gap: 14px;
        }
        .dir-empty-mark {
          width: 64px; height: 64px;
          border-radius: 50%;
          background: var(--accent-soft);
          color: var(--accent-light);
          display: flex; align-items: center; justify-content: center;
        }
        .dir-empty h3 {
          font-size: 22px;
          letter-spacing: -0.02em;
        }
        .dir-empty p {
          font-size: 15px;
          color: var(--text-secondary);
          max-width: 42ch;
          text-wrap: pretty;
        }

        /* Shared logo + status badge styling */
        .int-logo {
          border-radius: 12px;
          display: inline-flex;
          align-items: center;
          justify-content: center;
          font-family: var(--font-heading);
          font-weight: 800;
          letter-spacing: -0.04em;
          flex-shrink: 0;
          border: 1px solid var(--border);
          box-shadow: inset 0 1px 0 rgba(255,255,255,0.12), 0 4px 14px rgba(58, 49, 32, 0.10);
        }
        .int-logo-white {
          background: #FFFFFF;
          border: 1px solid var(--border-light);
          box-shadow: 0 4px 14px rgba(58, 49, 32, 0.10);
        }
        .int-logo-img {
          object-fit: contain;
          display: block;
        }

        .int-status {
          display: inline-flex;
          align-items: center;
          gap: 6px;
          padding: 4px 10px;
          font-family: var(--font-mono);
          font-size: 10.5px;
          font-weight: 600;
          letter-spacing: 0.12em;
          text-transform: uppercase;
          border-radius: 999px;
          border: 1px solid var(--border);
          background: var(--bg-elev);
        }
        .int-status::before {
          content: "";
          width: 6px; height: 6px;
          border-radius: 50%;
          background: currentColor;
        }
        .int-status-live {
          color: var(--accent-light);
          border-color: color-mix(in oklch, var(--accent) 35%, transparent);
          background: var(--accent-soft);
        }
        .int-status-live::before {
          animation: oct-pulse-dot 2400ms ease-in-out infinite;
        }
        .int-status-beta {
          color: #B8821C;
          border-color: rgba(184, 130, 28, 0.40);
          background: rgba(184, 130, 28, 0.10);
        }
        .int-status-soon {
          color: var(--text-muted);
        }
      `}</style>
    </section>
  );
}

// ───────────────────────────────────────────────────────────────────────────
// 6. REQUEST CTA — editorial closing op-ed
// ───────────────────────────────────────────────────────────────────────────

function RequestCTA() {
  return (
    <section className="int-request">
      <div className="container">
        <div className="int-request-card" data-reveal>
          <div className="int-request-mark" aria-hidden="true">
            <svg viewBox="0 0 80 80" width="56" height="56" fill="none">
              <circle cx="40" cy="40" r="38" stroke="currentColor" strokeWidth="1" strokeDasharray="3 3" opacity="0.5" />
              <circle cx="40" cy="40" r="28" stroke="currentColor" strokeWidth="1" opacity="0.4" />
              <circle cx="40" cy="40" r="6" fill="currentColor" />
              <line x1="40" y1="2" x2="40" y2="14" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
              <line x1="40" y1="66" x2="40" y2="78" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
              <line x1="2"  y1="40" x2="14" y2="40" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
              <line x1="66" y1="40" x2="78" y2="40" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
            </svg>
          </div>
          <div className="int-request-body">
            <div className="eyebrow">
              <span className="eyebrow-rule" />
              Missing something?
            </div>
            <h2>Tell us what to ship next.</h2>
            <p>
              Our integration roadmap is open. Tell us what you need — we&apos;ll tell you when
              it lands and ping you in chat the day it does. Most-requested integrations move
              to the top of the queue.
            </p>
          </div>
          <div className="int-request-ctas">
            <a className="btn btn-primary" href="https://calend.ly/emdx" target="_blank" rel="noopener">
              {Icons.send({ width: 16, height: 16 })} Request an integration
            </a>
            <a className="btn btn-ghost" href="https://t.me/octodusdev" target="_blank" rel="noopener">
              {Icons.telegram({ width: 16, height: 16 })} Follow the changelog
            </a>
            <div className="int-request-meta">
              <span>Avg. response &lt; 24h · ships in ~2 weeks</span>
            </div>
          </div>
        </div>
      </div>
      <style>{`
        .int-request { padding: 16px 0 100px; }
        .int-request-card {
          position: relative;
          padding: 48px 48px;
          background:
            radial-gradient(ellipse 70% 90% at 100% 0%, var(--accent-soft), transparent 65%),
            linear-gradient(180deg, var(--bg-card) 0%, var(--bg-elev) 100%);
          border: 1px solid var(--border);
          border-radius: 28px;
          display: grid;
          grid-template-columns: 64px minmax(0, 1.4fr) minmax(280px, 1fr);
          gap: 36px;
          align-items: center;
          overflow: hidden;
        }
        @media (max-width: 960px) {
          .int-request-card {
            grid-template-columns: 1fr;
            padding: 32px 28px;
            gap: 24px;
          }
        }
        .int-request-mark {
          color: var(--accent);
          opacity: 0.85;
        }
        @media (max-width: 960px) {
          .int-request-mark { display: none; }
        }
        .int-request-body .eyebrow {
          display: inline-flex;
          align-items: center;
          gap: 10px;
        }
        .int-request-card h2 {
          font-size: clamp(2rem, 3.2vw, 2.8rem);
          letter-spacing: -0.04em;
          line-height: 1;
          margin: 12px 0 14px;
        }
        .int-request-card p {
          font-size: 15.5px;
          line-height: 1.6;
          color: var(--text-secondary);
          max-width: 52ch;
          text-wrap: pretty;
        }
        .int-request-ctas {
          display: flex;
          flex-direction: column;
          gap: 10px;
        }
        .int-request-ctas .btn { justify-content: center; height: 52px; }
        .int-request-meta {
          margin-top: 6px;
          font-family: var(--font-mono);
          font-size: 11px;
          letter-spacing: 0.06em;
          color: var(--text-muted);
          text-align: center;
        }
      `}</style>
    </section>
  );
}

// ───────────────────────────────────────────────────────────────────────────
// PAGE
// ───────────────────────────────────────────────────────────────────────────

function IntegrationsPage() {
  const [query, setQuery] = useIntState('');

  const liveCount = INTEGRATIONS.filter(i => i.status === 'live').length;
  const betaCount = INTEGRATIONS.filter(i => i.status === 'beta').length;
  const soonCount = INTEGRATIONS.filter(i => i.status === 'soon').length;

  return (
    <>
      <SiteEffects />
      <SiteNav active="integrations" />
      <IntegrationsHero
        query={query}
        setQuery={setQuery}
        total={INTEGRATIONS.length}
        liveCount={liveCount}
        betaCount={betaCount}
        soonCount={soonCount}
      />
      <LogoMarquee />
      <FeaturedAtlas />
      <ConnectionFlow />
      <Directory query={query} />
      <RequestCTA />
      <FinalCTA
        heading={<>One bot.<br/><em>Every tool.</em></>}
        sub="Connect Octodus once. It works across your whole stack from the same Telegram thread."
        ctaLabel="Connect octodus"
      />
      <SiteFooter />
      <SiteTweaks />
    </>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<IntegrationsPage />);
