@pixldocs/canvas-renderer 0.5.157 → 0.5.159
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index-NR05ndTM.cjs → index-CA-UhjM7.cjs} +101 -7
- package/dist/{index-NR05ndTM.cjs.map → index-CA-UhjM7.cjs.map} +1 -1
- package/dist/{index-xn-L7QHB.js → index-ogNxtubz.js} +101 -7
- package/dist/{index-xn-L7QHB.js.map → index-ogNxtubz.js.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/{svgTextToPath-7fhL08qs.cjs → pdfFonts-BTEVnYX8.cjs} +31 -796
- package/dist/pdfFonts-BTEVnYX8.cjs.map +1 -0
- package/dist/{svgTextToPath-V1vC0SQt.js → pdfFonts-b3_bv7F0.js} +20 -747
- package/dist/pdfFonts-b3_bv7F0.js.map +1 -0
- package/dist/svgTextToPath-BXAzwaaR.js +706 -0
- package/dist/svgTextToPath-BXAzwaaR.js.map +1 -0
- package/dist/svgTextToPath-IM1f6F-f.cjs +745 -0
- package/dist/svgTextToPath-IM1f6F-f.cjs.map +1 -0
- package/dist/{vectorPdfExport-CZyyQbwm.js → vectorPdfExport-BRxfHxZU.js} +8 -54
- package/dist/vectorPdfExport-BRxfHxZU.js.map +1 -0
- package/dist/{vectorPdfExport-CTktki-M.cjs → vectorPdfExport-BqyoXT--.cjs} +8 -54
- package/dist/vectorPdfExport-BqyoXT--.cjs.map +1 -0
- package/package.json +1 -1
- package/dist/svgTextToPath-7fhL08qs.cjs.map +0 -1
- package/dist/svgTextToPath-V1vC0SQt.js.map +0 -1
- package/dist/vectorPdfExport-CTktki-M.cjs.map +0 -1
- package/dist/vectorPdfExport-CZyyQbwm.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdfFonts-BTEVnYX8.cjs","sources":["../../../src/lib/pdfFonts.ts"],"sourcesContent":["// Utility for loading local TTF fonts into jsPDF for vector PDF rendering\n\nconst fontCache: Map<string, string> = new Map();\n/** Cache for raw font bytes (used by HarfBuzz / opentype.js for path conversion) */\nconst fontBytesCache: Map<string, Uint8Array> = new Map();\n/** Cache for Google Fonts CSS-parsed TTF URLs (so we don't re-fetch CSS for every weight) */\nconst googleFontUrlCache: Map<string, string> = new Map();\n/** Negative cache — specific Google Font variants known not to exist; don't keep retrying */\nconst googleFontNotFound: Set<string> = new Set();\n/**\n * Negative cache for the Supabase font-proxy edge function. Once a specific\n * (family, weight, italic, source) tuple returns a non-OK / fallback response\n * we never probe again for the lifetime of this module — eliminates the\n * hundreds of 4xx/5xx requests in DevTools when a template references font\n * families that don't exist on Google Fonts or Fontshare.\n */\nconst proxyNotFound: Set<string> = new Set();\n/**\n * Family-level short-circuit cache. If the base (family, 400, upright) probe\n * fails on BOTH google and fontshare, the family doesn't exist on either CDN\n * — skip every subsequent weight/italic probe for the same family.\n */\nconst familyNotOnAnyCdn: Set<string> = new Set();\nconst familyConfirmedOnSomeCdn: Set<string> = new Set();\n\nconst proxyKey = (family: string, weight: number, isItalic: boolean, source: string): string =>\n `${source}|${family}|${weight}|${isItalic ? 'i' : 'n'}`;\n\n// ── localStorage persistence ──\n// Negative caches survive page reloads so the FIRST export of a new tab\n// doesn't pay the full font-probe ladder for families known to be missing\n// from previous sessions. Positive cache (`familyConfirmedOnSomeCdn`) is\n// also persisted so we can short-circuit \"family exists, only this variant\n// is missing\" decisions without a probe.\nconst LS_KEY = 'pdfFonts.negCache.v1';\nconst LS_VERSION = 1;\nfunction loadPersistedCaches(): void {\n try {\n if (typeof localStorage === 'undefined') return;\n const raw = localStorage.getItem(LS_KEY);\n if (!raw) return;\n const obj = JSON.parse(raw);\n if (!obj || obj.v !== LS_VERSION) return;\n (obj.proxyNotFound || []).forEach((k: string) => proxyNotFound.add(k));\n (obj.familyNotOnAnyCdn || []).forEach((k: string) => familyNotOnAnyCdn.add(k));\n (obj.familyConfirmedOnSomeCdn || []).forEach((k: string) => familyConfirmedOnSomeCdn.add(k));\n } catch { /* ignore corrupt cache */ }\n}\nlet persistTimer: any = null;\nfunction persistCaches(): void {\n try {\n if (typeof localStorage === 'undefined') return;\n if (persistTimer) clearTimeout(persistTimer);\n persistTimer = setTimeout(() => {\n try {\n localStorage.setItem(LS_KEY, JSON.stringify({\n v: LS_VERSION,\n proxyNotFound: Array.from(proxyNotFound),\n familyNotOnAnyCdn: Array.from(familyNotOnAnyCdn),\n familyConfirmedOnSomeCdn: Array.from(familyConfirmedOnSomeCdn),\n }));\n } catch { /* quota exceeded — ignore */ }\n }, 250);\n } catch { /* ignore */ }\n}\nloadPersistedCaches();\n\n/** Force-clear all negative caches (useful for debugging). Not called automatically. */\nexport const resetPdfFontProbeCaches = (): void => {\n proxyNotFound.clear();\n familyNotOnAnyCdn.clear();\n familyConfirmedOnSomeCdn.clear();\n googleFontNotFound.clear();\n try { if (typeof localStorage !== 'undefined') localStorage.removeItem(LS_KEY); } catch {}\n};\n/** Runtime registry of families successfully embedded into the active jsPDF bundle. */\nconst registeredFamilies: Set<string> = new Set();\n/** Runtime glyph coverage for each embedded (family, weight, italic) variant. */\nconst registeredVariantCoverage: Map<string, Set<number>> = new Map();\n\nexport const isFamilyEmbedded = (family: string): boolean => registeredFamilies.has(family);\n\n/**\n * Per-variant registry: which (family, weight, italic) tuples were actually\n * registered into the active jsPDF document. The SVG rewriter uses this to\n * avoid emitting a font-family like \"DMSerifDisplay-Bold\" when only the\n * Regular variant was embedded — emitting an unregistered name causes jsPDF\n * to silently fall back to Helvetica, breaking visual font parity with the\n * canvas preview.\n */\nconst registeredVariants: Set<string> = new Set();\n\nconst variantKey = (family: string, weight: number, italic: boolean): string =>\n `${family}|${weight}|${italic ? 'i' : 'n'}`;\n\nconst remoteVariantKey = (family: string, weight: number, italic: boolean): string =>\n `${family}|${resolveFontWeight(weight)}|${italic ? 'i' : 'n'}`;\n\nexport const resetPdfFontRegistry = (): void => {\n registeredFamilies.clear();\n registeredVariants.clear();\n registeredVariantCoverage.clear();\n};\n\nexport const isVariantEmbedded = (family: string, weight: number, italic: boolean): boolean =>\n registeredVariants.has(variantKey(family, resolveFontWeight(weight), italic));\n\n/**\n * Diagnostic: returns the sorted list of (family, weight, italic) variants\n * that were actually registered into the active jsPDF document. Useful for\n * comparing client vs server embed sets to diagnose file-size diffs.\n */\nexport const getEmbeddedVariantsList = (): string[] => {\n return Array.from(registeredVariants).sort();\n};\n\nexport const doesVariantSupportChar = (\n family: string,\n weight: number,\n italic: boolean,\n char: string,\n): boolean => {\n const cp = char.codePointAt(0);\n if (cp == null) return false;\n return registeredVariantCoverage.get(variantKey(family, resolveFontWeight(weight), italic))?.has(cp) === true;\n};\n\n/**\n * Pick the closest registered (weight, italic) variant for a family. Used by\n * the SVG-to-jsPDF rewriter when the requested exact variant isn't embedded\n * (e.g. user requested Bold but the family has no real Bold and Google's\n * fallback fetch returned 404). Returns null if the family has no registered\n * variants at all.\n */\nexport const resolveBestRegisteredVariant = (\n family: string,\n weight: number,\n italic: boolean,\n): { weight: number; italic: boolean } | null => {\n const want = resolveFontWeight(weight);\n const weights = [300, 400, 500, 600, 700];\n // 1. Exact match\n if (registeredVariants.has(variantKey(family, want, italic))) {\n return { weight: want, italic };\n }\n // 2. Same italic, nearest weight (prefer heavier when bold requested)\n const sortedByDistance = [...weights].sort((a, b) => {\n const da = Math.abs(a - want);\n const db = Math.abs(b - want);\n if (da !== db) return da - db;\n // tie: when wanting bold, prefer heavier; when wanting light, prefer lighter\n return want >= 500 ? b - a : a - b;\n });\n for (const w of sortedByDistance) {\n if (registeredVariants.has(variantKey(family, w, italic))) {\n return { weight: w, italic };\n }\n }\n // 3. Opposite italic, nearest weight\n for (const w of sortedByDistance) {\n if (registeredVariants.has(variantKey(family, w, !italic))) {\n return { weight: w, italic: !italic };\n }\n }\n return null;\n};\n\n// Server-side font proxy: needed because the browser sends modern UA hints\n// (sec-ch-ua) that override our custom User-Agent header, so Google Fonts\n// returns WOFF2 instead of TTF. The edge function spoofs a legacy UA and\n// returns embeddable TTF bytes for any Google Font / Fontshare family.\n//\n// Resolved LAZILY so this module works in two contexts:\n// 1. Client app — reads `import.meta.env.VITE_SUPABASE_URL` at build time.\n// 2. Server harness (`@pixldocs/canvas-renderer` browser bundle running\n// inside Puppeteer on EC2) — Vite does NOT inline VITE_SUPABASE_URL into\n// that standalone bundle, so we fall back to `window.__PIXLDOCS_SUPABASE_URL`,\n// which the harness HTML sets from the request payload before running.\nfunction resolveFontProxyUrl(): string {\n const fromEnv = (() => {\n try {\n return (import.meta as any).env?.VITE_SUPABASE_URL ?? '';\n } catch {\n return '';\n }\n })();\n const fromWindow = (() => {\n try {\n return (typeof window !== 'undefined' && (window as any).__PIXLDOCS_SUPABASE_URL) || '';\n } catch {\n return '';\n }\n })();\n const base = fromEnv || fromWindow || '';\n return base ? `${base}/functions/v1/font-proxy` : '';\n}\n\nasync function fetchTtfViaProxy(\n family: string,\n weight: number,\n isItalic: boolean,\n source: 'google' | 'fontshare',\n): Promise<Uint8Array | null> {\n const proxyUrl = resolveFontProxyUrl();\n if (!proxyUrl) return null;\n // Negative caches — skip probes that previously failed.\n const key = proxyKey(family, weight, isItalic, source);\n if (proxyNotFound.has(key)) return null;\n // Family short-circuit: if base variant failed on every CDN, skip everything.\n if (familyNotOnAnyCdn.has(family)) return null;\n try {\n const url = `${proxyUrl}?family=${encodeURIComponent(family)}&weight=${weight}&italic=${isItalic ? 1 : 0}&source=${source}`;\n const res = await fetch(url);\n if (!res.ok) {\n proxyNotFound.add(key);\n persistCaches();\n return null;\n }\n // Edge function may now return 200 + JSON `{fallback:true}` for upstream\n // misses (so DevTools doesn't flash red on every probe). Detect that\n // shape via Content-Type and treat as a miss.\n const ct = res.headers.get('content-type') || '';\n if (ct.startsWith('application/json')) {\n try {\n const j = await res.json();\n if (j && (j.fallback || j.error)) proxyNotFound.add(key);\n } catch {\n proxyNotFound.add(key);\n }\n persistCaches();\n return null;\n }\n const buf = await res.arrayBuffer();\n const bytes = new Uint8Array(buf);\n if (bytes.byteLength < 64) {\n proxyNotFound.add(key);\n persistCaches();\n return null;\n }\n familyConfirmedOnSomeCdn.add(family);\n persistCaches();\n return bytes;\n } catch {\n proxyNotFound.add(key);\n persistCaches();\n return null;\n }\n}\n\n/**\n * Probe the base (family, 400, upright) variant on both Google and Fontshare\n * before fetching every weight/italic combination. If both miss, mark the\n * family as missing so all subsequent variant probes are skipped.\n * Returns true if the family is available on at least one CDN.\n */\nexport async function familyProbe(family: string): Promise<boolean> {\n if (familyConfirmedOnSomeCdn.has(family)) return true;\n if (familyNotOnAnyCdn.has(family)) return false;\n // Reuse fetchTtfViaProxy for the base probe — populates negative caches and\n // the bytes cache as a side-effect, so the subsequent 400-regular embed\n // doesn't re-fetch.\n const g = await fetchTtfViaProxy(family, 400, false, 'google');\n if (g) return true;\n const f = await fetchTtfViaProxy(family, 400, false, 'fontshare');\n if (f) return true;\n familyNotOnAnyCdn.add(family);\n return false;\n}\n\n// Weight labels for jsPDF font names (editor uses 300, 400, 500, 600, 700)\nexport const FONT_WEIGHT_LABELS: Record<number, string> = {\n 300: 'Light',\n 400: 'Regular',\n 500: 'Medium',\n 600: 'SemiBold',\n 700: 'Bold',\n};\n\n// Resolve numeric weight to the closest supported key (300, 400, 500, 600, 700)\nexport function resolveFontWeight(weight: number): number {\n if (weight <= 350) return 300;\n if (weight <= 450) return 400;\n if (weight <= 550) return 500;\n if (weight <= 650) return 600;\n return 700;\n}\n\n// Font file mapping - maps font names to optional weight-specific TTF paths\nexport type FontWeightFiles = {\n regular: string;\n bold?: string;\n light?: string;\n medium?: string;\n semibold?: string;\n // Italic variants\n italic?: string;\n boldItalic?: string;\n lightItalic?: string;\n mediumItalic?: string;\n semiboldItalic?: string;\n};\n\n/** Font used for symbols (● ◆ ★ etc.) when the main font lacks the glyph. Must be in FONT_FILES. */\nexport const FONT_FALLBACK_SYMBOLS = 'Noto Sans';\n\n/** Tertiary fallback for math operators / arrows (≠ ≤ ≥ ≈ ∞ → ← × ÷ ∑ √ ∈ …)\n * that are not present in the main font OR in FONT_FALLBACK_SYMBOLS. Must be in FONT_FILES. */\nexport const FONT_FALLBACK_MATH = 'Noto Sans Math';\n\n/** Font used for Devanagari / Hindi script when the main font lacks the glyphs. Must be in FONT_FILES. */\nexport const FONT_FALLBACK_DEVANAGARI = 'Hind';\n\n// List paths under public/fonts.\n// All entries now use static (per-weight) TTF files for reliable PDF export.\n// Variable font files are kept in fonts.css for browser rendering only.\nexport const FONT_FILES: Record<string, FontWeightFiles> = {\n 'Playfair Display': {\n regular: '/fonts/PlayfairDisplay-Regular.ttf',\n bold: '/fonts/PlayfairDisplay-Bold.ttf',\n italic: '/fonts/PlayfairDisplay-Italic.ttf',\n boldItalic: '/fonts/PlayfairDisplay-BoldItalic.ttf',\n },\n 'Merriweather': {\n regular: '/fonts/Merriweather-Regular.ttf',\n bold: '/fonts/Merriweather-Bold.ttf',\n light: '/fonts/Merriweather-Light.ttf',\n italic: '/fonts/Merriweather-Italic.ttf',\n boldItalic: '/fonts/Merriweather-BoldItalic.ttf',\n lightItalic: '/fonts/Merriweather-LightItalic.ttf',\n },\n 'Lora': {\n regular: '/fonts/Lora-Regular.ttf',\n bold: '/fonts/Lora-Bold.ttf',\n italic: '/fonts/Lora-Italic.ttf',\n boldItalic: '/fonts/Lora-BoldItalic.ttf',\n },\n 'Montserrat': {\n regular: '/fonts/Montserrat-Regular.ttf',\n bold: '/fonts/Montserrat-Bold.ttf',\n light: '/fonts/Montserrat-Light.ttf',\n medium: '/fonts/Montserrat-Medium.ttf',\n semibold: '/fonts/Montserrat-SemiBold.ttf',\n italic: '/fonts/Montserrat-Italic.ttf',\n boldItalic: '/fonts/Montserrat-BoldItalic.ttf',\n lightItalic: '/fonts/Montserrat-LightItalic.ttf',\n mediumItalic: '/fonts/Montserrat-MediumItalic.ttf',\n semiboldItalic: '/fonts/Montserrat-SemiBoldItalic.ttf',\n },\n 'Open Sans': {\n regular: '/fonts/OpenSans-Regular.ttf',\n bold: '/fonts/OpenSans-Bold.ttf',\n light: '/fonts/OpenSans-Light.ttf',\n semibold: '/fonts/OpenSans-SemiBold.ttf',\n italic: '/fonts/OpenSans-Italic.ttf',\n boldItalic: '/fonts/OpenSans-BoldItalic.ttf',\n lightItalic: '/fonts/OpenSans-LightItalic.ttf',\n semiboldItalic: '/fonts/OpenSans-SemiBoldItalic.ttf',\n },\n 'Roboto': {\n regular: '/fonts/Roboto-Regular.ttf',\n bold: '/fonts/Roboto-Bold.ttf',\n light: '/fonts/Roboto-Light.ttf',\n medium: '/fonts/Roboto-Medium.ttf',\n italic: '/fonts/Roboto-Italic.ttf',\n boldItalic: '/fonts/Roboto-BoldItalic.ttf',\n lightItalic: '/fonts/Roboto-LightItalic.ttf',\n mediumItalic: '/fonts/Roboto-MediumItalic.ttf',\n },\n 'Lato': {\n regular: '/fonts/Lato-Regular.ttf',\n bold: '/fonts/Lato-Bold.ttf',\n light: '/fonts/Lato-Light.ttf',\n italic: '/fonts/Lato-Italic.ttf',\n boldItalic: '/fonts/Lato-BoldItalic.ttf',\n lightItalic: '/fonts/Lato-LightItalic.ttf',\n },\n 'Raleway': {\n regular: '/fonts/Raleway-Regular.ttf',\n bold: '/fonts/Raleway-Bold.ttf',\n light: '/fonts/Raleway-Light.ttf',\n medium: '/fonts/Raleway-Medium.ttf',\n semibold: '/fonts/Raleway-SemiBold.ttf',\n italic: '/fonts/Raleway-Italic.ttf',\n boldItalic: '/fonts/Raleway-BoldItalic.ttf',\n lightItalic: '/fonts/Raleway-LightItalic.ttf',\n },\n 'Poppins': {\n regular: '/fonts/Poppins-Regular.ttf',\n bold: '/fonts/Poppins-Bold.ttf',\n light: '/fonts/Poppins-Light.ttf',\n medium: '/fonts/Poppins-Medium.ttf',\n semibold: '/fonts/Poppins-SemiBold.ttf',\n italic: '/fonts/Poppins-Italic.ttf',\n boldItalic: '/fonts/Poppins-BoldItalic.ttf',\n lightItalic: '/fonts/Poppins-LightItalic.ttf',\n mediumItalic: '/fonts/Poppins-MediumItalic.ttf',\n semiboldItalic: '/fonts/Poppins-SemiBoldItalic.ttf',\n },\n 'Inter': {\n regular: '/fonts/Inter-Regular.ttf',\n bold: '/fonts/Inter-Bold.ttf',\n italic: '/fonts/Inter-Italic.ttf',\n boldItalic: '/fonts/Inter-BoldItalic.ttf',\n },\n 'Nunito': {\n regular: '/fonts/Nunito-Regular.ttf',\n bold: '/fonts/Nunito-Bold.ttf',\n light: '/fonts/Nunito-Light.ttf',\n medium: '/fonts/Nunito-Medium.ttf',\n semibold: '/fonts/Nunito-SemiBold.ttf',\n italic: '/fonts/Nunito-Italic.ttf',\n boldItalic: '/fonts/Nunito-BoldItalic.ttf',\n },\n 'Source Sans Pro': {\n regular: '/fonts/SourceSansPro-Regular.ttf',\n bold: '/fonts/SourceSansPro-Bold.ttf',\n light: '/fonts/SourceSansPro-Light.ttf',\n italic: '/fonts/SourceSansPro-Italic.ttf',\n boldItalic: '/fonts/SourceSansPro-BoldItalic.ttf',\n },\n 'Work Sans': {\n regular: '/fonts/WorkSans-Regular.ttf',\n bold: '/fonts/WorkSans-Bold.ttf',\n italic: '/fonts/WorkSans-Italic.ttf',\n boldItalic: '/fonts/WorkSans-BoldItalic.ttf',\n },\n 'Oswald': { regular: '/fonts/Oswald-Regular.ttf', bold: '/fonts/Oswald-Bold.ttf' },\n 'Bebas Neue': { regular: '/fonts/BebasNeue-Regular.ttf' },\n 'Abril Fatface': { regular: '/fonts/AbrilFatface-Regular.ttf' },\n 'Dancing Script': { regular: '/fonts/DancingScript-Regular.ttf', bold: '/fonts/DancingScript-Bold.ttf' },\n 'Pacifico': { regular: '/fonts/Pacifico-Regular.ttf' },\n 'Great Vibes': { regular: '/fonts/GreatVibes-Regular.ttf' },\n\n // ── Previously variable-only fonts — now with static per-weight TTFs for PDF export ──\n 'DM Sans': {\n regular: '/fonts/DMSans-Regular.ttf',\n bold: '/fonts/DMSans-Bold.ttf',\n light: '/fonts/DMSans-Light.ttf',\n medium: '/fonts/DMSans-Medium.ttf',\n semibold: '/fonts/DMSans-SemiBold.ttf',\n italic: '/fonts/DMSans-RegularItalic.ttf',\n boldItalic: '/fonts/DMSans-BoldItalic.ttf',\n lightItalic: '/fonts/DMSans-LightItalic.ttf',\n mediumItalic: '/fonts/DMSans-MediumItalic.ttf',\n semiboldItalic: '/fonts/DMSans-SemiBoldItalic.ttf',\n },\n 'Outfit': {\n regular: '/fonts/Outfit-Regular.ttf',\n bold: '/fonts/Outfit-Bold.ttf',\n light: '/fonts/Outfit-Light.ttf',\n medium: '/fonts/Outfit-Medium.ttf',\n semibold: '/fonts/Outfit-SemiBold.ttf',\n },\n 'Figtree': {\n regular: '/fonts/Figtree-Regular.ttf',\n bold: '/fonts/Figtree-Bold.ttf',\n light: '/fonts/Figtree-Light.ttf',\n medium: '/fonts/Figtree-Medium.ttf',\n semibold: '/fonts/Figtree-SemiBold.ttf',\n italic: '/fonts/Figtree-RegularItalic.ttf',\n boldItalic: '/fonts/Figtree-BoldItalic.ttf',\n lightItalic: '/fonts/Figtree-LightItalic.ttf',\n mediumItalic: '/fonts/Figtree-MediumItalic.ttf',\n semiboldItalic: '/fonts/Figtree-SemiBoldItalic.ttf',\n },\n 'Manrope': {\n regular: '/fonts/Manrope-Regular.ttf',\n bold: '/fonts/Manrope-Bold.ttf',\n light: '/fonts/Manrope-Light.ttf',\n medium: '/fonts/Manrope-Medium.ttf',\n semibold: '/fonts/Manrope-SemiBold.ttf',\n },\n 'Space Grotesk': {\n regular: '/fonts/SpaceGrotesk-Regular.ttf',\n bold: '/fonts/SpaceGrotesk-Bold.ttf',\n light: '/fonts/SpaceGrotesk-Light.ttf',\n medium: '/fonts/SpaceGrotesk-Medium.ttf',\n semibold: '/fonts/SpaceGrotesk-SemiBold.ttf',\n },\n 'League Spartan': {\n regular: '/fonts/LeagueSpartan-Regular.ttf',\n bold: '/fonts/LeagueSpartan-Bold.ttf',\n light: '/fonts/LeagueSpartan-Light.ttf',\n medium: '/fonts/LeagueSpartan-Medium.ttf',\n semibold: '/fonts/LeagueSpartan-SemiBold.ttf',\n },\n 'EB Garamond': {\n regular: '/fonts/EBGaramond-Regular.ttf',\n bold: '/fonts/EBGaramond-Bold.ttf',\n medium: '/fonts/EBGaramond-Medium.ttf',\n semibold: '/fonts/EBGaramond-SemiBold.ttf',\n italic: '/fonts/EBGaramond-RegularItalic.ttf',\n boldItalic: '/fonts/EBGaramond-BoldItalic.ttf',\n mediumItalic: '/fonts/EBGaramond-MediumItalic.ttf',\n semiboldItalic: '/fonts/EBGaramond-SemiBoldItalic.ttf',\n },\n 'Libre Baskerville': {\n regular: '/fonts/LibreBaskerville-Regular.ttf',\n bold: '/fonts/LibreBaskerville-Bold.ttf',\n italic: '/fonts/LibreBaskerville-RegularItalic.ttf',\n boldItalic: '/fonts/LibreBaskerville-BoldItalic.ttf',\n },\n 'Crimson Text': {\n regular: '/fonts/CrimsonText-Regular.ttf',\n bold: '/fonts/CrimsonText-Bold.ttf',\n italic: '/fonts/CrimsonText-Italic.ttf',\n boldItalic: '/fonts/CrimsonText-BoldItalic.ttf',\n },\n 'DM Serif Display': {\n regular: '/fonts/DMSerifDisplay-Regular.ttf',\n italic: '/fonts/DMSerifDisplay-Italic.ttf',\n },\n 'Libre Franklin': {\n regular: '/fonts/LibreFranklin-Regular.ttf',\n bold: '/fonts/LibreFranklin-Bold.ttf',\n light: '/fonts/LibreFranklin-Light.ttf',\n medium: '/fonts/LibreFranklin-Medium.ttf',\n semibold: '/fonts/LibreFranklin-SemiBold.ttf',\n italic: '/fonts/LibreFranklin-RegularItalic.ttf',\n boldItalic: '/fonts/LibreFranklin-BoldItalic.ttf',\n lightItalic: '/fonts/LibreFranklin-LightItalic.ttf',\n mediumItalic: '/fonts/LibreFranklin-MediumItalic.ttf',\n semiboldItalic: '/fonts/LibreFranklin-SemiBoldItalic.ttf',\n },\n 'Mulish': {\n regular: '/fonts/Mulish-Regular.ttf',\n bold: '/fonts/Mulish-Bold.ttf',\n light: '/fonts/Mulish-Light.ttf',\n medium: '/fonts/Mulish-Medium.ttf',\n semibold: '/fonts/Mulish-SemiBold.ttf',\n italic: '/fonts/Mulish-RegularItalic.ttf',\n boldItalic: '/fonts/Mulish-BoldItalic.ttf',\n lightItalic: '/fonts/Mulish-LightItalic.ttf',\n mediumItalic: '/fonts/Mulish-MediumItalic.ttf',\n semiboldItalic: '/fonts/Mulish-SemiBoldItalic.ttf',\n },\n 'Quicksand': {\n regular: '/fonts/Quicksand-Regular.ttf',\n bold: '/fonts/Quicksand-Bold.ttf',\n light: '/fonts/Quicksand-Light.ttf',\n medium: '/fonts/Quicksand-Medium.ttf',\n semibold: '/fonts/Quicksand-SemiBold.ttf',\n },\n 'Rubik': {\n regular: '/fonts/Rubik-Regular.ttf',\n bold: '/fonts/Rubik-Bold.ttf',\n light: '/fonts/Rubik-Light.ttf',\n medium: '/fonts/Rubik-Medium.ttf',\n semibold: '/fonts/Rubik-SemiBold.ttf',\n italic: '/fonts/Rubik-RegularItalic.ttf',\n boldItalic: '/fonts/Rubik-BoldItalic.ttf',\n lightItalic: '/fonts/Rubik-LightItalic.ttf',\n mediumItalic: '/fonts/Rubik-MediumItalic.ttf',\n semiboldItalic: '/fonts/Rubik-SemiBoldItalic.ttf',\n },\n 'Karla': {\n regular: '/fonts/Karla-Regular.ttf',\n bold: '/fonts/Karla-Bold.ttf',\n light: '/fonts/Karla-Light.ttf',\n medium: '/fonts/Karla-Medium.ttf',\n semibold: '/fonts/Karla-SemiBold.ttf',\n italic: '/fonts/Karla-RegularItalic.ttf',\n boldItalic: '/fonts/Karla-BoldItalic.ttf',\n lightItalic: '/fonts/Karla-LightItalic.ttf',\n mediumItalic: '/fonts/Karla-MediumItalic.ttf',\n semiboldItalic: '/fonts/Karla-SemiBoldItalic.ttf',\n },\n 'Plus Jakarta Sans': {\n regular: '/fonts/PlusJakartaSans-Regular.ttf',\n bold: '/fonts/PlusJakartaSans-Bold.ttf',\n light: '/fonts/PlusJakartaSans-Light.ttf',\n medium: '/fonts/PlusJakartaSans-Medium.ttf',\n semibold: '/fonts/PlusJakartaSans-SemiBold.ttf',\n italic: '/fonts/PlusJakartaSans-RegularItalic.ttf',\n boldItalic: '/fonts/PlusJakartaSans-BoldItalic.ttf',\n lightItalic: '/fonts/PlusJakartaSans-LightItalic.ttf',\n mediumItalic: '/fonts/PlusJakartaSans-MediumItalic.ttf',\n semiboldItalic: '/fonts/PlusJakartaSans-SemiBoldItalic.ttf',\n },\n 'Sora': {\n regular: '/fonts/Sora-Regular.ttf',\n bold: '/fonts/Sora-Bold.ttf',\n light: '/fonts/Sora-Light.ttf',\n medium: '/fonts/Sora-Medium.ttf',\n semibold: '/fonts/Sora-SemiBold.ttf',\n },\n 'Urbanist': {\n regular: '/fonts/Urbanist-Regular.ttf',\n bold: '/fonts/Urbanist-Bold.ttf',\n light: '/fonts/Urbanist-Light.ttf',\n medium: '/fonts/Urbanist-Medium.ttf',\n semibold: '/fonts/Urbanist-SemiBold.ttf',\n italic: '/fonts/Urbanist-RegularItalic.ttf',\n boldItalic: '/fonts/Urbanist-BoldItalic.ttf',\n lightItalic: '/fonts/Urbanist-LightItalic.ttf',\n mediumItalic: '/fonts/Urbanist-MediumItalic.ttf',\n semiboldItalic: '/fonts/Urbanist-SemiBoldItalic.ttf',\n },\n 'Lexend': {\n regular: '/fonts/Lexend-Regular.ttf',\n bold: '/fonts/Lexend-Bold.ttf',\n light: '/fonts/Lexend-Light.ttf',\n medium: '/fonts/Lexend-Medium.ttf',\n semibold: '/fonts/Lexend-SemiBold.ttf',\n },\n 'Albert Sans': {\n regular: '/fonts/AlbertSans-Regular.ttf',\n bold: '/fonts/AlbertSans-Bold.ttf',\n light: '/fonts/AlbertSans-Light.ttf',\n medium: '/fonts/AlbertSans-Medium.ttf',\n semibold: '/fonts/AlbertSans-SemiBold.ttf',\n italic: '/fonts/AlbertSans-RegularItalic.ttf',\n boldItalic: '/fonts/AlbertSans-BoldItalic.ttf',\n lightItalic: '/fonts/AlbertSans-LightItalic.ttf',\n mediumItalic: '/fonts/AlbertSans-MediumItalic.ttf',\n semiboldItalic: '/fonts/AlbertSans-SemiBoldItalic.ttf',\n },\n 'Noto Sans': {\n regular: '/fonts/NotoSans-Regular.ttf',\n bold: '/fonts/NotoSans-Bold.ttf',\n light: '/fonts/NotoSans-Light.ttf',\n medium: '/fonts/NotoSans-Medium.ttf',\n semibold: '/fonts/NotoSans-SemiBold.ttf',\n italic: '/fonts/NotoSans-RegularItalic.ttf',\n boldItalic: '/fonts/NotoSans-BoldItalic.ttf',\n lightItalic: '/fonts/NotoSans-LightItalic.ttf',\n mediumItalic: '/fonts/NotoSans-MediumItalic.ttf',\n semiboldItalic: '/fonts/NotoSans-SemiBoldItalic.ttf',\n },\n 'Cabin': {\n regular: '/fonts/Cabin-Regular.ttf',\n bold: '/fonts/Cabin-Bold.ttf',\n medium: '/fonts/Cabin-Medium.ttf',\n semibold: '/fonts/Cabin-SemiBold.ttf',\n italic: '/fonts/Cabin-RegularItalic.ttf',\n boldItalic: '/fonts/Cabin-BoldItalic.ttf',\n mediumItalic: '/fonts/Cabin-MediumItalic.ttf',\n semiboldItalic: '/fonts/Cabin-SemiBoldItalic.ttf',\n },\n 'Barlow': {\n regular: '/fonts/Barlow-Regular.ttf',\n bold: '/fonts/Barlow-Bold.ttf',\n light: '/fonts/Barlow-Light.ttf',\n medium: '/fonts/Barlow-Medium.ttf',\n semibold: '/fonts/Barlow-SemiBold.ttf',\n italic: '/fonts/Barlow-Italic.ttf',\n boldItalic: '/fonts/Barlow-BoldItalic.ttf',\n },\n 'Josefin Sans': {\n regular: '/fonts/JosefinSans-Regular.ttf',\n bold: '/fonts/JosefinSans-Bold.ttf',\n light: '/fonts/JosefinSans-Light.ttf',\n medium: '/fonts/JosefinSans-Medium.ttf',\n semibold: '/fonts/JosefinSans-SemiBold.ttf',\n italic: '/fonts/JosefinSans-RegularItalic.ttf',\n boldItalic: '/fonts/JosefinSans-BoldItalic.ttf',\n lightItalic: '/fonts/JosefinSans-LightItalic.ttf',\n mediumItalic: '/fonts/JosefinSans-MediumItalic.ttf',\n semiboldItalic: '/fonts/JosefinSans-SemiBoldItalic.ttf',\n },\n 'Archivo': {\n regular: '/fonts/Archivo-Regular.ttf',\n bold: '/fonts/Archivo-Bold.ttf',\n light: '/fonts/Archivo-Light.ttf',\n medium: '/fonts/Archivo-Medium.ttf',\n semibold: '/fonts/Archivo-SemiBold.ttf',\n italic: '/fonts/Archivo-RegularItalic.ttf',\n boldItalic: '/fonts/Archivo-BoldItalic.ttf',\n lightItalic: '/fonts/Archivo-LightItalic.ttf',\n mediumItalic: '/fonts/Archivo-MediumItalic.ttf',\n semiboldItalic: '/fonts/Archivo-SemiBoldItalic.ttf',\n },\n 'Overpass': {\n regular: '/fonts/Overpass-Regular.ttf',\n bold: '/fonts/Overpass-Bold.ttf',\n light: '/fonts/Overpass-Light.ttf',\n medium: '/fonts/Overpass-Medium.ttf',\n semibold: '/fonts/Overpass-SemiBold.ttf',\n italic: '/fonts/Overpass-RegularItalic.ttf',\n boldItalic: '/fonts/Overpass-BoldItalic.ttf',\n lightItalic: '/fonts/Overpass-LightItalic.ttf',\n mediumItalic: '/fonts/Overpass-MediumItalic.ttf',\n semiboldItalic: '/fonts/Overpass-SemiBoldItalic.ttf',\n },\n 'Exo 2': {\n regular: '/fonts/Exo2-Regular.ttf',\n bold: '/fonts/Exo2-Bold.ttf',\n light: '/fonts/Exo2-Light.ttf',\n medium: '/fonts/Exo2-Medium.ttf',\n semibold: '/fonts/Exo2-SemiBold.ttf',\n italic: '/fonts/Exo2-RegularItalic.ttf',\n boldItalic: '/fonts/Exo2-BoldItalic.ttf',\n lightItalic: '/fonts/Exo2-LightItalic.ttf',\n mediumItalic: '/fonts/Exo2-MediumItalic.ttf',\n semiboldItalic: '/fonts/Exo2-SemiBoldItalic.ttf',\n },\n 'Roboto Mono': {\n regular: '/fonts/RobotoMono-Regular.ttf',\n bold: '/fonts/RobotoMono-Bold.ttf',\n light: '/fonts/RobotoMono-Light.ttf',\n medium: '/fonts/RobotoMono-Medium.ttf',\n semibold: '/fonts/RobotoMono-SemiBold.ttf',\n italic: '/fonts/RobotoMono-RegularItalic.ttf',\n boldItalic: '/fonts/RobotoMono-BoldItalic.ttf',\n lightItalic: '/fonts/RobotoMono-LightItalic.ttf',\n mediumItalic: '/fonts/RobotoMono-MediumItalic.ttf',\n semiboldItalic: '/fonts/RobotoMono-SemiBoldItalic.ttf',\n },\n 'Fira Code': {\n regular: '/fonts/FiraCode-Regular.ttf',\n bold: '/fonts/FiraCode-Bold.ttf',\n light: '/fonts/FiraCode-Light.ttf',\n medium: '/fonts/FiraCode-Medium.ttf',\n semibold: '/fonts/FiraCode-SemiBold.ttf',\n },\n 'JetBrains Mono': {\n regular: '/fonts/JetBrainsMono-Regular.ttf',\n bold: '/fonts/JetBrainsMono-Bold.ttf',\n light: '/fonts/JetBrainsMono-Light.ttf',\n medium: '/fonts/JetBrainsMono-Medium.ttf',\n semibold: '/fonts/JetBrainsMono-SemiBold.ttf',\n italic: '/fonts/JetBrainsMono-RegularItalic.ttf',\n boldItalic: '/fonts/JetBrainsMono-BoldItalic.ttf',\n lightItalic: '/fonts/JetBrainsMono-LightItalic.ttf',\n mediumItalic: '/fonts/JetBrainsMono-MediumItalic.ttf',\n semiboldItalic: '/fonts/JetBrainsMono-SemiBoldItalic.ttf',\n },\n 'Source Code Pro': {\n regular: '/fonts/SourceCodePro-Regular.ttf',\n bold: '/fonts/SourceCodePro-Bold.ttf',\n light: '/fonts/SourceCodePro-Light.ttf',\n medium: '/fonts/SourceCodePro-Medium.ttf',\n semibold: '/fonts/SourceCodePro-SemiBold.ttf',\n italic: '/fonts/SourceCodePro-RegularItalic.ttf',\n boldItalic: '/fonts/SourceCodePro-BoldItalic.ttf',\n lightItalic: '/fonts/SourceCodePro-LightItalic.ttf',\n mediumItalic: '/fonts/SourceCodePro-MediumItalic.ttf',\n semiboldItalic: '/fonts/SourceCodePro-SemiBoldItalic.ttf',\n },\n 'IBM Plex Mono': {\n regular: '/fonts/IBMPlexMono-Regular.ttf',\n bold: '/fonts/IBMPlexMono-Bold.ttf',\n },\n 'Space Mono': {\n regular: '/fonts/SpaceMono-Regular.ttf',\n bold: '/fonts/SpaceMono-Bold.ttf',\n italic: '/fonts/SpaceMono-Italic.ttf',\n boldItalic: '/fonts/SpaceMono-BoldItalic.ttf',\n },\n 'Sacramento': { regular: '/fonts/Sacramento-Regular.ttf' },\n 'Alex Brush': { regular: '/fonts/AlexBrush-Regular.ttf' },\n 'Allura': { regular: '/fonts/Allura-Regular.ttf' },\n 'Caveat': {\n regular: '/fonts/Caveat-Regular.ttf',\n bold: '/fonts/Caveat-Bold.ttf',\n medium: '/fonts/Caveat-Medium.ttf',\n semibold: '/fonts/Caveat-SemiBold.ttf',\n },\n 'Lobster': { regular: '/fonts/Lobster-Regular.ttf' },\n 'Comfortaa': {\n regular: '/fonts/Comfortaa-Regular.ttf',\n bold: '/fonts/Comfortaa-Bold.ttf',\n light: '/fonts/Comfortaa-Light.ttf',\n medium: '/fonts/Comfortaa-Medium.ttf',\n semibold: '/fonts/Comfortaa-SemiBold.ttf',\n },\n 'Anton': { regular: '/fonts/Anton-Regular.ttf' },\n 'Teko': {\n regular: '/fonts/Teko-Regular.ttf',\n bold: '/fonts/Teko-Bold.ttf',\n light: '/fonts/Teko-Light.ttf',\n medium: '/fonts/Teko-Medium.ttf',\n semibold: '/fonts/Teko-SemiBold.ttf',\n },\n // ── Indic Script Fallback Fonts ──\n 'Noto Sans Devanagari': {\n regular: '/fonts/NotoSansDevanagari-Regular.ttf',\n bold: '/fonts/NotoSansDevanagari-Bold.ttf',\n light: '/fonts/NotoSansDevanagari-Light.ttf',\n medium: '/fonts/NotoSansDevanagari-Medium.ttf',\n semibold: '/fonts/NotoSansDevanagari-SemiBold.ttf',\n },\n 'Hind': {\n regular: '/fonts/Hind-Regular.ttf',\n bold: '/fonts/Hind-Bold.ttf',\n light: '/fonts/Hind-Light.ttf',\n medium: '/fonts/Hind-Medium.ttf',\n semibold: '/fonts/Hind-SemiBold.ttf',\n },\n // ── Math / Operator Symbol Fallback ──\n // Carries glyphs that NotoSans-Regular's Latin subset is missing\n // (≠ ≤ ≥ ≈ ∞ → ← × ÷ ∑ √ ∈ ∀ ∃ etc.). Used as a tertiary fallback\n // ONLY for chars classified as 'math' that the main font + Noto Sans\n // both lack.\n 'Noto Sans Math': {\n regular: '/fonts/NotoSansMath-Regular.ttf',\n },\n};\n\n// Convert font file to Base64\nconst fontToBase64 = async (url: string): Promise<string> => {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch font: ${response.statusText}`);\n }\n const arrayBuffer = await response.arrayBuffer();\n \n // Convert ArrayBuffer to Base64\n const bytes = new Uint8Array(arrayBuffer);\n if (!isJsPdfEmbeddableTrueType(bytes)) {\n throw new Error(`Font is not a jsPDF-compatible TrueType file: ${url}`);\n }\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n};\n\nfunction isJsPdfEmbeddableTrueType(bytes: Uint8Array): boolean {\n if (bytes.length < 12) return false;\n const signature = String.fromCharCode(bytes[0], bytes[1], bytes[2], bytes[3]);\n if (signature !== '\\x00\\x01\\x00\\x00' && signature !== 'true') return false;\n\n const u16 = (offset: number) => (bytes[offset] << 8) | bytes[offset + 1];\n const u32 = (offset: number) => ((bytes[offset] << 24) | (bytes[offset + 1] << 16) | (bytes[offset + 2] << 8) | bytes[offset + 3]) >>> 0;\n const tableCount = u16(4);\n for (let i = 0; i < tableCount; i++) {\n const recordOffset = 12 + i * 16;\n if (recordOffset + 16 > bytes.length) return false;\n const tag = String.fromCharCode(bytes[recordOffset], bytes[recordOffset + 1], bytes[recordOffset + 2], bytes[recordOffset + 3]);\n if (tag !== 'cmap') continue;\n const cmapOffset = u32(recordOffset + 8);\n const cmapLength = u32(recordOffset + 12);\n if (cmapOffset + Math.min(cmapLength, 4) > bytes.length) return false;\n const subtables = u16(cmapOffset + 2);\n for (let j = 0; j < subtables; j++) {\n const encOffset = cmapOffset + 4 + j * 8;\n if (encOffset + 8 > bytes.length) return false;\n const platform = u16(encOffset);\n const encoding = u16(encOffset + 2);\n if (platform === 0 || (platform === 3 && (encoding === 1 || encoding === 10))) return true;\n }\n return false;\n }\n return false;\n}\n\nfunction extractSupportedCodePointsFromTtf(bytes: Uint8Array): Set<number> {\n const supported = new Set<number>();\n if (bytes.length < 12) return supported;\n const u16 = (offset: number) => (bytes[offset] << 8) | bytes[offset + 1];\n const i16 = (offset: number) => {\n const value = u16(offset);\n return value & 0x8000 ? value - 0x10000 : value;\n };\n const u32 = (offset: number) => ((bytes[offset] << 24) | (bytes[offset + 1] << 16) | (bytes[offset + 2] << 8) | bytes[offset + 3]) >>> 0;\n const tableCount = u16(4);\n let cmapOffset = 0;\n for (let i = 0; i < tableCount; i++) {\n const recordOffset = 12 + i * 16;\n if (recordOffset + 16 > bytes.length) return supported;\n if (String.fromCharCode(bytes[recordOffset], bytes[recordOffset + 1], bytes[recordOffset + 2], bytes[recordOffset + 3]) === 'cmap') {\n cmapOffset = u32(recordOffset + 8);\n break;\n }\n }\n if (!cmapOffset || cmapOffset + 4 > bytes.length) return supported;\n const subtables = u16(cmapOffset + 2);\n const candidates: Array<{ format: number; offset: number; score: number }> = [];\n for (let j = 0; j < subtables; j++) {\n const encOffset = cmapOffset + 4 + j * 8;\n if (encOffset + 8 > bytes.length) continue;\n const platform = u16(encOffset);\n const encoding = u16(encOffset + 2);\n const subOffset = cmapOffset + u32(encOffset + 4);\n if (subOffset + 2 > bytes.length) continue;\n const format = u16(subOffset);\n const score = format === 12 ? 40 : format === 4 ? 30 : 0;\n if (score) candidates.push({ format, offset: subOffset, score: score + (platform === 3 && encoding === 10 ? 2 : platform === 0 ? 1 : 0) });\n }\n candidates.sort((a, b) => b.score - a.score);\n const best = candidates[0];\n if (!best) return supported;\n if (best.format === 12 && best.offset + 16 <= bytes.length) {\n const nGroups = u32(best.offset + 12);\n for (let i = 0; i < nGroups; i++) {\n const off = best.offset + 16 + i * 12;\n if (off + 12 > bytes.length) break;\n const start = u32(off);\n const end = u32(off + 4);\n for (let cp = start; cp <= end && cp <= 0x10FFFF; cp++) supported.add(cp);\n }\n } else if (best.format === 4 && best.offset + 14 <= bytes.length) {\n const segCount = u16(best.offset + 6) / 2;\n const endCodes = best.offset + 14;\n const startCodes = endCodes + segCount * 2 + 2;\n const idDeltas = startCodes + segCount * 2;\n const idRangeOffsets = idDeltas + segCount * 2;\n for (let i = 0; i < segCount; i++) {\n const start = u16(startCodes + i * 2);\n const end = u16(endCodes + i * 2);\n const delta = i16(idDeltas + i * 2);\n const rangeOffset = u16(idRangeOffsets + i * 2);\n for (let cp = start; cp <= end && cp !== 0xFFFF; cp++) {\n if (rangeOffset === 0) {\n if (((cp + delta) & 0xffff) !== 0) supported.add(cp);\n } else {\n const glyphOffset = idRangeOffsets + i * 2 + rangeOffset + (cp - start) * 2;\n if (glyphOffset + 2 <= bytes.length && u16(glyphOffset) !== 0) supported.add(cp);\n }\n }\n }\n }\n return supported;\n}\n\nfunction base64ToBytes(base64: string): Uint8Array {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return bytes;\n}\n\n// Get jsPDF-compatible font name (sanitized - no spaces)\nexport const getJsPDFFontName = (fontName: string): string => {\n return fontName.replace(/\\s+/g, '');\n};\n\n// Weight → file key and fallback order for resolving TTF path (normal style)\nconst WEIGHT_TO_KEYS: Record<number, (keyof FontWeightFiles)[]> = {\n 300: ['light', 'regular'],\n 400: ['regular'],\n 500: ['medium', 'regular'],\n 600: ['semibold', 'bold', 'regular'],\n 700: ['bold', 'regular'],\n};\n\n// Weight → file key and fallback order for resolving TTF path (italic style)\nconst WEIGHT_TO_ITALIC_KEYS: Record<number, (keyof FontWeightFiles)[]> = {\n 300: ['lightItalic', 'italic', 'light', 'regular'],\n 400: ['italic', 'regular'],\n 500: ['mediumItalic', 'italic', 'medium', 'regular'],\n 600: ['semiboldItalic', 'boldItalic', 'italic', 'semibold', 'bold', 'regular'],\n 700: ['boldItalic', 'italic', 'bold', 'regular'],\n};\n\nfunction getFontPathForWeight(fontFiles: FontWeightFiles, resolvedWeight: number, isItalic = false): string {\n const keys = isItalic ? WEIGHT_TO_ITALIC_KEYS[resolvedWeight] : WEIGHT_TO_KEYS[resolvedWeight];\n if (!keys) return fontFiles.regular;\n for (const k of keys) {\n const path = fontFiles[k];\n if (path) return path;\n }\n return fontFiles.regular;\n}\n\n/**\n * True when the path resolved by getFontPathForWeight is actually the file for\n * the requested (weight, italic) — not a fallback (e.g. resolving Bold to\n * Regular because the family has no Bold file). Used so we can avoid\n * registering Regular bytes under a \"Bold\" name (which makes jsPDF render\n * inline bold spans in regular weight).\n */\nfunction isExactWeightItalicMatch(\n fontFiles: FontWeightFiles,\n resolvedWeight: number,\n isItalic: boolean,\n resolvedPath: string,\n): boolean {\n const exactKey: keyof FontWeightFiles | null = isItalic\n ? resolvedWeight === 300 ? 'lightItalic'\n : resolvedWeight === 500 ? 'mediumItalic'\n : resolvedWeight === 600 ? 'semiboldItalic'\n : resolvedWeight === 700 ? 'boldItalic'\n : 'italic'\n : resolvedWeight === 300 ? 'light'\n : resolvedWeight === 500 ? 'medium'\n : resolvedWeight === 600 ? 'semibold'\n : resolvedWeight === 700 ? 'bold'\n : 'regular';\n return !!exactKey && fontFiles[exactKey] === resolvedPath;\n}\n\n/** Check if the resolved path is actually an italic-specific file */\nfunction isItalicPath(fontFiles: FontWeightFiles, path: string): boolean {\n return path === fontFiles.italic ||\n path === fontFiles.boldItalic ||\n path === fontFiles.lightItalic ||\n path === fontFiles.mediumItalic ||\n path === fontFiles.semiboldItalic;\n}\n\n// Returns the jsPDF font name used when embedding; includes italic suffix when applicable\nexport const getEmbeddedJsPDFFontName = (fontName: string, weight: number, isItalic = false): string => {\n const resolved = resolveFontWeight(weight);\n const label = FONT_WEIGHT_LABELS[resolved];\n const italicSuffix = isItalic ? 'Italic' : '';\n return `${getJsPDFFontName(fontName)}-${label}${italicSuffix}`;\n};\n\n// Load and embed a font into jsPDF from local TTF files (one jsPDF font per weight+style, style always \"normal\")\nexport const embedFont = async (\n pdf: any,\n fontName: string,\n weight: number = 400,\n isItalic = false,\n): Promise<boolean> => {\n const fontFiles = FONT_FILES[fontName];\n if (!fontFiles) {\n console.warn(`Font ${fontName} not found in local fonts`);\n return false;\n }\n\n const resolvedWeight = resolveFontWeight(weight);\n const fontPath = getFontPathForWeight(fontFiles, resolvedWeight, isItalic);\n if (!fontPath) return false;\n\n // If the local family lacks a TTF for this exact (weight, italic) and would\n // fall back to Regular, refuse — let embedFontWithGoogleFallback fetch a\n // real variant from Google Fonts / Fontshare. Registering Regular bytes\n // under e.g. \"DMSerifDisplay-Bold\" makes jsPDF render bold spans in\n // regular weight, breaking inline bold/italic in selectable PDFs.\n if (!isExactWeightItalicMatch(fontFiles, resolvedWeight, isItalic, fontPath)) {\n return false;\n }\n\n const label = FONT_WEIGHT_LABELS[resolvedWeight];\n const italicSuffix = isItalic ? 'Italic' : '';\n const cacheKey = `${fontName}-${resolvedWeight}${isItalic ? '-italic' : ''}`;\n const jsPdfFontName = getEmbeddedJsPDFFontName(fontName, weight, isItalic);\n\n try {\n let base64Font = fontCache.get(cacheKey);\n if (!base64Font) {\n const response = await fetch(fontPath);\n if (!response.ok) throw new Error(`Failed to fetch font: ${response.statusText}`);\n const arrayBuffer = await response.arrayBuffer();\n const bytes = new Uint8Array(arrayBuffer);\n if (!isJsPdfEmbeddableTrueType(bytes)) throw new Error(`Font is not a jsPDF-compatible TrueType file: ${fontPath}`);\n registeredVariantCoverage.set(variantKey(fontName, resolvedWeight, isItalic), extractSupportedCodePointsFromTtf(bytes));\n let binary = '';\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);\n base64Font = btoa(binary);\n fontCache.set(cacheKey, base64Font);\n } else if (!registeredVariantCoverage.has(variantKey(fontName, resolvedWeight, isItalic))) {\n // The registry is reset per PDF export, but `fontCache` persists across\n // exports. Rebuild glyph coverage directly from the cached TTF bytes;\n // otherwise supported glyphs like Karla's `≠` are treated as missing and\n // incorrectly rewritten to Noto Sans Math in selectable PDFs.\n registeredVariantCoverage.set(variantKey(fontName, resolvedWeight, isItalic), extractSupportedCodePointsFromTtf(base64ToBytes(base64Font)));\n }\n\n const fileName = `${getJsPDFFontName(fontName)}-${label}${italicSuffix}.ttf`;\n pdf.addFileToVFS(fileName, base64Font);\n pdf.addFont(fileName, jsPdfFontName, 'normal');\n if (fontName !== jsPdfFontName) {\n try {\n pdf.addFont(fileName, fontName, 'normal');\n } catch {\n // Ignore duplicate alias registration; svg2pdf only needs one successful alias.\n }\n }\n registeredFamilies.add(fontName);\n registeredVariants.add(variantKey(fontName, resolvedWeight, isItalic));\n return true;\n } catch (error) {\n console.error(`Failed to embed font ${fontName} (weight ${weight}, italic=${isItalic}):`, error);\n return false;\n }\n};\n\n// Pre-load all font weights into cache (can be called at app start for faster PDF export)\nexport const preloadFonts = async (): Promise<void> => {\n const loadPromises: Promise<void>[] = [];\n const weights = [300, 400, 500, 600, 700] as const;\n\n for (const [fontName, files] of Object.entries(FONT_FILES)) {\n for (const w of weights) {\n // Normal\n const path = getFontPathForWeight(files as FontWeightFiles, w);\n if (path) {\n const cacheKey = `${fontName}-${w}`;\n loadPromises.push(\n fontToBase64(path)\n .then(base64 => { fontCache.set(cacheKey, base64); })\n .catch(err => console.warn(`Failed to preload ${fontName} weight ${w}:`, err))\n );\n }\n // Italic\n const italicPath = getFontPathForWeight(files as FontWeightFiles, w, true);\n if (italicPath && italicPath !== path) {\n const cacheKeyItalic = `${fontName}-${w}-italic`;\n loadPromises.push(\n fontToBase64(italicPath)\n .then(base64 => { fontCache.set(cacheKeyItalic, base64); })\n .catch(err => console.warn(`Failed to preload ${fontName} weight ${w} italic:`, err))\n );\n }\n }\n }\n\n await Promise.all(loadPromises);\n};\n\n// Check if a font is available locally\nexport const isFontAvailable = (fontName: string): boolean => {\n return fontName in FONT_FILES;\n};\n\n// Check if a font has an italic variant for the given weight\nexport const hasItalicVariant = (fontName: string, weight: number = 400): boolean => {\n const files = FONT_FILES[fontName];\n if (!files) return false;\n const resolvedWeight = resolveFontWeight(weight);\n const normalPath = getFontPathForWeight(files, resolvedWeight, false);\n const italicPath = getFontPathForWeight(files, resolvedWeight, true);\n return italicPath !== normalPath && isItalicPath(files, italicPath);\n};\n\n// Get all available font names\nexport const getAvailableFonts = (): string[] => {\n return Object.keys(FONT_FILES);\n};\n\n/**\n * Get available font weights for a given font family.\n * Returns only weights that have a dedicated TTF file (not fallbacks).\n */\nexport const getAvailableWeights = (fontFamily: string): number[] => {\n const files = FONT_FILES[fontFamily];\n if (!files) return [400]; // Fallback: at least regular\n\n const weights: number[] = [];\n if (files.light) weights.push(300);\n // regular always exists\n weights.push(400);\n if (files.medium) weights.push(500);\n if (files.semibold) weights.push(600);\n if (files.bold) weights.push(700);\n\n return weights;\n};\n\n/**\n * Check if a font has any italic variant at all.\n */\nexport const hasAnyItalicVariant = (fontFamily: string): boolean => {\n const files = FONT_FILES[fontFamily];\n if (!files) return false;\n return !!(files.italic || files.boldItalic || files.lightItalic || files.mediumItalic || files.semiboldItalic);\n};\n\n// ═══════════════════════════════════════════════════════════════\n// Google Fonts dynamic TTF fetching (parity with EC2 server)\n// ═══════════════════════════════════════════════════════════════\n\n/** Fetch a TTF (as base64) for any Google Font. Caches per (family, weight, style). */\nexport async function fetchGoogleFontTTF(\n fontFamily: string,\n weight: number = 400,\n isItalic = false,\n): Promise<string | null> {\n const cacheKey = `gf:${fontFamily}:${weight}:${isItalic ? 'i' : 'n'}`;\n if (fontCache.has(cacheKey)) return fontCache.get(cacheKey)!;\n const notFoundKey = remoteVariantKey(fontFamily, weight, isItalic);\n if (googleFontNotFound.has(notFoundKey)) return null;\n // Try the server-side proxy first — it reliably returns TTF since the edge\n // function can spoof a legacy UA. Direct browser fetch is unreliable because\n // sec-ch-ua client hints override our custom User-Agent.\n const proxyBytes = await fetchTtfViaProxy(fontFamily, weight, isItalic, 'google');\n if (proxyBytes && isJsPdfEmbeddableTrueType(proxyBytes)) {\n fontBytesCache.set(cacheKey, proxyBytes);\n let binary = '';\n for (let i = 0; i < proxyBytes.length; i++) binary += String.fromCharCode(proxyBytes[i]);\n const b64 = btoa(binary);\n fontCache.set(cacheKey, b64);\n return b64;\n }\n if (resolveFontProxyUrl()) return null;\n try {\n const ital = isItalic ? '1' : '0';\n const cssUrl = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(\n fontFamily,\n )}:ital,wght@${ital},${weight}&display=swap`;\n // The User-Agent below tricks Google Fonts into returning legacy TTF (not WOFF2),\n // matching what the EC2 server does so jsPDF can consume it.\n const cssRes = await fetch(cssUrl, {\n headers: {\n 'User-Agent':\n 'Mozilla/5.0 (Linux; U; Android 2.2; en-us) AppleWebKit/533.1 (KHTML, like Gecko)',\n },\n });\n if (!cssRes.ok) {\n if (cssRes.status === 400 || cssRes.status === 404) googleFontNotFound.add(notFoundKey);\n return null;\n }\n const css = await cssRes.text();\n const urlMatch = css.match(/url\\(([^)]+)\\)\\s+format\\(['\"]?truetype['\"]?\\)/i)\n || css.match(/url\\(([^)]+)\\)/);\n if (!urlMatch) return null;\n const ttfUrl = urlMatch[1].replace(/['\"]/g, '');\n googleFontUrlCache.set(cacheKey, ttfUrl);\n const ttfRes = await fetch(ttfUrl);\n if (!ttfRes.ok) return null;\n const buf = await ttfRes.arrayBuffer();\n const bytes = new Uint8Array(buf);\n if (!isJsPdfEmbeddableTrueType(bytes)) {\n console.warn(`[pdfFonts] Google Fonts returned a non-TTF font for ${fontFamily} (${weight}); skipping jsPDF embed`);\n return null;\n }\n fontBytesCache.set(cacheKey, bytes);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);\n const b64 = btoa(binary);\n fontCache.set(cacheKey, b64);\n return b64;\n } catch (err) {\n console.warn(`[pdfFonts] fetchGoogleFontTTF failed for ${fontFamily} (${weight}):`, err);\n return null;\n }\n}\n\n/** Get raw TTF bytes for a Google Font (used by opentype.js / HarfBuzz). */\nexport async function getGoogleFontBytes(\n fontFamily: string,\n weight: number = 400,\n isItalic = false,\n): Promise<Uint8Array | null> {\n const cacheKey = `gf:${fontFamily}:${weight}:${isItalic ? 'i' : 'n'}`;\n if (fontBytesCache.has(cacheKey)) return fontBytesCache.get(cacheKey)!;\n await fetchGoogleFontTTF(fontFamily, weight, isItalic);\n return fontBytesCache.get(cacheKey) || null;\n}\n\n// ═══════════════════════════════════════════════════════════════\n// Fontshare dynamic TTF fetching (Satoshi, Clash Display, etc.)\n// ═══════════════════════════════════════════════════════════════\n\nconst fontshareNotFound: Set<string> = new Set();\n\n/** Convert a font family display name to the slug Fontshare's API expects. */\nfunction toFontshareSlug(family: string): string {\n return family.trim().toLowerCase().replace(/\\s+/g, '-');\n}\n\n/**\n * Fetch a TTF (as base64) for a Fontshare family. Mirrors `fetchGoogleFontTTF`:\n * pulls the CSS for the requested weight/style, picks the `format('truetype')`\n * URL, downloads the bytes, validates, and caches under the same key shape used\n * for Google Fonts so all downstream consumers work without changes.\n */\nexport async function fetchFontshareTTF(\n fontFamily: string,\n weight: number = 400,\n isItalic = false,\n slug?: string,\n): Promise<string | null> {\n const cacheKey = `gf:${fontFamily}:${weight}:${isItalic ? 'i' : 'n'}`;\n if (fontCache.has(cacheKey)) return fontCache.get(cacheKey)!;\n const notFoundKey = remoteVariantKey(fontFamily, weight, isItalic);\n if (fontshareNotFound.has(notFoundKey)) return null;\n const proxyBytes = await fetchTtfViaProxy(fontFamily, weight, isItalic, 'fontshare');\n if (proxyBytes && isJsPdfEmbeddableTrueType(proxyBytes)) {\n fontBytesCache.set(cacheKey, proxyBytes);\n let binary = '';\n for (let i = 0; i < proxyBytes.length; i++) binary += String.fromCharCode(proxyBytes[i]);\n const b64 = btoa(binary);\n fontCache.set(cacheKey, b64);\n return b64;\n }\n if (resolveFontProxyUrl()) return null;\n const finalSlug = slug || toFontshareSlug(fontFamily);\n try {\n const styleSuffix = isItalic ? 'i' : '';\n const cssUrl = `https://api.fontshare.com/v2/css?f[]=${finalSlug}@${weight}${styleSuffix}&display=swap`;\n const cssRes = await fetch(cssUrl);\n if (!cssRes.ok) {\n if (cssRes.status === 400 || cssRes.status === 404) fontshareNotFound.add(notFoundKey);\n return null;\n }\n const css = await cssRes.text();\n // Fontshare CSS includes woff2/woff/ttf; pick truetype explicitly.\n const ttMatch = css.match(/url\\(([^)]+)\\)\\s+format\\(['\"]?truetype['\"]?\\)/i);\n if (!ttMatch) {\n fontshareNotFound.add(notFoundKey);\n return null;\n }\n let ttfUrl = ttMatch[1].replace(/['\"]/g, '').trim();\n if (ttfUrl.startsWith('//')) ttfUrl = `https:${ttfUrl}`;\n const ttfRes = await fetch(ttfUrl);\n if (!ttfRes.ok) return null;\n const buf = await ttfRes.arrayBuffer();\n const bytes = new Uint8Array(buf);\n if (!isJsPdfEmbeddableTrueType(bytes)) {\n console.warn(`[pdfFonts] Fontshare returned a non-TTF font for ${fontFamily} (${weight}); skipping jsPDF embed`);\n return null;\n }\n fontBytesCache.set(cacheKey, bytes);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);\n const b64 = btoa(binary);\n fontCache.set(cacheKey, b64);\n return b64;\n } catch (err) {\n console.warn(`[pdfFonts] fetchFontshareTTF failed for ${fontFamily} (${weight}):`, err);\n return null;\n }\n}\n\n/** Get raw TTF bytes for a Fontshare font (used by opentype.js / HarfBuzz). */\nexport async function getFontshareFontBytes(\n fontFamily: string,\n weight: number = 400,\n isItalic = false,\n slug?: string,\n): Promise<Uint8Array | null> {\n const cacheKey = `gf:${fontFamily}:${weight}:${isItalic ? 'i' : 'n'}`;\n if (fontBytesCache.has(cacheKey)) return fontBytesCache.get(cacheKey)!;\n await fetchFontshareTTF(fontFamily, weight, isItalic, slug);\n return fontBytesCache.get(cacheKey) || null;\n}\n\n/**\n * Embed a font into jsPDF — local TTF if available, otherwise Google Fonts.\n * Returns true on success. Registers under the SAME jsPDF font name as\n * `getEmbeddedJsPDFFontName(...)` so SVG rewriting matches.\n */\nexport const embedFontWithGoogleFallback = async (\n pdf: any,\n fontName: string,\n weight: number = 400,\n isItalic = false,\n): Promise<boolean> => {\n // 1. Local first\n if (FONT_FILES[fontName]) {\n const ok = await embedFont(pdf, fontName, weight, isItalic);\n if (ok) return true;\n }\n\n // Family short-circuit: if base 400-regular missed on every CDN already,\n // skip the variant ladder entirely. Saves 6–8 wasted edge-function calls\n // per missing family (massive DevTools spam reduction + faster export).\n if (familyNotOnAnyCdn.has(fontName)) return false;\n\n // 2. Try the requested variant first on Fontshare, then Google. Many\n // decorative families on Google Fonts and Fontshare ship a SINGLE\n // weight (e.g. Pacifico, Frijole, Stardom only at 400). The canvas\n // fakes bold/semibold via synthetic-bold rendering — the PDF must do\n // the same: when the requested weight is unavailable, fall back\n // through a weight ladder so the family still embeds with its real\n // glyphs and svg2pdf can match by family. Without this fallback,\n // bold display fonts silently substitute Helvetica/Times in the PDF.\n const resolved = resolveFontWeight(weight);\n const weightLadder: number[] = [resolved];\n for (const w of [400, 500, 700, 600, 300]) {\n if (!weightLadder.includes(w)) weightLadder.push(w);\n }\n\n const tryFetch = async (w: number, italic: boolean): Promise<string | null> => {\n const fs = await fetchFontshareTTF(fontName, w, italic);\n if (fs) return fs;\n const g = await fetchGoogleFontTTF(fontName, w, italic);\n return g;\n };\n\n let b64: string | null = null;\n let usedItalic = isItalic;\n let usedWeight = resolved;\n for (const w of weightLadder) {\n b64 = await tryFetch(w, isItalic);\n if (b64) { usedWeight = w; break; }\n }\n // If italic was requested but no italic variant exists at any weight,\n // fall back to upright bytes so the family still renders. svg2pdf will\n // skew via the existing synthetic-italic transform path in the rewriter.\n if (!b64 && isItalic) {\n for (const w of weightLadder) {\n b64 = await tryFetch(w, false);\n if (b64) { usedItalic = false; usedWeight = w; break; }\n }\n }\n if (!b64) {\n // Both CDNs missed for this variant. If the base 400-regular also failed\n // for both (meaning the family doesn't exist anywhere), seed the family\n // short-circuit so subsequent variant requests skip the ladder.\n if (\n !familyConfirmedOnSomeCdn.has(fontName) &&\n proxyNotFound.has(proxyKey(fontName, 400, false, 'google')) &&\n proxyNotFound.has(proxyKey(fontName, 400, false, 'fontshare'))\n ) {\n familyNotOnAnyCdn.add(fontName);\n persistCaches();\n }\n // For italic requests, do NOT silently register upright bytes under the\n // italic variant key — that previously caused inline italic spans to\n // render in upright glyphs in the PDF. Instead we let\n // `resolveBestRegisteredVariant` (in the SVG rewriter) fall back to a\n // lighter italic weight that actually carries italic glyphs, with\n // synthetic bold (stroke) applied for the weight delta.\n return false;\n }\n // Register the bytes under the ACTUAL weight whose glyphs we fetched.\n // This is critical for visual parity with the canvas: when the requested\n // weight (e.g. 700) is not available and we fell back to 400, the SVG\n // rewriter's `resolveBestRegisteredVariant` will return weight=400, and\n // `needsSyntheticBold(700, 400)` will trigger the stroke-based synthetic\n // bold path — matching what the browser does on <canvas> for\n // single-weight families like Pacifico/Stardom/Frijole.\n return registerJsPdfFont(pdf, fontName, usedWeight, usedItalic, b64);\n};\n\n/** Register a base64 TTF inside jsPDF under the canonical embedded name + alias. */\nfunction registerJsPdfFont(\n pdf: any,\n fontName: string,\n resolvedWeight: number,\n isItalic: boolean,\n base64: string,\n): boolean {\n const label = FONT_WEIGHT_LABELS[resolvedWeight];\n const italicSuffix = isItalic ? 'Italic' : '';\n const jsPdfFontName = getEmbeddedJsPDFFontName(fontName, resolvedWeight, isItalic);\n const fileName = `${getJsPDFFontName(fontName)}-${label}${italicSuffix}.ttf`;\n try {\n try {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n registeredVariantCoverage.set(variantKey(fontName, resolvedWeight, isItalic), extractSupportedCodePointsFromTtf(bytes));\n } catch {\n // Coverage is an optimization for choosing fallbacks; font registration can still proceed.\n }\n pdf.addFileToVFS(fileName, base64);\n pdf.addFont(fileName, jsPdfFontName, 'normal');\n if (fontName !== jsPdfFontName) {\n try {\n pdf.addFont(fileName, fontName, 'normal');\n } catch {\n /* duplicate alias; ignore */\n }\n }\n registeredFamilies.add(fontName);\n registeredVariants.add(variantKey(fontName, resolvedWeight, isItalic));\n return true;\n } catch (err) {\n console.warn(`[pdfFonts] registerJsPdfFont failed for ${fontName}:`, err);\n return false;\n }\n}\n\n// ═══════════════════════════════════════════════════════════════\n// Latin → Devanagari font sibling mapping\n// ═══════════════════════════════════════════════════════════════\n\n/**\n * Map of Latin Google Fonts → their Devanagari sibling family on Google Fonts.\n * When a user picks a Latin font and types Hindi, we use the matching Devanagari\n * family for path conversion so the visual style is preserved (instead of always\n * falling back to Hind). Sourced from Google's own family pairings.\n */\nexport const LATIN_TO_DEVANAGARI: Record<string, string> = {\n // Direct Devanagari subsets — same family carries both scripts\n 'Poppins': 'Poppins',\n 'Noto Sans': 'Noto Sans Devanagari',\n 'Noto Serif': 'Noto Serif Devanagari',\n 'Hind': 'Hind',\n 'Mukta': 'Mukta',\n\n // Curated visual matches (Google's own recommendations)\n 'Montserrat': 'Mukta',\n 'Open Sans': 'Mukta',\n 'Lato': 'Mukta',\n 'Roboto': 'Mukta',\n 'Inter': 'Mukta',\n 'Nunito': 'Mukta',\n 'Source Sans Pro': 'Mukta',\n 'Work Sans': 'Mukta',\n 'DM Sans': 'Mukta',\n 'Outfit': 'Mukta',\n 'Figtree': 'Mukta',\n 'Manrope': 'Mukta',\n 'Plus Jakarta Sans': 'Mukta',\n 'Sora': 'Mukta',\n 'Urbanist': 'Mukta',\n 'Lexend': 'Mukta',\n 'Albert Sans': 'Mukta',\n 'Cabin': 'Mukta',\n 'Karla': 'Mukta',\n 'Mulish': 'Mukta',\n 'Rubik': 'Mukta',\n 'Quicksand': 'Mukta',\n 'Libre Franklin': 'Mukta',\n 'Barlow': 'Mukta',\n 'Archivo': 'Mukta',\n 'Overpass': 'Mukta',\n 'Josefin Sans': 'Mukta',\n 'Exo 2': 'Mukta',\n 'Space Grotesk': 'Mukta',\n\n // Display / heavy\n 'Oswald': 'Teko',\n 'Bebas Neue': 'Teko',\n 'Anton': 'Teko',\n 'Teko': 'Teko',\n 'League Spartan': 'Teko',\n\n // Serifs → Tiro Devanagari Hindi (a refined Devanagari serif)\n 'Playfair Display': 'Tiro Devanagari Hindi',\n 'Merriweather': 'Tiro Devanagari Hindi',\n 'Lora': 'Tiro Devanagari Hindi',\n 'EB Garamond': 'Tiro Devanagari Hindi',\n 'Libre Baskerville': 'Tiro Devanagari Hindi',\n 'Crimson Text': 'Tiro Devanagari Hindi',\n 'DM Serif Display': 'Tiro Devanagari Sanskrit',\n 'Abril Fatface': 'Tiro Devanagari Sanskrit',\n\n // Handwriting → Kalam (the only serious Devanagari handwriting family on GF)\n 'Dancing Script': 'Kalam',\n 'Pacifico': 'Kalam',\n 'Great Vibes': 'Kalam',\n 'Sacramento': 'Kalam',\n 'Alex Brush': 'Kalam',\n 'Allura': 'Kalam',\n 'Caveat': 'Kalam',\n 'Lobster': 'Kalam',\n 'Comfortaa': 'Mukta',\n\n // Monospace → there's no proper Devanagari mono; fall back to Mukta\n 'Roboto Mono': 'Mukta',\n 'Fira Code': 'Mukta',\n 'JetBrains Mono': 'Mukta',\n 'Source Code Pro': 'Mukta',\n 'IBM Plex Mono': 'Mukta',\n 'Space Mono': 'Mukta',\n};\n\n/** Pick the best Devanagari family for a given Latin font (returns FONT_FALLBACK_DEVANAGARI as last resort). */\nexport function resolveDevanagariSibling(latinFont: string | null | undefined): string {\n if (!latinFont) return FONT_FALLBACK_DEVANAGARI;\n return LATIN_TO_DEVANAGARI[latinFont] || FONT_FALLBACK_DEVANAGARI;\n}\n"],"names":[],"mappings":"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"}
|