import {
  borders,
  colors,
  layout,
  theme,
  textGradient,
  fontSizes,
  space,
  radii,
  breakpoints,
  shadows
} from 'theme'
import { withTitle } from 'helpers/hoc/with-title'
import CaptionBase from 'components/patterns/Caption/Caption'
import Layout from 'components/patterns/Layout'
import Faq from 'components/patterns/Faq/Faq'
import ArrowLink from 'components/patterns/ArrowLink'
import RaceContainer from 'components/patterns/RaceContainer/RaceContainer'
import SpeedSectionBase from 'components/patterns/SpeedSection'
import BluePrintBackground from 'components/patterns/BluePrintBackground/BluePrintBackground'
import { trackEvent } from 'helpers/plausible'
import styled, { css } from 'styled-components'
import React from 'react'

import Box from 'components/elements/Box'
import Caps from 'components/elements/Caps'
import Container from 'components/elements/Container'
import Flex from 'components/elements/Flex'
import HeadingBase from 'components/elements/Heading'
import { Link } from 'components/elements/Link'
import Meta from 'components/elements/Meta/Meta'
import SubheadBase from 'components/elements/Subhead'
import Text from 'components/elements/Text'
import { CDN_EDGES } from 'helpers/cdn-edges'
import MultiCodeEditorInteractive from 'components/patterns/MultiCodeEditor/MultiCodeEditorInteractive'
import { useBreakpoint } from 'components/hook/use-breakpoint'

const RaceHero = styled(Box)`
  width: 100%;
  max-width: 960px;

  ${theme({
    borderRadius: 4,
    bg: 'white',
    p: [3, 3, 4, 4],
    boxShadow: `${shadows[4]}`
  })}

  & > div {
    min-height: 220px;

    @media (max-width: ${breakpoints[0]}) {
      min-height: 190px;
    }
  }
`

const Heading = withTitle(HeadingBase)
const Subhead = withTitle(SubheadBase)
const Caption = withTitle(CaptionBase)

const BREAKPOINT_SMALL_MAX = breakpoints[0]
const SPACE_10 = `calc(${space[2]} + ${radii[1]})`
const SPACE_14 = `calc(${space[3]} - ${radii[1]})`

const CTA_LINK_FONT_SIZE = [
  `calc(${fontSizes[2]} + ${space[1]})`,
  fontSizes[3],
  `calc(${fontSizes[3]} + ${radii[1]})`,
  `calc(${fontSizes[3]} + ${space[1]})`
]

const BENCHMARK_DATA = {
  timestamp: '2026-03',
  testUrls: [
    {
      url: 'https://vercel.com',
      width: 1920,
      fullPage: true,
      format: 'jpeg'
    },
    {
      url: 'https://example.com',
      width: 1280,
      height: 800,
      fullPage: false,
      format: 'png'
    },
    {
      url: 'https://stripe.com',
      width: 393,
      height: 852,
      fullPage: false,
      format: 'jpeg'
    },
    {
      url: 'https://screenshotone.com',
      width: 1920,
      fullPage: true,
      format: 'png'
    },
    {
      url: 'https://news.ycombinator.com',
      width: 1440,
      fullPage: true,
      format: 'jpeg'
    },
    {
      url: 'https://github.com/trending',
      width: 768,
      height: 1024,
      fullPage: false,
      format: 'png'
    },
    {
      url: 'https://www.framer.com',
      width: 1920,
      height: 1800,
      fullPage: false,
      format: 'jpeg'
    }
  ],
  results: {
    microlink: {
      name: 'Microlink',
      summary: {
        avgColdDuration: 4111.84,
        totalColdDuration: 28782.87
      },
      perUrl: [
        { url: 'https://vercel.com', coldDuration: 6361.22 },
        { url: 'https://example.com', coldDuration: 967.96 },
        { url: 'https://stripe.com', coldDuration: 3217.22 },
        { url: 'https://screenshotone.com', coldDuration: 5474.39 },
        { url: 'https://news.ycombinator.com', coldDuration: 3435.08 },
        { url: 'https://github.com/trending', coldDuration: 3059.69 },
        { url: 'https://www.framer.com', coldDuration: 6267.31 }
      ]
    },
    screenshotmachine: {
      name: 'ScreenshotMachine',
      summary: {
        avgColdDuration: 6099.77,
        totalColdDuration: 42698.4
      },
      perUrl: [
        { url: 'https://vercel.com', coldDuration: 9790.6 },
        { url: 'https://example.com', coldDuration: 1321.19 },
        { url: 'https://stripe.com', coldDuration: 3167.16 },
        { url: 'https://screenshotone.com', coldDuration: 12403.69 },
        { url: 'https://news.ycombinator.com', coldDuration: 4328.76 },
        { url: 'https://github.com/trending', coldDuration: 3898.21 },
        { url: 'https://www.framer.com', coldDuration: 7788.79 }
      ]
    }
  }
}

const SERVICE_COLORS = {
  microlink: colors.red6,
  screenshotmachine: colors.blue6
}

/* ---------------------------------------------------------------------------
 * Styled primitives
 * --------------------------------------------------------------------------- */

const Section = styled(Box)`
  ${theme({
    py: [5, 5, 6, 6],
    px: [3, 3, 4, 4]
  })}
`

const SectionInner = styled(Container)`
  ${theme({
    maxWidth: [layout.normal, layout.normal, layout.large, layout.large],
    alignItems: 'center',
    pt: 0
  })}
`

const Badge = styled(Caps)`
  display: inline-flex;
  align-items: center;
  ${theme({
    fontSize: '11px',
    fontWeight: 'bold',
    px: '10px',
    py: '4px',
    borderRadius: '20px',
    letterSpacing: '0.08em'
  })}
`

const GradientText = styled('span')`
  ${css`
    ${textGradient}
  `}
`

/* ---------------------------------------------------------------------------
 * Comparison Table (benchmark-style)
 * --------------------------------------------------------------------------- */

const FeatureTable = styled('table')`
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-variant-numeric: tabular-nums;
  table-layout: auto;

  th,
  td {
    padding: ${SPACE_10} ${SPACE_14};
    ${theme({ textAlign: 'left', fontSize: 0, fontFamily: 'mono' })};
    border-bottom: ${borders[1]} ${colors.black05};

    @media (max-width: ${BREAKPOINT_SMALL_MAX}) {
      padding: ${space[2]} ${SPACE_10};
      white-space: normal;
      word-break: break-word;
    }
  }

  th {
    font-weight: 600;
    text-transform: uppercase;
    ${theme({ color: 'black', fontSize: 0 })};
    border-bottom: ${borders[1]} ${colors.black10};
  }

  td {
    ${theme({ color: 'black' })};
  }

  tbody tr:last-child td {
    border-bottom: 0;
  }

  tbody tr:hover {
    ${theme({ bg: 'black05' })};
  }
`

const Check = () => (
  <span
    css={theme({
      color: 'green7',
      fontFamily: 'mono',
      fontSize: 1,
      display: 'block',
      textAlign: 'center'
    })}
    aria-label='Yes'
    role='img'
  >
    ✓
  </span>
)

const Cross = () => (
  <span
    css={theme({
      color: 'red5',
      fontFamily: 'mono',
      fontSize: 1,
      display: 'block',
      textAlign: 'center',
      opacity: 0.7
    })}
    aria-label='No'
    role='img'
  >
    ✕
  </span>
)

const Partial = ({ children }) => (
  <span
    css={theme({
      color: 'yellow7',
      fontFamily: 'mono',
      fontSize: 0,
      display: 'block',
      textAlign: 'center'
    })}
  >
    {children || '~'}
  </span>
)

const COMPARISON_DATA = [
  { feature: 'Screenshot capture', microlink: true, screenshotmachine: true },
  {
    feature: 'Full-page screenshots',
    microlink: true,
    screenshotmachine: true
  },
  {
    feature: 'PDF generation',
    microlink: true,
    screenshotmachine: true
  },
  {
    feature: 'Device emulation (desktop/tablet/phone)',
    microlink: true,
    screenshotmachine: true
  },
  {
    feature: 'Custom delay before capture',
    microlink: true,
    screenshotmachine: true
  },
  {
    feature: 'Hide elements (CSS selectors)',
    microlink: true,
    screenshotmachine: true
  },
  {
    feature: 'Click interactions',
    microlink: true,
    screenshotmachine: true
  },
  { feature: 'Zoom control', microlink: true, screenshotmachine: true },
  { feature: 'PNG / JPEG output', microlink: true, screenshotmachine: true },
  {
    feature: 'Built-in response cache',
    microlink: true,
    screenshotmachine: true,
    note: 'ScreenshotMachine caches for up to 14\u00a0days.'
  },
  {
    feature: 'Signed request URLs (hash security)',
    microlink: true,
    screenshotmachine: true
  },
  {
    feature: 'Custom CSS injection',
    microlink: true,
    screenshotmachine: false,
    highlight: true
  },
  {
    feature: 'Custom JS injection',
    microlink: true,
    screenshotmachine: false,
    highlight: true
  },
  {
    feature: 'Custom HTTP headers',
    microlink: true,
    screenshotmachine: 'partial',
    highlight: true,
    note: 'Supports request language and user-agent, not arbitrary headers.'
  },
  {
    feature: 'Custom cookies',
    microlink: true,
    screenshotmachine: true
  },
  {
    feature: 'Wait for CSS selector',
    microlink: true,
    screenshotmachine: false,
    highlight: true
  },
  {
    feature: 'Element-level capture (CSS selector)',
    microlink: true,
    screenshotmachine: true
  },
  {
    feature: 'HTML rendering (raw HTML input)',
    microlink: true,
    screenshotmachine: false,
    highlight: true
  },
  {
    feature: 'Dark/light mode capture',
    microlink: true,
    screenshotmachine: false,
    highlight: true
  },
  {
    feature: 'Custom proxy support',
    microlink: true,
    screenshotmachine: false,
    highlight: true
  },
  {
    feature: 'Built-in proxy (auto-rotating residential)',
    microlink: true,
    screenshotmachine: false,
    highlight: true
  },
  {
    feature: 'Antibot detection (30+ providers)',
    microlink: true,
    screenshotmachine: false,
    highlight: true
  },
  {
    feature: 'Metadata extraction',
    microlink: true,
    screenshotmachine: false,
    highlight: true
  },
  {
    feature: 'Link previews SDK (React/Vue/JS)',
    microlink: true,
    screenshotmachine: false,
    highlight: true
  },
  {
    feature: 'Browser chrome overlay',
    microlink: true,
    screenshotmachine: false,
    highlight: true
  },
  {
    feature: 'Direct embed (no backend)',
    microlink: true,
    screenshotmachine: false,
    highlight: true
  },
  {
    feature: 'Open-source core',
    microlink: true,
    screenshotmachine: false,
    highlight: true
  },
  {
    feature: 'Remote JS execution (return values)',
    microlink: true,
    screenshotmachine: false,
    highlight: true
  },
  {
    feature: 'MCP server',
    microlink: true,
    screenshotmachine: false,
    highlight: true
  },
  { feature: 'Markdown conversion', microlink: true, screenshotmachine: false },
  {
    feature: 'Cookie banner blocking',
    microlink: true,
    screenshotmachine: 'partial',
    highlight: true,
    note: 'Manual via click/hide selectors instead of a built-in blocker.'
  },
  {
    feature: 'Ad blocking',
    microlink: true,
    screenshotmachine: false,
    highlight: true
  },
  {
    feature: 'GIF output (from API)',
    microlink: false,
    screenshotmachine: true,
    note: 'ScreenshotMachine supports GIF as a direct output format.'
  },
  {
    feature: 'Region cropping (x, y, w, h)',
    microlink: false,
    screenshotmachine: true
  }
]

const CellValue = ({ value }) => {
  if (value === true) return <Check />
  if (value === false) return <Cross />
  if (value === 'partial' || value === 'on demand') {
    const capitalized = value.charAt(0).toUpperCase() + value.slice(1)
    return <Partial>{capitalized}</Partial>
  }
  return <span>{value}</span>
}

const ComparisonTable = () => (
  <Box
    css={theme({
      overflowX: 'auto',
      WebkitOverflowScrolling: 'touch',
      borderRadius: 4,
      border: `${borders[1]} ${colors.black10}`,
      bg: 'white'
    })}
  >
    <FeatureTable>
      <thead>
        <tr>
          <th css={{ minWidth: '220px' }}>Feature</th>
          <th css={[theme({ textAlign: 'center' }), { minWidth: '120px' }]}>
            <span css={textGradient}>Microlink</span>
          </th>
          <th
            css={[
              theme({ textAlign: 'center', color: 'black60' }),
              { minWidth: '120px' }
            ]}
          >
            ScreenshotMachine
          </th>
        </tr>
      </thead>
      <tbody>
        {COMPARISON_DATA.map(
          ({ feature, microlink, screenshotmachine, highlight, note }) => (
            <tr
              key={feature}
              css={{
                background: highlight
                  ? 'rgba(6, 125, 247, 0.03)'
                  : 'transparent'
              }}
            >
              <td css={theme({ fontWeight: 'regular' })}>
                {feature}
                {note && (
                  <Text
                    css={theme({
                      fontSize: '11px',
                      color: 'black40',
                      pt: 1,
                      lineHeight: 1
                    })}
                    as='div'
                  >
                    {note}
                  </Text>
                )}
              </td>
              <td css={theme({ textAlign: 'center' })}>
                <CellValue value={microlink} />
              </td>
              <td css={theme({ textAlign: 'center' })}>
                <CellValue value={screenshotmachine} />
              </td>
            </tr>
          )
        )}
      </tbody>
    </FeatureTable>
  </Box>
)

/* ---------------------------------------------------------------------------
 * Pricing Comparison
 * --------------------------------------------------------------------------- */

const PriceCard = styled(Flex)`
  ${theme({
    flexDirection: 'column',
    p: [3, 4, 4, 4],
    borderRadius: 3,
    border: 1,
    borderColor: 'black10',
    flex: 1,
    minWidth: '260px'
  })}
`

const PriceAmount = styled(Text)`
  ${theme({
    fontSize: [4, 5, 5, 5],
    fontWeight: 'bold',
    lineHeight: 0
  })}
  font-variant-numeric: tabular-nums;
`

const FAQ_ITEMS = [
  {
    question: 'Is there a free Screenshot Machine alternative?',
    answer: (
      <>
        <div>
          Yes. Microlink's <Link href='/pricing'>free tier</Link> gives you
          25&nbsp;requests/day with no credit card and no time limit. Same API,
          same quality, same {CDN_EDGES} edge network as paid plans.
        </div>
        <div>
          Screenshot Machine also offers a free tier with 100&nbsp;fresh
          screenshots per month. Microlink's daily-reset model gives you up to
          750&nbsp;requests/month on free, which is 7.5&times; more volume and
          easier to test with real traffic patterns.
        </div>
      </>
    ),
    text: `Yes. Microlink's free tier gives you 25 requests/day with no credit card and no time limit. Same API, same quality, same ${CDN_EDGES} edge network as paid plans. Screenshot Machine also offers a free tier with 100 fresh screenshots per month. Microlink's daily-reset model gives you up to 750 requests/month on free, which is 7.5\u00d7 more volume.`
  },
  {
    question:
      'How does Microlink compare to Screenshot Machine for screenshot quality?',
    answer: (
      <>
        <div>
          Both services produce screenshots using Chromium. Microlink serves
          maximum quality with optimal compression by default and delivers
          results 33% faster on average. Screenshot Machine also delivers good
          quality and supports JPG, PNG, and GIF output formats.
        </div>
      </>
    ),
    text: 'Both services produce screenshots using Chromium. Microlink serves maximum quality with optimal compression by default and delivers results 33% faster on average. Screenshot Machine also delivers good quality and supports JPG, PNG, and GIF output formats.'
  },
  {
    question: 'Can I migrate from Screenshot Machine to Microlink easily?',
    answer: (
      <>
        <div>
          Yes. Screenshot Machine uses a simple GET API with parameters like{' '}
          <i>url</i>, <i>dimension</i>, <i>device</i>, <i>format</i>,{' '}
          <i>delay</i>, and <i>zoom</i>. Microlink accepts the same capture
          concepts under its own parameter names. Most migrations involve
          updating the API endpoint and key. The{' '}
          <Link href='/docs/guides/screenshot'>screenshot docs</Link> cover
          every parameter with examples.
        </div>
        <div>
          Paste your existing code into any LLM and ask it to migrate to
          Microlink. Or email{' '}
          <Link href='mailto:hello@microlink.io'>hello@microlink.io</Link> and
          we'll help directly.
        </div>
      </>
    ),
    text: "Yes. Screenshot Machine uses a simple GET API with parameters like url, dimension, device, format, delay, and zoom. Microlink accepts the same capture concepts under its own parameter names. Most migrations involve updating the API endpoint and key. The screenshot docs cover every parameter with examples. Paste your existing code into any LLM and ask it to migrate to Microlink. Or email hello@microlink.io and we'll help directly."
  },
  {
    question: 'When is Screenshot Machine enough, and when should you upgrade?',
    answer: (
      <>
        <div>
          Screenshot Machine is a good fit when you want a simpler API focused
          on screenshots and website-to-PDF conversion.
        </div>
        <div>
          Microlink is the upgrade path when those captures need to feed richer
          browser workflows: metadata/Open Graph extraction, link previews (via
          SDK), remote JavaScript execution, and Lighthouse audits from one API
          key and one integration.
        </div>
      </>
    ),
    text: 'Screenshot Machine is a good fit when you want a simpler API focused on screenshots and website-to-PDF conversion. Microlink is the upgrade path when those captures need to feed richer browser workflows: metadata/Open Graph extraction, link previews (via SDK), remote JavaScript execution, and Lighthouse audits from one API key and one integration.'
  },
  {
    question: 'Is Microlink really open source?',
    answer: (
      <>
        <div>
          The core engine components are MIT-licensed on GitHub:{' '}
          <Link href='https://github.com/microlinkhq/metascraper'>
            Metascraper
          </Link>{' '}
          (metadata extraction),{' '}
          <Link href='https://github.com/microlinkhq/mql'>MQL</Link> (Microlink
          Query Language), and{' '}
          <Link href='https://github.com/microlinkhq/browserless'>
            Browserless
          </Link>{' '}
          (headless browser). Enterprise teams can audit, fork, and contribute.
        </div>
        <div>
          Screenshot Machine is closed-source. There is no way to inspect or
          audit the engine processing your requests.
        </div>
      </>
    ),
    text: 'The core engine components are MIT-licensed on GitHub: Metascraper (metadata extraction), MQL (Microlink Query Language), and Browserless (headless browser). Enterprise teams can audit, fork, and contribute. Screenshot Machine is closed-source. There is no way to inspect or audit the engine processing your requests.'
  },
  {
    question: 'How much does Screenshot Machine cost compared to Microlink?',
    answer: (
      <>
        <div>
          Screenshot Machine Pro is listed at €59/month for 20,000&nbsp;fresh
          screenshots with €0.003 per extra screenshot. Microlink's comparison
          tier is &euro;39/month for 46,000&nbsp;requests, which is more than
          2&times; the included monthly volume on the plan we compare here.
        </div>
        <div>
          Enterprise clients running millions of requests fund the
          infrastructure, which is how indie devs get the same global edge
          network at these prices.
        </div>
      </>
    ),
    text: "Screenshot Machine Pro is listed at €59/month for 20,000 fresh screenshots with €0.003 per extra screenshot. Microlink's comparison tier is \u20ac39/month for 46,000 requests, which is more than 2\u00d7 the included monthly volume on the plan we compare here. Enterprise clients running millions of requests fund the infrastructure."
  },
  {
    question: 'Does Microlink have rate limits?',
    answer: (
      <>
        <div>
          Paid plans have no requests-per-minute cap &mdash; burst as high as
          your concurrency allows. The only limit is your monthly request quota.
        </div>
        <div>
          Screenshot Machine does not publish explicit per-minute rate limits,
          but its pricing tiers are based on fresh screenshots per month. Cached
          screenshots (up to 14&nbsp;days) are not billed.
        </div>
      </>
    ),
    text: 'Paid plans have no requests-per-minute cap \u2014 burst as high as your concurrency allows. The only limit is your monthly request quota. Screenshot Machine does not publish explicit per-minute rate limits, but its pricing tiers are based on fresh screenshots per month. Cached screenshots (up to 14 days) are not billed.'
  },
  {
    question: 'How does Microlink handle sites with cookie banners or ads?',
    answer: (
      <>
        <div>
          Microlink supports ad blocking via the{' '}
          <Link href='/docs/api/parameters/adblock'>adblock</Link> parameter and
          custom CSS/JS injection to dismiss consent dialogs before the
          screenshot is taken. Screenshot Machine supports cookie-banner
          handling through its <i>click</i> and <i>hide</i> selector parameters,
          but it does not advertise a dedicated ad-blocking or cookie-blocking
          rules engine.
        </div>
      </>
    ),
    text: 'Microlink supports ad blocking via the adblock parameter and custom CSS/JS injection to dismiss consent dialogs. Screenshot Machine supports cookie-banner handling through click and hide selectors, but it does not advertise a dedicated ad-blocking or cookie-blocking rules engine. Use screenshot.hide to remove specific elements by CSS selector.'
  },
  {
    question: 'What uptime and SLA does Microlink guarantee?',
    answer: (
      <>
        <div>
          Microlink guarantees 99.9% uptime backed by a formal SLA. Requests are
          served from {CDN_EDGES} Cloudflare edge nodes worldwide. Screenshot
          Machine advertises 99.99% uptime on its SLA page, which is a strong
          availability commitment.
        </div>
      </>
    ),
    text: `Microlink guarantees 99.9% uptime backed by a formal SLA. Requests are served from ${CDN_EDGES} Cloudflare edge nodes worldwide. Screenshot Machine advertises 99.99% uptime on its SLA page, which is a strong availability commitment.`
  }
]

/* ---------------------------------------------------------------------------
 * Hero Section
 * --------------------------------------------------------------------------- */

const Hero = () => (
  <BluePrintBackground as='section'>
    <Flex
      css={theme({
        flexDirection: 'column',
        alignItems: 'center',
        pt: 3,
        pb: [4, 4, 5, 5],
        px: 4
      })}
    >
      <Heading
        variant={null}
        css={theme({
          textAlign: 'center',
          maxWidth: '100%',
          color: 'black'
        })}
      >
        The <GradientText>ScreenshotMachine</GradientText> upgrade path
        <br />
        for richer browser workflows
      </Heading>

      <Caption
        forwardedAs='h2'
        css={theme({
          pt: [3, 3, 4, 4],
          maxWidth: layout.large,
          color: 'black80'
        })}
        titleize={false}
      >
        <b>Screenshot Machine</b> is a reliable, no-frills screenshot and PDF
        API. When your workflow outgrows that simpler surface and you need
        metadata, link previews, remote JS, and more request headroom,{' '}
        <b>Microlink</b> gives you the broader browser API while staying{' '}
        <b>33% faster on average</b>.
      </Caption>

      <Flex
        css={theme({
          pt: [3, 3, 4, 4],
          pb: [3, 3, 4, 4],
          fontSize: [2, 2, 3, 3],
          gap: '16px',
          flexWrap: 'wrap',
          justifyContent: 'center'
        })}
      >
        <ArrowLink
          href='/screenshot'
          onClick={() =>
            trackEvent('alternative cta', { competitor: 'screenshotmachine' })}
        >
          Get Started Free
        </ArrowLink>
      </Flex>

      <Flex
        css={theme({
          width: '100%',
          justifyContent: 'center',
          my: [3, 3, 4, 4],
          pb: [3, 3, 4, 4]
        })}
      >
        <RaceHero aria-label='Live benchmark race: Microlink vs Screenshot Machine screenshot speed'>
          <RaceContainer
            benchmarkData={BENCHMARK_DATA}
            serviceColors={SERVICE_COLORS}
            highlightKey='microlink'
            flat
            compact
          />
        </RaceHero>
      </Flex>
    </Flex>
  </BluePrintBackground>
)

/* ---------------------------------------------------------------------------
 * Comparison Table Section
 * --------------------------------------------------------------------------- */

const ComparisonSection = () => (
  <Section
    as='section'
    id='comparison'
    css={theme({
      borderTop: `${borders[1]} ${colors.black05}`,
      borderBottom: `${borders[1]} ${colors.black05}`,
      py: 5
    })}
  >
    <SectionInner>
      <Subhead css={theme({ pb: [2, 2, 3, 3], pt: 4 })} titleize={false}>
        <GradientText>Feature-by-Feature</GradientText> Comparison
      </Subhead>
      <Caption
        css={theme({
          pt: 2,
          pb: [3, 3, 4, 4],
          maxWidth: layout.normal,
          color: 'black60'
        })}
        titleize={false}
      >
        An honest look at what each API offers.
      </Caption>
      <ComparisonTable />
      <Text
        css={theme({
          pt: 4,
          pb: 4,
          fontSize: '12px',
          color: 'black40',
          textAlign: 'center',
          fontFamily: 'mono'
        })}
      >
        Last verified: April&nbsp;2026. See each product's docs for the latest.
      </Text>
    </SectionInner>
  </Section>
)

/* ---------------------------------------------------------------------------
 * Speed Section (benchmark data tables)
 * --------------------------------------------------------------------------- */

const SpeedSection = () => (
  <SpeedSectionBase
    benchmark={BENCHMARK_DATA}
    title={
      <>
        <GradientText>Up to 2.3&times; faster</GradientText> response times
      </>
    }
    subtitle='Same request. Same URL. Same output format.'
    description={
      <>
        We ran identical screenshot requests against both APIs from a New York
        server and measured cold-start latency &mdash; no cache, no warm-up. The
        numbers below are averages from 10&nbsp;independent benchmark runs at
        different hours. The biggest gap was on screenshotone.com, where
        Screenshot Machine took over 12&nbsp;seconds while Microlink finished in
        5.5&nbsp;seconds.
      </>
    }
    note={
      <>
        See the full benchmark with all 6&nbsp;providers and 7&nbsp;URLs on the{' '}
        <Link href='/benchmarks/screenshot-api'>Screenshot API Benchmark</Link>{' '}
        page.
      </>
    }
    footnote={
      <>
        Averages from 10&nbsp;benchmark runs taken from a New York server at
        different hours. The{' '}
        <Link href='https://github.com/microlinkhq/screenshot-benchmark'>
          benchmark repo
        </Link>{' '}
        is open — run it yourself and see. Last run: March&nbsp;2026.
      </>
    }
  />
)

/* ---------------------------------------------------------------------------
 * Why Developers Switch
 * --------------------------------------------------------------------------- */

const WHY_SWITCH_ITEMS = [
  {
    number: '01',
    title: 'A modern API surface, not just query params',
    description: (
      <>
        Screenshot Machine covers the basics well, including cookies plus
        user-agent and language controls. Microlink goes further with{' '}
        <b>arbitrary headers, JS injection, CSS injection</b>, and broader
        browser automation for SPAs, auth-gated pages, and dynamic content.
      </>
    )
  },
  {
    number: '02',
    title: '2.3× more included monthly volume',
    description: (
      <>
        Screenshot Machine Pro is listed at <b>€59/month</b> for 20,000 fresh
        screenshots. Microlink{'\u2019'}s comparison tier is{' '}
        <b>€39/month for 46,000 requests</b>, which is more than double the
        included monthly volume.
      </>
    )
  },
  {
    number: '03',
    title: 'One API key, not five',
    description: (
      <>
        Microlink handles screenshots, PDFs, metadata extraction, link previews,
        and remote JS in <b>a single integration</b>. Screenshot Machine covers
        screenshots and PDFs only — anything else requires a separate service.
      </>
    )
  },
  {
    number: '04',
    title: '33% faster on cold starts',
    description: (
      <>
        In the March 2026 benchmark, Microlink averaged <b>4,112{'\u2009'}ms</b>{' '}
        and Screenshot Machine averaged <b>6,100{'\u2009'}ms</b> across 7
        real-world URLs. On heavy pages, the gap reached <b>2.3×</b>.
      </>
    )
  },
  {
    number: '05',
    title: 'Proxy and antibot\u00a0built\u2011in, zero\u00a0config',
    description: (
      <>
        Microlink <b>auto-rotates residential proxies</b> and detects{' '}
        <b>30+&nbsp;antibot providers</b> (Cloudflare, DataDome, Akamai
        {'\u2026'}) on every request. Screenshot Machine does not offer proxy
        support or antibot&nbsp;detection.
      </>
    )
  },
  {
    number: '06',
    title: 'Open-source, fully auditable',
    description: (
      <>
        Metascraper, MQL, and Browserless are <b>MIT-licensed</b>. Inspect the
        core engine, fork it, or self-host.{' '}
        <b>No black boxes, no vendor lock-in</b> — Screenshot Machine is
        closed-source with no way to audit what runs against your&nbsp;URLs.
      </>
    )
  }
]

const WhySwitchTimeline = styled(Flex)`
  position: relative;
  ${theme({
    flexDirection: 'column',
    alignItems: 'flex-start'
  })}
`

const WhySwitchItem = styled(Flex)`
  ${theme({
    flexDirection: 'row',
    alignItems: 'stretch',
    gap: 0
  })}
`

const WhySwitchRail = styled('div')`
  ${theme({ flexShrink: 0, position: 'relative', mr: [3, 3, 4, 4] })}
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 32px;

  @media (min-width: ${breakpoints[1]}) {
    width: 40px;
  }
`

const WhySwitchConnector = styled('div')`
  width: 1px;
  flex: 1;
  ${theme({ bg: 'black10', mt: 2, mb: 2 })}
`

const WhySwitchNumber = styled(Text)`
  ${theme({
    fontFamily: 'mono',
    fontSize: [3, 3, 4, 4],
    fontWeight: 'bold',
    lineHeight: 0,
    flexShrink: 0
  })}
  ${css`
    ${textGradient}
  `}
  opacity: 0.90;
`

const WhySwitchSection = () => (
  <Section as='section' id='why-switch' css={theme({ bg: 'pinky' })}>
    <SectionInner>
      <Subhead
        css={theme({ color: 'black', pb: [1, 2, 2, 2] })}
        titleize={false}
      >
        Why <GradientText>Developers</GradientText> Switch
      </Subhead>
      <Caption
        css={theme({
          color: 'black60',
          pb: [4, 4, 5, 5],
          maxWidth: layout.normal
        })}
        titleize={false}
      >
        The top reasons teams move from Screenshot Machine to Microlink.
      </Caption>

      <WhySwitchTimeline
        css={theme({
          width: '100%',
          maxWidth: layout.normal,
          mx: 'auto'
        })}
      >
        {WHY_SWITCH_ITEMS.map(({ number, title, description }, index) => {
          const isLast = index === WHY_SWITCH_ITEMS.length - 1
          return (
            <WhySwitchItem key={number}>
              <WhySwitchRail>
                <WhySwitchNumber aria-hidden='true'>{number}</WhySwitchNumber>
                {!isLast && <WhySwitchConnector />}
              </WhySwitchRail>
              <Box
                css={theme({
                  flex: 1,
                  minWidth: 0,
                  pb: isLast ? 0 : [3, 3, 4, 4]
                })}
              >
                <Text
                  css={theme({
                    fontWeight: 'bold',
                    fontSize: [2, 2, 3, 3],
                    color: 'black',
                    pb: 2,
                    lineHeight: 1
                  })}
                >
                  {title}
                </Text>
                <Text
                  css={theme({
                    fontSize: [1, 1, 2, 2],
                    color: 'black90',
                    lineHeight: 2,
                    maxWidth: '40em'
                  })}
                >
                  {description}
                </Text>
              </Box>
            </WhySwitchItem>
          )
        })}
      </WhySwitchTimeline>
    </SectionInner>
  </Section>
)

/* ---------------------------------------------------------------------------
 * Where Screenshot Machine Might Be Right
 * --------------------------------------------------------------------------- */

const HONESTY_ITEMS = [
  {
    title: 'The simplest possible API',
    description:
      'Screenshot Machine\u2019s API is a single GET endpoint with a handful of parameters. If you only need basic screenshots and PDFs with no advanced browser control, that simplicity is genuinely\u00a0appealing.'
  },
  {
    title: 'Region cropping built in',
    description:
      'Screenshot Machine lets you crop a specific rectangle (x, y, width, height) from the viewport in a single API call. Microlink captures full viewports or CSS-selected elements, but does not have built-in pixel-coordinate\u00a0cropping.'
  },
  {
    title: 'Free cached impressions',
    description:
      'Screenshot Machine caches screenshots for up to 14\u00a0days and serves cached impressions at no cost. If your use case involves hot-linking the same URLs repeatedly, that caching model can save\u00a0money.'
  },
  {
    title: 'GIF output directly from the API',
    description:
      'Screenshot Machine supports GIF as a direct output format alongside JPG and PNG.'
  }
]

const HonestySection = () => (
  <Section
    as='section'
    id='screenshotmachine-strengths'
    css={theme({ bg: 'gray0', px: 5, pt: 5, pb: 5 })}
  >
    <SectionInner>
      <Subhead css={theme({ pb: [4, 4, 5, 5], pt: 3 })} titleize={false}>
        Where <GradientText>Screenshot Machine</GradientText>
        <br /> Might Be the Right Choice
      </Subhead>

      <Box
        css={theme({
          maxWidth: layout.normal,
          width: '100%',
          mx: 'auto'
        })}
      >
        {HONESTY_ITEMS.map(({ title, description }, index) => {
          const isLast = index === HONESTY_ITEMS.length - 1
          return (
            <Flex
              key={title}
              css={theme({
                flexDirection: 'row',
                alignItems: 'baseline',
                py: [3, 3, 3, 3],
                borderBottom: isLast ? 0 : 1,
                borderBottomColor: 'black05'
              })}
            >
              <Text
                css={theme({
                  fontFamily: 'mono',
                  fontSize: 0,
                  color: 'black20',
                  flexShrink: 0,
                  mr: [3, 3, 4, 4],
                  minWidth: '24px'
                })}
                aria-hidden='true'
              >
                {String(index + 1).padStart(2, '0')}
              </Text>
              <Box css={theme({ flex: 1, minWidth: 0 })}>
                <Text
                  css={theme({
                    fontWeight: 'bold',
                    fontSize: [1, 1, 2, 2],
                    color: 'black',
                    pb: 1
                  })}
                >
                  {title}
                </Text>
                <Text
                  css={theme({
                    fontSize: [0, 0, 1, 1],
                    color: 'black50',
                    lineHeight: 2,
                    maxWidth: '40em'
                  })}
                >
                  {description}
                </Text>
              </Box>
            </Flex>
          )
        })}
      </Box>
    </SectionInner>
  </Section>
)

/* ---------------------------------------------------------------------------
 * Pricing Section
 * --------------------------------------------------------------------------- */

/* Pricing sources:
 * Screenshot Machine pricing: https://www.screenshotmachine.com/pricing.php
 * Microlink comparison tier: .cursor/skills/alternative-landing/references/microlink-features.md
 */
const PricingSection = () => (
  <Section as='section' id='pricing' css={theme({ py: 5 })}>
    <SectionInner>
      <Subhead css={theme({ pb: [2, 2, 3, 3], pt: 3 })} titleize={false}>
        More requests. <GradientText>Less glue code.</GradientText>
      </Subhead>
      <Caption
        css={theme({
          pb: [4, 4, 5, 5],
          maxWidth: layout.large,
          color: 'black60'
        })}
        titleize={false}
      >
        Compare Microlink's <b>46,000&nbsp;requests</b> at &euro;39/month with
        Screenshot Machine Pro's <b>20,000&nbsp;fresh screenshots</b> at
        €59/month.
      </Caption>

      <Flex
        css={theme({
          gap: [3, 3, 4, 4],
          flexDirection: ['column', 'column', 'row', 'row'],
          width: '100%',
          maxWidth: layout.normal,
          mx: 'auto'
        })}
      >
        <Box
          css={theme({
            borderRadius: 3,
            flex: 1,
            minWidth: ['100%', '400px']
          })}
          style={{
            background:
              'linear-gradient(90deg, rgb(247, 102, 152), rgb(192, 63, 162) 60%, rgb(140, 27, 171) 100%)',
            padding: '2px'
          }}
        >
          <PriceCard
            style={{
              border: 'none',
              borderRadius: '6px',
              flex: 1,
              minWidth: 0,
              background: 'white'
            }}
          >
            <Badge
              css={{
                background: colors.blue0,
                color: colors.blue8,
                alignSelf: 'flex-start',
                marginBottom: '12px'
              }}
            >
              Microlink
            </Badge>
            <PriceAmount>
              &euro;39
              <Text
                as='span'
                css={theme({
                  fontSize: 1,
                  color: 'black50',
                  fontWeight: 'normal'
                })}
              >
                /mo
              </Text>
            </PriceAmount>
            <Text
              css={theme({
                fontSize: 2,
                color: 'black80',
                pt: 2,
                pb: 3,
                fontWeight: 'bold'
              })}
            >
              46,000&nbsp;requests/month
            </Text>
            <Box as='ul' css={theme({ pl: 3, m: 0 })}>
              {[
                'Screenshots, PDF, metadata, link previews, remote\u00a0JS',
                'Free: 25\u00a0requests/day, no credit card, no expiry',
                'No per-minute cap on paid plans',
                `${CDN_EDGES} edge nodes, 99.9%\u00a0SLA`,
                'Open-source core (MIT licensed)',
                '~€0.00085/request on this tier'
              ].map(item => (
                <Text
                  as='li'
                  key={item}
                  css={theme({
                    fontSize: 1,
                    color: 'black70',
                    pb: 2,
                    lineHeight: 2
                  })}
                >
                  {item}
                </Text>
              ))}
            </Box>
            <Box css={theme({ pt: 3 })}>
              <Link
                href='/screenshot'
                css={theme({ fontSize: 1, width: '100%', textAlign: 'center' })}
              >
                <Caps>Start for free</Caps>
              </Link>
            </Box>
          </PriceCard>
        </Box>

        <PriceCard>
          <Badge
            css={{
              background: colors.gray1,
              color: colors.gray7,
              alignSelf: 'flex-start',
              marginBottom: '12px'
            }}
          >
            Screenshot Machine
          </Badge>
          <PriceAmount>
            &euro;59
            <Text
              as='span'
              css={theme({
                fontSize: 1,
                color: 'black50',
                fontWeight: 'normal'
              })}
            >
              /mo
            </Text>
          </PriceAmount>
          <Text
            css={theme({
              fontSize: 2,
              color: 'black80',
              pt: 2,
              pb: 3,
              fontWeight: 'bold'
            })}
          >
            20,000&nbsp;screenshots/month
          </Text>
          <Box as='ul' css={theme({ pl: 3, m: 0 })}>
            {[
              'Screenshots and PDF only \u2014 no metadata, previews, or remote\u00a0JS',
              '€0.003 per additional screenshot',
              'Unlimited impressions from cache (14\u00a0days)',
              'Cookies plus language / user-agent controls',
              'No custom JS or CSS injection',
              '99.99% uptime SLA'
            ].map(item => (
              <Text
                as='li'
                key={item}
                css={theme({
                  fontSize: 1,
                  color: 'black70',
                  pb: 2,
                  lineHeight: 2
                })}
              >
                {item}
              </Text>
            ))}
          </Box>
        </PriceCard>
      </Flex>

      <Text
        css={theme({
          pt: 4,
          mb: 4,
          fontSize: 1,
          color: 'black60',
          textAlign: 'center',
          maxWidth: layout.small,
          mx: 'auto',
          lineHeight: 2
        })}
      >
        We can keep prices this low because our{' '}
        <Link href='/enterprise'>enterprise clients</Link> cover the
        infrastructure cost. We want to help indie devs and startups{' '}
        <b>squeeze every drop of value</b> out of their budget.
      </Text>
    </SectionInner>
  </Section>
)

/* ---------------------------------------------------------------------------
 * CTA Section
 * --------------------------------------------------------------------------- */

const CTASection = () => (
  <Section
    as='section'
    id='get-started'
    css={theme({
      backgroundImage: `radial-gradient(
        circle at center right,
        #850ba7 0%,
        #850ba7 48%,
        #a31b91 48%,
        #a31b91 52%,
        #c12a78 52%,
        #c12a78 65%,
        #df3a61 65%,
        #df3a61 79%,
        #fd494a 79%,
        #fd494a 100%
      )`,
      borderTop: `${borders[1]} ${colors.white20}`,
      borderBottom: `${borders[1]} ${colors.white20}`,
      py: [4, 4, 5, 5]
    })}
  >
    <Flex
      css={theme({
        flexDirection: 'column',
        alignItems: 'center',
        maxWidth: layout.large,
        mx: 'auto',
        textAlign: 'center'
      })}
    >
      <Subhead
        css={theme({
          color: 'white',
          pb: [2, 2, 3, 3]
        })}
        titleize={false}
      >
        Upgrade without rebuilding everything
      </Subhead>

      <Caption
        css={theme({
          color: 'white80',
          pb: [3, 3, 4, 4],
          maxWidth: layout.large
        })}
        titleize={false}
      >
        Keep the screenshot and PDF workflow you already know.
      </Caption>

      <Caption
        css={theme({
          color: 'white80',
          pb: [3, 3, 4, 4],
          maxWidth: layout.large
        })}
      >
        Your first{' '}
        <b css={theme({ color: 'white' })}>25&nbsp;requests/day are free</b> —
        no credit card, no commitment.
      </Caption>

      <Flex
        css={theme({
          gap: 3,
          flexWrap: 'wrap',
          justifyContent: 'center'
        })}
      >
        <ArrowLink
          href='/screenshot'
          onClick={() =>
            trackEvent('alternative cta', { competitor: 'screenshotmachine' })}
          css={theme({ fontSize: 3, px: 5, py: 3, color: 'white' })}
        >
          Start Building Free
        </ArrowLink>
      </Flex>
    </Flex>
  </Section>
)

/* ---------------------------------------------------------------------------
 * Try It Section (code editor + call-to-action)
 * --------------------------------------------------------------------------- */

const TryItSection = () => {
  const breakpoint = useBreakpoint()
  return (
    <Section as='section' css={theme({ py: [5, 5, 6, 6] })}>
      <SectionInner>
        <Subhead
          css={theme({
            textAlign: 'center'
          })}
        >
          Ship <span css='color: #fa5252;'>faster</span> screenshots
        </Subhead>
        <Caption
          forwardedAs='div'
          css={theme({
            pt: [3, 3, 4, 4],
            maxWidth: [
              layout.small,
              layout.small,
              layout.normal,
              layout.normal
            ],
            textAlign: 'center'
          })}
        >
          25&nbsp;requests/day free — no account, no credit card. Start
          capturing screenshots at the speed your users&nbsp;deserve.
        </Caption>
        <Flex
          css={[
            theme({
              pt: [4, 4, 5, 5],
              width: '100%',
              px: [2, 3, 0, 0]
            }),
            {
              '& > div, & > div > div:first-child': {
                width: '100%'
              }
            }
          ]}
        >
          <MultiCodeEditorInteractive
            height={breakpoint === 0 ? 250 : 180}
            mqlCode={{
              url: 'https://www.apple.com',
              screenshot: true
            }}
          />
        </Flex>
        <Flex
          css={theme({
            pt: [3, 3, 4, 4],
            gap: [3, 3, 4, 4],
            flexDirection: ['column', 'column', 'row', 'row'],
            alignItems: 'center'
          })}
        >
          <Link
            href='/docs/guides/screenshot'
            onClick={() =>
              trackEvent('alternative cta', { competitor: 'screenshotmachine' })}
            css={theme({ fontSize: CTA_LINK_FONT_SIZE })}
          >
            Start now for free
          </Link>
        </Flex>
      </SectionInner>
    </Section>
  )
}

/* ---------------------------------------------------------------------------
 * FAQ Section
 * --------------------------------------------------------------------------- */

const FAQSection = () => (
  <Faq
    css={theme({ py: 0 })}
    questions={FAQ_ITEMS.map(({ question, answer }) => ({ question, answer }))}
  />
)

/* ---------------------------------------------------------------------------
 * Head / SEO
 * --------------------------------------------------------------------------- */

export const Head = () => (
  <Meta
    title='Screenshot Machine Alternative for Broader Browser Workflows'
    description='Screenshot Machine is great for simple screenshots and PDFs. Microlink benchmarks 33% faster on average and adds metadata, link previews, remote JS, and 46,000 requests on its €39 tier.'
    schemaType='WebPage'
    structured={[
      {
        '@context': 'https://schema.org',
        '@type': 'WebPage',
        name: 'Screenshot Machine Alternative for Broader Browser Workflows | Microlink',
        description:
          'Compare Microlink and Screenshot Machine when your screenshot workflow grows beyond basic captures and PDFs. Microlink is 33% faster on average and adds metadata extraction, link previews, and remote JS in one API.',
        url: 'https://microlink.io/alternative/screenshotmachine',
        mainEntity: {
          '@type': 'SoftwareApplication',
          name: 'Microlink',
          applicationCategory: ['DeveloperApplication', 'WebApplication'],
          url: 'https://microlink.io',
          offers: {
            '@type': 'Offer',
            price: '0',
            priceCurrency: 'EUR'
          }
        }
      },
      {
        '@context': 'https://schema.org',
        '@type': 'FAQPage',
        mainEntity: FAQ_ITEMS.map(({ question, text }) => ({
          '@type': 'Question',
          name: question,
          acceptedAnswer: {
            '@type': 'Answer',
            text
          }
        }))
      }
    ]}
  />
)

/* ---------------------------------------------------------------------------
 * Page
 * --------------------------------------------------------------------------- */

const ScreenshotMachinePage = () => (
  <Layout>
    <Hero />
    <SpeedSection />
    <WhySwitchSection />
    <PricingSection />
    <CTASection />
    <ComparisonSection />
    <HonestySection />
    <TryItSection />
    <FAQSection />
  </Layout>
)

export default ScreenshotMachinePage
