// src/pdf-exports/prominence.ts
function tierToProminence(tier) {
  if (tier === "patron") return "refined";
  if (tier === "supporter") return "refined";
  return "maximum";
}
function resolveProminence(brand, tier) {
  if (brand.prominenceMap) return brand.prominenceMap(tier);
  return tierToProminence(tier);
}

// src/pdf-exports/qr.ts
async function generateQrDataUrl(url, options) {
  try {
    const qr = await import("qrcode");
    const toDataURL = qr.default?.toDataURL ?? qr.toDataURL;
    return await toDataURL(url, {
      width: options?.size ?? 320,
      margin: options?.margin ?? 1,
      errorCorrectionLevel: options?.errorCorrectionLevel ?? "M",
      color: {
        dark: options?.darkColor ?? "#0c1f22",
        light: options?.lightColor ?? "#ffffff"
      }
    });
  } catch {
    return null;
  }
}

// src/pdf-exports/url-utils.ts
function buildExportUrl({
  brand,
  tool,
  medium,
  shareSlug,
  path,
  params
}) {
  const resolvedPath = path ? path : shareSlug ? `/s/${shareSlug}` : `/tools/${tool}`;
  const base = `https://${brand.domain}${resolvedPath}`;
  const search = new URLSearchParams({
    utm_source: "export",
    utm_medium: medium,
    utm_tool: tool,
    ...params
  });
  return `${base}?${search.toString()}`;
}
function buildExportFilename({
  brand,
  tool,
  titleOrDate,
  ext
}) {
  const brandSlug = slugify(brand.name);
  const titleSlug = slugify(titleOrDate);
  const middle = titleSlug ? `${tool}-${titleSlug}` : tool;
  return `${brandSlug}-${middle}.${ext}`;
}
function slugify(input) {
  if (!input) return "";
  return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
}

// src/pdf-exports/pdf-chrome.tsx
import { Image, Page, StyleSheet, Text, View } from "@react-pdf/renderer";
import { jsx, jsxs } from "react/jsx-runtime";
var FOOTER_SAFE_AREA_PT = 72;
function makeChromeStyles(brand) {
  return StyleSheet.create({
    headerRow: {
      flexDirection: "row",
      alignItems: "center",
      justifyContent: "space-between",
      borderBottomWidth: 3,
      borderBottomColor: brand.colors.primary,
      paddingBottom: 10,
      marginBottom: 12,
      gap: 16
    },
    headerLeft: { flexDirection: "column", flexGrow: 1, flexShrink: 1 },
    eyebrow: {
      fontSize: 9,
      letterSpacing: 1.5,
      color: brand.colors.muted,
      textTransform: "uppercase",
      fontFamily: "Helvetica-Bold",
      marginBottom: 2
    },
    title: {
      fontSize: 22,
      fontFamily: "Helvetica-Bold",
      color: brand.colors.ink,
      lineHeight: 1.15
    },
    subtitle: {
      fontSize: 10,
      color: brand.colors.muted,
      marginTop: 3
    },
    lockupRow: {
      flexDirection: "row",
      alignItems: "center",
      gap: 8
    },
    wordmark: {
      fontSize: 13,
      fontFamily: "Helvetica-Bold",
      color: brand.colors.secondary,
      letterSpacing: -0.2
    },
    footerRow: {
      flexDirection: "row",
      alignItems: "center",
      justifyContent: "space-between",
      borderTopWidth: 2,
      borderTopColor: brand.colors.primary,
      paddingTop: 8,
      marginTop: 10,
      gap: 16
    },
    footerLeft: { flexDirection: "row", alignItems: "center", gap: 8 },
    footerMid: {
      flexDirection: "column",
      alignItems: "flex-end",
      flexShrink: 1
    },
    footerUrl: {
      fontSize: 9,
      fontFamily: "Helvetica-Bold",
      color: brand.colors.secondary
    },
    footerDate: {
      fontSize: 8,
      color: brand.colors.muted,
      marginTop: 2
    },
    footerTagline: {
      fontSize: 8,
      color: brand.colors.muted
    },
    footerName: {
      fontSize: 11,
      fontFamily: "Helvetica-Bold",
      color: brand.colors.secondary
    },
    qr: {
      width: 44,
      height: 44
    },
    qrRefined: {
      width: 32,
      height: 32
    },
    // `flex: 1` makes the body fill the page's available flow area between the
    // header and the footer's flow anchor. `marginBottom: FOOTER_SAFE_AREA_PT`
    // carves an explicit safe-zone INSIDE that flow area so overflow children
    // (e.g., a flex column with `justifyContent: "space-around"` and content
    // exceeding the container height) cannot render past the body's bottom
    // edge into the footer's render band. Combined with the page-level
    // `paddingBottom: FOOTER_SAFE_AREA_PT`, this is a 2x defensive carve that
    // covers both normal-flow pagination (where `paddingBottom` is sufficient)
    // and non-paginating distributions (where only `marginBottom` saves you).
    // See the JSDoc on `FOOTER_SAFE_AREA_PT` above for the full rationale.
    pageBody: {
      flex: 1,
      marginBottom: FOOTER_SAFE_AREA_PT
    }
  });
}
function ExportHeaderPdf({
  brand,
  title,
  toolLabel,
  subtitle,
  prominence = "maximum"
}) {
  const styles = makeChromeStyles(brand);
  const lockupSize = prominence === "maximum" ? 32 : 26;
  const titleSize = prominence === "maximum" ? 22 : 18;
  const Logo = brand.renderLogoMarkPdf;
  return /* @__PURE__ */ jsxs(View, { style: styles.headerRow, fixed: false, children: [
    /* @__PURE__ */ jsxs(View, { style: styles.headerLeft, children: [
      /* @__PURE__ */ jsx(Text, { style: styles.eyebrow, children: toolLabel }),
      /* @__PURE__ */ jsx(Text, { style: [styles.title, { fontSize: titleSize }], children: title }),
      subtitle ? /* @__PURE__ */ jsx(Text, { style: styles.subtitle, children: subtitle }) : null
    ] }),
    /* @__PURE__ */ jsxs(View, { style: styles.lockupRow, children: [
      /* @__PURE__ */ jsx(Logo, { size: lockupSize, variant: "original" }),
      /* @__PURE__ */ jsx(Text, { style: styles.wordmark, children: brand.name })
    ] })
  ] });
}
function ExportFooterPdf({
  brand,
  url,
  dateLabel,
  qrDataUrl,
  prominence = "maximum",
  fixed = true
}) {
  const styles = makeChromeStyles(brand);
  const isRefined = prominence === "refined";
  const showTagline = prominence === "maximum" && Boolean(brand.tagline);
  const markSize = isRefined ? 20 : 26;
  const showQr = Boolean(qrDataUrl);
  const Logo = brand.renderLogoMarkPdf;
  return /* @__PURE__ */ jsxs(View, { style: styles.footerRow, fixed, children: [
    /* @__PURE__ */ jsxs(View, { style: styles.footerLeft, children: [
      /* @__PURE__ */ jsx(Logo, { size: markSize, variant: "original" }),
      /* @__PURE__ */ jsxs(View, { children: [
        /* @__PURE__ */ jsx(Text, { style: styles.footerName, children: brand.name }),
        showTagline ? /* @__PURE__ */ jsx(Text, { style: styles.footerTagline, children: brand.tagline }) : null
      ] })
    ] }),
    /* @__PURE__ */ jsxs(View, { style: styles.footerMid, children: [
      /* @__PURE__ */ jsx(Text, { style: styles.footerUrl, children: url }),
      dateLabel ? /* @__PURE__ */ jsx(Text, { style: styles.footerDate, children: dateLabel }) : null
    ] }),
    showQr && qrDataUrl ? /* @__PURE__ */ jsx(
      Image,
      {
        src: qrDataUrl,
        style: isRefined ? styles.qrRefined : styles.qr
      }
    ) : null
  ] });
}
function BrandedPdfPage({
  brand,
  title,
  toolLabel,
  subtitle,
  url,
  dateLabel,
  qrDataUrl,
  prominence = "maximum",
  pageStyle,
  size = "LETTER",
  children
}) {
  const styles = makeChromeStyles(brand);
  const defaultPageStyle = {
    paddingTop: 36,
    paddingHorizontal: 36,
    paddingBottom: FOOTER_SAFE_AREA_PT,
    fontFamily: "Helvetica",
    backgroundColor: brand.colors.surface ?? "#ffffff",
    fontSize: 10,
    color: brand.colors.ink
  };
  const mergedPageStyle = { ...defaultPageStyle, ...pageStyle };
  return /* @__PURE__ */ jsxs(Page, { size, style: mergedPageStyle, children: [
    /* @__PURE__ */ jsx(
      ExportHeaderPdf,
      {
        brand,
        title,
        toolLabel,
        subtitle,
        prominence
      }
    ),
    /* @__PURE__ */ jsx(View, { style: styles.pageBody, children }),
    /* @__PURE__ */ jsx(
      ExportFooterPdf,
      {
        brand,
        url,
        dateLabel,
        qrDataUrl,
        prominence
      }
    )
  ] });
}
export {
  BrandedPdfPage,
  ExportFooterPdf,
  ExportHeaderPdf,
  FOOTER_SAFE_AREA_PT,
  buildExportFilename,
  buildExportUrl,
  generateQrDataUrl,
  resolveProminence,
  tierToProminence
};
//# sourceMappingURL=index.mjs.map