{
  "version": 3,
  "sources": ["../src/locale.ts", "../src/debug.ts", "../src/config.ts", "../src/appearance.ts", "../src/headless/store.ts", "../src/headless/quote-view.ts", "../src/core.ts", "../src/element.ts", "../src/fiscal/tax-id.ts", "../src/fiscal/sat.ts", "../src/fiscal/receptor.ts", "../src/headless/fiscal-form.ts", "../src/fiscal/messages.ts", "../src/fiscal-element.ts", "../src/api.ts", "../src/engine.ts", "../src/index.ts"],
  "sourcesContent": ["// Idiomas de Cord Elements: los mismos cinco de la app de Cord.\nexport type CordLocale = 'es' | 'en' | 'pt' | 'fr' | 'de';\n\n/** Etiqueta de Intl con la que se formatean importes y porcentajes en cada idioma. */\nexport const INTL_TAG: Record<CordLocale, string> = { es: 'es-MX', en: 'en-US', pt: 'pt-BR', fr: 'fr-FR', de: 'de-DE' };\n\n/** 'pt-BR' \u2192 'pt'. Sin idioma, el default documentado ('es'); uno que no se reconoce cae a ingl\u00E9s. */\nexport function cordLocale(value?: string | null): CordLocale {\n    const base = String(value ?? '').trim().toLowerCase().split(/[-_]/)[0];\n    if (!base) return 'es';\n    return Object.prototype.hasOwnProperty.call(INTL_TAG, base) ? (base as CordLocale) : 'en';\n}\n", "// Barra de depuraci\u00F3n de Cord Elements (debug: true). Muestra en tu sitio lo que\n// pasa entre tu p\u00E1gina, el iframe y la API: eventos, peticiones con su request\n// id y avisos de configuraci\u00F3n. Vive en un Shadow DOM, solo usa textContent (nada\n// de HTML inyectado) y no se dibuja con una llave en vivo.\nimport { cordLocale, type CordLocale } from './locale.js';\n\nexport type DebugKind = 'event' | 'request' | 'warning' | 'error';\n\ninterface Entry { at: Date; kind: DebugKind; summary: string; detail?: string }\n\nconst MAX = 80;\nconst entries: Entry[] = [];\nconst listeners = new Set<() => void>();\nlet enabled = false;\n\nconst TEXT = {\n    es: {\n        title: 'Cord \u00B7 modo prueba', label: 'Depuraci\u00F3n de Cord', clear: 'Limpiar', hide: 'Ocultar', show: 'Mostrar',\n        empty: 'Sin actividad todav\u00EDa.',\n        liveKey: '[Cord] debug est\u00E1 activo con una llave en vivo: la barra de depuraci\u00F3n solo se muestra con pk_test_.',\n        testKeyHost: (host: string) => `Llave de prueba en ${host}: las cotizaciones van a la sandbox, no a tu cuenta real.`,\n        appearanceDropped: (keys: string) => `appearance descartado: ${keys}`,\n        appearanceDroppedConsole: (keys: string) => `[Cord] appearance: Cord descarta estos valores por no ser v\u00E1lidos: ${keys}.`,\n        appearanceTooBig: 'appearance excede el l\u00EDmite de tama\u00F1o y se ignora',\n        appearanceTooBigConsole: (size: number, max: number) => `[Cord] appearance pesa ${size} bytes; el l\u00EDmite es ${max} y Cord lo ignora completo.`,\n    },\n    en: {\n        title: 'Cord \u00B7 test mode', label: 'Cord debugging', clear: 'Clear', hide: 'Hide', show: 'Show',\n        empty: 'No activity yet.',\n        liveKey: '[Cord] debug is on with a live key: the debug bar only shows with pk_test_.',\n        testKeyHost: (host: string) => `Test key on ${host}: quotes go to the sandbox, not your real account.`,\n        appearanceDropped: (keys: string) => `appearance dropped: ${keys}`,\n        appearanceDroppedConsole: (keys: string) => `[Cord] appearance: Cord drops these values because they are not valid: ${keys}.`,\n        appearanceTooBig: 'appearance exceeds the size limit and is ignored',\n        appearanceTooBigConsole: (size: number, max: number) => `[Cord] appearance is ${size} bytes; the limit is ${max} and Cord ignores all of it.`,\n    },\n    pt: {\n        title: 'Cord \u00B7 modo de teste', label: 'Depura\u00E7\u00E3o do Cord', clear: 'Limpar', hide: 'Ocultar', show: 'Mostrar',\n        empty: 'Nenhuma atividade ainda.',\n        liveKey: '[Cord] O debug est\u00E1 ativo com uma chave de produ\u00E7\u00E3o: a barra de depura\u00E7\u00E3o s\u00F3 aparece com pk_test_.',\n        testKeyHost: (host: string) => `Chave de teste em ${host}: os or\u00E7amentos v\u00E3o para o ambiente de teste, n\u00E3o para a sua conta real.`,\n        appearanceDropped: (keys: string) => `appearance descartado: ${keys}`,\n        appearanceDroppedConsole: (keys: string) => `[Cord] appearance: o Cord descarta estes valores por n\u00E3o serem v\u00E1lidos: ${keys}.`,\n        appearanceTooBig: 'appearance excede o limite de tamanho e \u00E9 ignorado',\n        appearanceTooBigConsole: (size: number, max: number) => `[Cord] appearance tem ${size} bytes; o limite \u00E9 ${max} e o Cord o ignora por completo.`,\n    },\n    fr: {\n        title: 'Cord \u00B7 mode test', label: 'D\u00E9bogage de Cord', clear: 'Effacer', hide: 'Masquer', show: 'Afficher',\n        empty: 'Aucune activit\u00E9 pour le moment.',\n        liveKey: '[Cord] debug est actif avec une cl\u00E9 live : la barre de d\u00E9bogage ne s\u2019affiche qu\u2019avec pk_test_.',\n        testKeyHost: (host: string) => `Cl\u00E9 de test sur ${host} : les devis vont dans l\u2019environnement de test, pas dans votre compte r\u00E9el.`,\n        appearanceDropped: (keys: string) => `appearance ignor\u00E9 : ${keys}`,\n        appearanceDroppedConsole: (keys: string) => `[Cord] appearance : Cord ignore ces valeurs, car elles ne sont pas valides : ${keys}.`,\n        appearanceTooBig: 'appearance d\u00E9passe la taille maximale et est ignor\u00E9',\n        appearanceTooBigConsole: (size: number, max: number) => `[Cord] appearance p\u00E8se ${size} octets ; la limite est de ${max} et Cord l\u2019ignore enti\u00E8rement.`,\n    },\n    de: {\n        title: 'Cord \u00B7 Testmodus', label: 'Cord-Debugging', clear: 'Leeren', hide: 'Ausblenden', show: 'Einblenden',\n        empty: 'Noch keine Aktivit\u00E4t.',\n        liveKey: '[Cord] debug ist mit einem Live-Schl\u00FCssel aktiv: Die Debug-Leiste erscheint nur mit pk_test_.',\n        testKeyHost: (host: string) => `Testschl\u00FCssel auf ${host}: Angebote gehen in die Testumgebung, nicht in Ihr echtes Konto.`,\n        appearanceDropped: (keys: string) => `appearance verworfen: ${keys}`,\n        appearanceDroppedConsole: (keys: string) => `[Cord] appearance: Cord verwirft diese Werte, weil sie ung\u00FCltig sind: ${keys}.`,\n        appearanceTooBig: 'appearance \u00FCberschreitet die Gr\u00F6\u00DFenbegrenzung und wird ignoriert',\n        appearanceTooBigConsole: (size: number, max: number) => `[Cord] appearance ist ${size} Bytes gro\u00DF; das Limit liegt bei ${max}, Cord ignoriert es vollst\u00E4ndig.`,\n    },\n};\n\nlet localeOverride: CordLocale | null = null;\n\n/** Idioma de la barra. Sin uno expl\u00EDcito (el locale del Provider) sigue el lang de tu p\u00E1gina. */\nexport function setDebugLocale(locale: CordLocale): void {\n    localeOverride = cordLocale(locale);\n    for (const l of listeners) l();\n}\n\nexport function debugText() {\n    if (localeOverride) return TEXT[localeOverride];\n    return TEXT[cordLocale(typeof document !== 'undefined' ? document.documentElement.lang : '')];\n}\n\nexport function isDebugEnabled(): boolean {\n    return enabled;\n}\n\n/** Activa la barra. Con una pk_live_ solo avisa por consola: no se depura producci\u00F3n en la cara del cliente. */\nexport function enableDebug(publishableKey?: string): void {\n    if (typeof document === 'undefined') return;\n    if (publishableKey?.startsWith('pk_live_')) {\n        console.warn(debugText().liveKey);\n        return;\n    }\n    // Sin llave con qu\u00E9 decidir (Web Component, embed.js): solo en tu m\u00E1quina o\n    // pidi\u00E9ndolo en la URL, para que un atributo olvidado no la muestre a tus clientes.\n    if (!publishableKey && typeof location !== 'undefined') {\n        const local = /^(localhost|127\\.0\\.0\\.1|\\[::1\\])$|\\.localhost$/.test(location.hostname);\n        if (!local && !new URLSearchParams(location.search).has('cord_debug')) return;\n    }\n    enabled = true;\n    mountPanel();\n}\n\nexport function debugLog(kind: DebugKind, summary: string, detail?: unknown): void {\n    if (!enabled) return;\n    entries.unshift({ at: new Date(), kind, summary: summary.slice(0, 300), detail: detail === undefined ? undefined : safeJson(detail) });\n    if (entries.length > MAX) entries.length = MAX;\n    for (const l of listeners) l();\n}\n\nfunction safeJson(v: unknown): string {\n    try { return JSON.stringify(v, null, 2).slice(0, 4000); } catch { return String(v); }\n}\n\nconst CSS = `\n:host{all:initial;position:fixed;right:16px;bottom:16px;z-index:2147483646;font:12px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;color:#0a192f}\n.panel{width:min(420px,calc(100vw - 32px));max-height:min(60vh,520px);display:flex;flex-direction:column;background:#fff;border-radius:16px;box-shadow:0 12px 40px rgba(10,25,47,.18),0 2px 8px rgba(10,25,47,.08);overflow:hidden}\n.head{display:flex;align-items:center;gap:8px;padding:10px 12px;background:#0a192f;color:#fff}\n.head strong{flex:1;font-weight:600}\nbutton{all:unset;cursor:pointer;padding:4px 8px;border-radius:8px;background:rgba(255,255,255,.12);color:#fff}\nbutton:focus-visible{outline:2px solid #fff}\n.list{overflow:auto;padding:4px 0}\n.row{padding:6px 12px;border-bottom:1px solid rgba(10,25,47,.06)}\n.meta{display:flex;gap:8px;color:#6b7280}\n.k-error .sum,.k-warning .sum{color:#8e2a1f}\npre{margin:4px 0 0;white-space:pre-wrap;word-break:break-word;color:#374151;max-height:160px;overflow:auto}\n.closed .list{display:none}\n.empty{padding:12px;color:#6b7280}\n`;\n\nfunction mountPanel() {\n    if (document.querySelector('cord-debug-panel') || typeof customElements === 'undefined') return;\n    if (!customElements.get('cord-debug-panel')) {\n        customElements.define('cord-debug-panel', class extends HTMLElement {\n            connectedCallback() {\n                const root = this.attachShadow({ mode: 'open' });\n                const style = document.createElement('style');\n                style.textContent = CSS;\n                const panel = document.createElement('div');\n                panel.className = 'panel';\n                panel.setAttribute('role', 'log');\n                panel.setAttribute('aria-label', debugText().label);\n                const head = document.createElement('div');\n                head.className = 'head';\n                const title = document.createElement('strong');\n                const clear = document.createElement('button');\n                clear.type = 'button';\n                const toggle = document.createElement('button');\n                toggle.type = 'button';\n                const labels = () => {\n                    const t = debugText();\n                    title.textContent = t.title;\n                    clear.textContent = t.clear;\n                    toggle.textContent = panel.classList.contains('closed') ? t.show : t.hide;\n                    panel.setAttribute('aria-label', t.label);\n                };\n                head.append(title, clear, toggle);\n                const list = document.createElement('div');\n                list.className = 'list';\n                panel.append(head, list);\n                root.append(style, panel);\n\n                const render = () => {\n                    labels();\n                    list.textContent = '';\n                    if (!entries.length) {\n                        const empty = document.createElement('div');\n                        empty.className = 'empty';\n                        empty.textContent = debugText().empty;\n                        list.append(empty);\n                        return;\n                    }\n                    for (const e of entries) {\n                        const row = document.createElement('div');\n                        row.className = `row k-${e.kind}`;\n                        const meta = document.createElement('div');\n                        meta.className = 'meta';\n                        meta.textContent = `${e.at.toLocaleTimeString()} \u00B7 ${e.kind}`;\n                        const sum = document.createElement('div');\n                        sum.className = 'sum';\n                        sum.textContent = e.summary;\n                        row.append(meta, sum);\n                        if (e.detail) {\n                            const pre = document.createElement('pre');\n                            pre.textContent = e.detail;\n                            row.append(pre);\n                        }\n                        list.append(row);\n                    }\n                };\n                clear.addEventListener('click', () => { entries.length = 0; render(); });\n                toggle.addEventListener('click', () => {\n                    panel.classList.toggle('closed');\n                    labels();\n                });\n                listeners.add(render);\n                render();\n            }\n        });\n    }\n    document.body.appendChild(document.createElement('cord-debug-panel'));\n}\n", "// Configuraci\u00F3n global de @flouviahq/elements \u2014 an\u00E1logo a `loadStripe`/Stripe.js:\n// un singleton de m\u00F3dulo para fijar defaults (baseUrl de self-host/staging,\n// appearance) sin necesidad de un <CordProvider> (Vue, Web Component, vanilla).\n//\n// Precedencia de resoluci\u00F3n en TODO el SDK: props del componente > valor del\n// <CordProvider> (si existe) > configureCord() > default embebido.\nimport type { CordAppearance } from './types.js';\nimport { enableDebug } from './debug.js';\n\nexport interface CordGlobalConfig {\n    /** Origen de Cord. Default: https://cordhq.app (self-host/staging). */\n    baseUrl?: string;\n    /** Appearance aplicada cuando ni el componente ni el Provider la traen. */\n    appearance?: CordAppearance;\n    /** Llave publishable por default (ver CordProviderProps para el uso normal). */\n    publishableKey?: string;\n    /** Muestra la barra de depuraci\u00F3n (solo con llaves de prueba). */\n    debug?: boolean;\n}\n\nconst DEFAULT_ORIGIN = 'https://cordhq.app';\n\nlet globalConfig: CordGlobalConfig = {};\n\n/** Fija defaults globales del SDK. Llamar una vez, antes de montar cualquier componente. */\nexport function configureCord(config: CordGlobalConfig): void {\n    globalConfig = { ...globalConfig, ...config };\n    if (config.debug) enableDebug(globalConfig.publishableKey);\n}\n\n/** Config actual (uso interno del SDK; no se garantiza estable entre versiones). */\nexport function getCordConfig(): CordGlobalConfig {\n    return globalConfig;\n}\n\n/** Origen de Cord sin trailing slash, aplicando la precedencia est\u00E1ndar del SDK. */\nexport function resolveOrigin(explicit?: string): string {\n    return (explicit || globalConfig.baseUrl || DEFAULT_ORIGIN).replace(/\\/$/, '');\n}\n\n/** Base de la API p\u00FAblica v1 (origen + /api/v1), o la expl\u00EDcita si se provee completa. */\nexport function resolveApiBase(explicit?: string): string {\n    if (explicit) return explicit.replace(/\\/$/, '');\n    return `${resolveOrigin()}/api/v1`;\n}\n", "// Validador \u00FAnico del Appearance API. Lo usan el servidor (/embed/[token]) y el\n// SDK: todo valor que termina en CSS pasa por aqu\u00ED, con listas cerradas de\n// claves, selectores y propiedades, y una gram\u00E1tica por tipo. Lo que no encaja\n// se descarta y se reporta; nunca se copia texto libre a una hoja de estilos.\n\nexport type AppearanceTheme = 'light' | 'dark' | 'auto' | 'flat';\n\ntype ValueKind = 'color' | 'length' | 'fontFamily' | 'fontWeight' | 'shadow' | 'textTransform' | 'borderStyle' | 'opacity' | 'spacing';\n\n/** Variables p\u00FAblicas. Cada una la consume el embed y/o el Builder nativo. */\nconst VARIABLES: Record<string, ValueKind> = {\n    colorPrimary: 'color',\n    colorOnPrimary: 'color',\n    colorBackground: 'color',\n    colorSurface: 'color',\n    colorText: 'color',\n    colorTextSecondary: 'color',\n    colorTextPlaceholder: 'color',\n    colorBorder: 'color',\n    colorDanger: 'color',\n    colorSuccess: 'color',\n    colorInput: 'color',\n    colorInputText: 'color',\n    colorInputBorder: 'color',\n    colorFocus: 'color',\n    fontFamily: 'fontFamily',\n    fontSize: 'length',\n    fontWeightBold: 'fontWeight',\n    borderRadius: 'length',\n    borderRadiusButton: 'length',\n    borderRadiusInput: 'length',\n    spacingCard: 'spacing',\n    shadowCard: 'shadow',\n};\n\nexport const APPEARANCE_VARIABLES = Object.keys(VARIABLES);\n\n/** Selectores p\u00FAblicos de `rules`. El servidor los traduce a su markup interno. */\nexport const APPEARANCE_SELECTORS = [\n    'Card', 'Header', 'Total', 'Table', 'Row', 'SummaryRow', 'Notes',\n    'Button', 'Button:hover', 'ButtonSecondary', 'ButtonSecondary:hover',\n    'Input', 'Input:focus', 'Chat', 'Bubble', 'Bubble--mine',\n] as const;\nexport type AppearanceSelector = (typeof APPEARANCE_SELECTORS)[number];\n\nconst RULE_PROPERTIES: Record<string, ValueKind> = {\n    color: 'color',\n    'background-color': 'color',\n    'border-color': 'color',\n    'border-width': 'length',\n    'border-style': 'borderStyle',\n    'border-radius': 'length',\n    'font-size': 'length',\n    'font-weight': 'fontWeight',\n    'letter-spacing': 'length',\n    'text-transform': 'textTransform',\n    padding: 'spacing',\n    'box-shadow': 'shadow',\n    opacity: 'opacity',\n};\n\nexport const APPEARANCE_RULE_PROPERTIES = Object.keys(RULE_PROPERTIES);\n\nconst FONT_HOSTS = ['fonts.googleapis.com', 'fonts.bunny.net'];\nconst MAX_FONTS = 4;\nconst MAX_RULES = 40;\nexport const MAX_APPEARANCE_BYTES = 8192;\n\nconst COLOR = /^(#[0-9a-f]{3,8}|(rgba?|hsla?|oklch|oklab|lab|lch)\\([0-9a-z.,%/\\s+-]{1,60}\\)|[a-z]{3,20})$/i;\nconst LENGTH = /^(0|-?\\d{1,3}(\\.\\d{1,3})?(px|rem|em|%))$/;\nconst FONT_FAMILY = /^[a-z0-9 ,'\"-]{1,120}$/i;\nconst SPACING = /^(0|\\d{1,3}(\\.\\d{1,3})?(px|rem|em))( (0|\\d{1,3}(\\.\\d{1,3})?(px|rem|em))){0,3}$/;\nconst FORBIDDEN = /\\\\|@|javascript:|expression\\(|url\\(|!important|;|\\{|\\}|<|>/i;\n\nfunction validValue(kind: ValueKind, value: string): boolean {\n    if (FORBIDDEN.test(value)) return false;\n    switch (kind) {\n        case 'color': return COLOR.test(value);\n        case 'length': return LENGTH.test(value);\n        case 'fontFamily': return FONT_FAMILY.test(value);\n        case 'fontWeight': return /^(normal|bold|[1-9]00)$/.test(value);\n        case 'shadow': return value === 'none' || value === 'default';\n        case 'textTransform': return /^(none|uppercase|lowercase|capitalize)$/.test(value);\n        case 'borderStyle': return /^(none|solid|dashed|dotted)$/.test(value);\n        case 'opacity': return /^(0(\\.\\d{1,3})?|1(\\.0{1,3})?)$/.test(value);\n        case 'spacing': return SPACING.test(value);\n    }\n}\n\nfunction fontUrl(src: unknown): string | null {\n    if (typeof src !== 'string' || src.length > 512) return null;\n    let u: URL;\n    try { u = new URL(src); } catch { return null; }\n    if (u.protocol !== 'https:' || !FONT_HOSTS.includes(u.hostname)) return null;\n    if (!/^\\/css2?$/.test(u.pathname) || u.username || u.password || u.hash) return null;\n    const href = u.href;\n    return /['\"()\\\\\\s]/.test(href) ? null : href;\n}\n\nexport function cssVariableName(key: string): string {\n    return `--cord-${key.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase())}`;\n}\n\nexport interface AppearanceLayout {\n    /** Menos aire en la tarjeta del embed. */\n    compact: boolean;\n    hideChat: boolean;\n    hideNotes: boolean;\n}\n\nexport interface SanitizedAppearance {\n    theme: AppearanceTheme;\n    variables: Array<[string, string]>;\n    fontImports: string[];\n    rules: Array<{ selector: AppearanceSelector; declarations: Array<[string, string]> }>;\n    layout: AppearanceLayout;\n    rejected: string[];\n}\n\nexport function sanitizeAppearance(input: unknown): SanitizedAppearance {\n    const out: SanitizedAppearance = {\n        theme: 'light', variables: [], fontImports: [], rules: [],\n        layout: { compact: false, hideChat: false, hideNotes: false }, rejected: [],\n    };\n    if (!input || typeof input !== 'object') return out;\n    const a = input as Record<string, any>;\n\n    if (a.theme === 'dark' || a.theme === 'light' || a.theme === 'auto' || a.theme === 'flat') out.theme = a.theme;\n    else if (a.theme === 'night') out.theme = 'dark';\n    else if (a.theme !== undefined) out.rejected.push('theme');\n\n    let fontFamily: string | undefined;\n    if (a.variables && typeof a.variables === 'object') {\n        for (const [key, raw] of Object.entries(a.variables as Record<string, unknown>)) {\n            const kind = VARIABLES[key];\n            const value = typeof raw === 'string' ? raw.trim() : '';\n            if (!kind || !value || !validValue(kind, value)) {\n                if (raw !== undefined) out.rejected.push(`variables.${key}`);\n                continue;\n            }\n            if (key === 'fontFamily') fontFamily = value;\n            else out.variables.push([cssVariableName(key), value]);\n        }\n    }\n\n    if (Array.isArray(a.fonts)) {\n        a.fonts.slice(0, MAX_FONTS).forEach((f: any, i: number) => {\n            const href = fontUrl(f?.cssSrc);\n            if (href) out.fontImports.push(href);\n            else out.rejected.push(`fonts.${i}`);\n        });\n        if (!fontFamily && out.fontImports[0]) {\n            const fam = new URL(out.fontImports[0]).searchParams.get('family')?.split(':')[0];\n            if (fam && FONT_FAMILY.test(fam)) fontFamily = fam;\n        }\n    }\n    if (fontFamily) out.variables.push(['--cord-font-family', fontFamily]);\n\n    if (a.rules && typeof a.rules === 'object') {\n        for (const [selector, decls] of Object.entries(a.rules as Record<string, unknown>).slice(0, MAX_RULES)) {\n            if (!(APPEARANCE_SELECTORS as readonly string[]).includes(selector) || !decls || typeof decls !== 'object') {\n                out.rejected.push(`rules.${selector}`);\n                continue;\n            }\n            const declarations: Array<[string, string]> = [];\n            for (const [prop, raw] of Object.entries(decls as Record<string, unknown>)) {\n                const kind = RULE_PROPERTIES[prop];\n                const value = typeof raw === 'string' ? raw.trim() : typeof raw === 'number' ? String(raw) : '';\n                if (!kind || !value || !validValue(kind, value)) {\n                    out.rejected.push(`rules.${selector}.${prop}`);\n                    continue;\n                }\n                if (kind === 'shadow' && value === 'default') continue;\n                declarations.push([prop, value]);\n            }\n            if (declarations.length) out.rules.push({ selector: selector as AppearanceSelector, declarations });\n        }\n    }\n\n    if (a.layout && typeof a.layout === 'object') {\n        for (const key of ['compact', 'hideChat', 'hideNotes'] as const) {\n            if (a.layout[key] === true) out.layout[key] = true;\n            else if (a.layout[key] !== undefined && a.layout[key] !== false) out.rejected.push(`layout.${key}`);\n        }\n    }\n\n    return out;\n}\n\n/** Paleta oscura completa: el modo oscuro cambia la tarjeta entera, no solo el texto. */\nexport const DARK_PALETTE: Array<[string, string]> = [\n    ['--cord-color-background', '#111827'],\n    ['--cord-color-surface', '#1f2937'],\n    ['--cord-color-text', '#f3f4f6'],\n    ['--cord-color-text-secondary', '#d1d5db'],\n    ['--cord-color-text-placeholder', '#9ca3af'],\n    ['--cord-color-border', 'rgba(255,255,255,0.12)'],\n    ['--cord-color-input', '#1f2937'],\n    ['--cord-color-input-text', '#f3f4f6'],\n    ['--cord-color-input-border', 'rgba(255,255,255,0.18)'],\n    ['--cord-color-focus', 'rgba(255,255,255,0.35)'],\n];\n\nconst FLAT_PRESET: Array<[string, string]> = [\n    ['--cord-shadow-card', 'none'],\n    ['--cord-color-border', 'rgba(10,25,47,0.12)'],\n];\n\n/**\n * Variables como CSS sobre `selector`. El tema va antes que las variables del\n * usuario, que siempre ganan. `shadowCard: default` se traduce a \"sin\n * variable\" para conservar la sombra de Cord.\n */\nexport function appearanceToCss(a: SanitizedAppearance, selector = ':root'): string {\n    const block = (vars: Array<[string, string]>) => `${selector} {\\n${vars.map(([k, v]) => `  ${k}: ${v};`).join('\\n')}\\n}\\n`;\n    let css = a.fontImports.map((href) => `@import url('${href}');\\n`).join('');\n    if (a.theme === 'dark') css += block(DARK_PALETTE);\n    if (a.theme === 'auto') css += `@media (prefers-color-scheme: dark) {\\n${block(DARK_PALETTE)}}\\n`;\n    if (a.theme === 'flat') css += block(FLAT_PRESET);\n    const vars = a.variables.filter(([k, v]) => !(k === '--cord-shadow-card' && v === 'default'));\n    if (a.theme === 'dark' || a.theme === 'auto') vars.push(['color-scheme', a.theme === 'dark' ? 'dark' : 'light dark']);\n    if (vars.length) css += block(vars);\n    return css;\n}\n", "// Store observable m\u00EDnimo. Es la pieza que permite que el mismo estado alimente\n// a React (useSyncExternalStore), Vue (shallowRef), un Web Component o tu propia UI.\n\nexport interface ReadableStore<T> {\n    get(): T;\n    subscribe(listener: (state: T) => void): () => void;\n}\n\nexport interface Store<T> extends ReadableStore<T> {\n    set(next: T | ((prev: T) => T)): void;\n}\n\nexport function createStore<T>(initial: T): Store<T> {\n    let state = initial;\n    const listeners = new Set<(state: T) => void>();\n    return {\n        get: () => state,\n        set(next) {\n            const value = typeof next === 'function' ? (next as (prev: T) => T)(state) : next;\n            if (Object.is(value, state)) return;\n            state = value;\n            for (const l of [...listeners]) l(state);\n        },\n        subscribe(listener) {\n            listeners.add(listener);\n            return () => { listeners.delete(listener); };\n        },\n    };\n}\n", "// Estado en vivo de una cotizaci\u00F3n embebida. El iframe ya est\u00E1 suscrito al\n// stream de Cord dentro de su propio origen; aqu\u00ED solo se reduce lo que relaya\n// por postMessage. El stream nunca se expone a otro origen: es una credencial.\nimport type { CordEvent } from '../types.js';\n\nexport interface QuoteViewState {\n    ready: boolean;\n    /** Solo con dominios permitidos configurados; en solo lectura llega null. */\n    status: string | null;\n    folio: string | null;\n    moneda: string | null;\n    total: number | null;\n    approved: boolean;\n    rejected: boolean;\n    paid: boolean;\n    signedBy: string | null;\n    lastEvent: CordEvent['type'] | null;\n}\n\nexport const INITIAL_QUOTE_VIEW: QuoteViewState = {\n    ready: false, status: null, folio: null, moneda: null, total: null,\n    approved: false, rejected: false, paid: false, signedBy: null, lastEvent: null,\n};\n\nconst PAID = new Set(['paid', 'invoiced']);\n\nexport function reduceQuoteView(state: QuoteViewState, event: CordEvent): QuoteViewState {\n    const next: QuoteViewState = { ...state, lastEvent: event.type };\n    switch (event.type) {\n        case 'cord:ready': {\n            const d = event.detail ?? {};\n            next.ready = true;\n            if (typeof d.status === 'string') next.status = d.status;\n            if (typeof d.folio === 'string') next.folio = d.folio;\n            if (typeof d.moneda === 'string') next.moneda = d.moneda;\n            if (typeof d.total === 'number') next.total = d.total;\n            break;\n        }\n        case 'cord:updated':\n            if (typeof event.detail?.total === 'number') next.total = event.detail.total;\n            if (typeof event.detail?.moneda === 'string') next.moneda = event.detail.moneda;\n            break;\n        case 'cord:status_changed':\n            if (typeof event.detail?.status === 'string') next.status = event.detail.status;\n            break;\n        case 'cord:approved':\n        case 'cord:signed':\n            next.approved = true;\n            next.status = next.status === 'paid' ? next.status : 'approved';\n            if (typeof event.detail?.signed_by === 'string') next.signedBy = event.detail.signed_by;\n            break;\n        case 'cord:rejected':\n            next.rejected = true;\n            next.status = 'rejected';\n            break;\n        case 'cord:paid':\n            next.status = 'paid';\n            break;\n    }\n    next.approved = next.approved || next.status === 'approved' || PAID.has(next.status ?? '');\n    next.rejected = next.rejected || next.status === 'rejected';\n    next.paid = PAID.has(next.status ?? '');\n    return next;\n}\n", "// N\u00FAcleo agn\u00F3stico de framework de @flouviahq/elements: monta el cotizador (iframe a\n// /embed/{token}) con skeleton, auto-altura (postMessage) y relay de eventos.\n// Es la MISMA mec\u00E1nica que public/embed.js, pero como m\u00F3dulo: cada instancia tiene\n// su propio listener (scoped por contentWindow) y se limpia con destroy().\nimport type { CordElementOptions, CordController, CordEvent } from './types.js';\nimport { resolveOrigin } from './config.js';\nimport { sanitizeAppearance, MAX_APPEARANCE_BYTES } from './appearance.js';\nimport { createStore } from './headless/store.js';\nimport { INITIAL_QUOTE_VIEW, reduceQuoteView } from './headless/quote-view.js';\nimport { debugLog, debugText } from './debug.js';\nimport { cordLocale, type CordLocale } from './locale.js';\n\nconst STYLE_ID = 'cord-elements-style';\n\n// Nombre accesible del iframe en el idioma de la p\u00E1gina anfitriona.\nconst FRAME_TITLE: Record<CordLocale, [quote: string, invoice: string]> = {\n    es: ['Cotizaci\u00F3n', 'Factura'], en: ['Quote', 'Invoice'], pt: ['Or\u00E7amento', 'Fatura'], fr: ['Devis', 'Facture'], de: ['Angebot', 'Rechnung'],\n};\n\nconst REDUCED =\n    typeof window !== 'undefined' &&\n    typeof window.matchMedia === 'function' &&\n    window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n/** Eventos que re-emitimos. El catch-all (onEvent) recibe todos. */\nconst RELAYED = ['cord:ready', 'cord:viewed', 'cord:approved', 'cord:signed', 'cord:rejected', 'cord:message', 'cord:item_comment', 'cord:pay', 'cord:updated', 'cord:status_changed', 'cord:paid'] as const;\n\nexport const EMBED_CSS = (() => {\n    const css =\n        '.cord-embed{position:relative;width:100%;}' +\n        '.cord-embed iframe{width:100%;border:0;display:block;background:transparent;' +\n        'opacity:0;transition:opacity .35s ease,height .2s ease;}' +\n        '.cord-embed.is-ready iframe{opacity:1;}' +\n        '.cord-embed-skeleton{position:absolute;inset:0;border-radius:18px;overflow:hidden;' +\n        'background:#fcfcfc;box-shadow:inset 0 0 0 1px rgba(10,25,47,.06);}' +\n        '.cord-embed.is-ready .cord-embed-skeleton{opacity:0;transition:opacity .3s ease;pointer-events:none;}' +\n        '.cord-embed-shimmer{position:absolute;inset:0;background:linear-gradient(100deg,' +\n        'transparent 20%,rgba(10,25,47,.05) 40%,rgba(10,25,47,.07) 50%,rgba(10,25,47,.05) 60%,transparent 80%);' +\n        'background-size:200% 100%;' + (REDUCED ? '' : 'animation:cord-shimmer 1.4s infinite linear;') + '}' +\n        '@keyframes cord-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}';\n    return css;\n})();\n\n// En el documento: un <style> compartido. En un Shadow DOM: los estilos viven\n// dentro de la ra\u00EDz y no tocan la p\u00E1gina anfitriona.\nfunction injectStyles(root: Document | ShadowRoot) {\n    if (typeof document === 'undefined') return;\n    if (root instanceof Document || !('host' in root)) {\n        if (document.getElementById(STYLE_ID)) return;\n        const st = document.createElement('style');\n        st.id = STYLE_ID;\n        st.textContent = EMBED_CSS;\n        (document.head || document.documentElement).appendChild(st);\n        return;\n    }\n    const shadow = root as ShadowRoot;\n    if (shadow.querySelector(`style[data-cord=\"${STYLE_ID}\"]`)) return;\n    try {\n        if ('adoptedStyleSheets' in shadow && typeof CSSStyleSheet !== 'undefined') {\n            const sheet = new CSSStyleSheet();\n            sheet.replaceSync(EMBED_CSS);\n            shadow.adoptedStyleSheets = [...shadow.adoptedStyleSheets, sheet];\n            return;\n        }\n    } catch { /* cae al <style> */ }\n    const st = document.createElement('style');\n    st.dataset.cord = STYLE_ID;\n    st.textContent = EMBED_CSS;\n    shadow.appendChild(st);\n}\n\nconst MAX_HEIGHT = 20000;\nconst isDev = () => typeof process === 'undefined' || process.env?.NODE_ENV !== 'production';\n\n/**\n * Monta el cotizador dentro de `target`. Devuelve un controller con destroy().\n */\nexport function mountCotizador(target: HTMLElement, opts: CordElementOptions, styleRoot?: Document | ShadowRoot): CordController {\n    if (!target) throw new Error('[Cord] target inv\u00E1lido');\n    if (!opts || !opts.token) throw new Error('[Cord] falta opts.token');\n    if (opts.appearance && isDev()) {\n        const { rejected } = sanitizeAppearance(opts.appearance);\n        if (rejected.length) {\n            console.warn(debugText().appearanceDroppedConsole(rejected.join(', ')));\n            debugLog('warning', debugText().appearanceDropped(rejected.join(', ')));\n        }\n    }\n    const state = createStore(INITIAL_QUOTE_VIEW);\n\n    const base = resolveOrigin(opts.baseUrl);\n    const origin = (() => { try { return new URL(base).origin; } catch { return base; } })();\n    const minH = typeof opts.minHeight === 'number' && opts.minHeight > 0 ? opts.minHeight : 420;\n\n    injectStyles(styleRoot ?? (typeof document !== 'undefined' ? document : (undefined as any)));\n    target.classList.add('cord-embed');\n\n    const skeleton = document.createElement('div');\n    skeleton.className = 'cord-embed-skeleton';\n    skeleton.setAttribute('part', 'skeleton');\n    skeleton.innerHTML = '<div class=\"cord-embed-shimmer\"></div>';\n    target.appendChild(skeleton);\n\n    // `parentOrigin` deja que /embed/[token] use un targetOrigin real en su\n    // postMessage (en vez de '*' siempre) cuando el origen matchea la\n    // allowlist de orgs.embed_domains \u2014 mismo gate que ya protege frame-ancestors.\n    const params = new URLSearchParams();\n    const appearanceJson = opts.appearance ? JSON.stringify(opts.appearance) : '';\n    if (appearanceJson.length > MAX_APPEARANCE_BYTES) {\n        console.warn(debugText().appearanceTooBigConsole(appearanceJson.length, MAX_APPEARANCE_BYTES));\n        debugLog('error', debugText().appearanceTooBig);\n    } else if (appearanceJson) params.set('appearance', appearanceJson);\n    if (typeof window !== 'undefined' && window.location?.origin) params.set('parentOrigin', window.location.origin);\n    const query = params.toString();\n\n    const iframe = document.createElement('iframe');\n    const invoice = opts.document === 'invoice';\n    iframe.src = base + (invoice ? '/embed/i/' : '/embed/') + encodeURIComponent(opts.token) + (query ? '?' + query : '');\n    iframe.title = FRAME_TITLE[cordLocale(document.documentElement.lang)][invoice ? 1 : 0];\n    iframe.setAttribute('loading', 'lazy');\n    iframe.setAttribute('referrerpolicy', 'strict-origin-when-cross-origin');\n    iframe.setAttribute('allow', 'payment; clipboard-write');\n    iframe.setAttribute('part', 'frame');\n    iframe.style.height = minH + 'px';\n    // El outer <iframe> refleja el theme (chrome del elemento \u2014 scrollbar/UA\n    // widgets DESDE afuera); el contenido de adentro lo decide /embed/[token]\n    // mismo con la misma appearance (ver theme en el query param arriba).\n    iframe.style.colorScheme = opts.appearance?.theme === 'dark' ? 'dark'\n        : opts.appearance?.theme === 'auto' ? 'light dark' : 'light';\n    target.appendChild(iframe);\n\n    let ready = false;\n    const reveal = () => {\n        if (ready) return;\n        ready = true;\n        target.classList.add('is-ready');\n        window.setTimeout(() => { if (skeleton.parentNode) skeleton.parentNode.removeChild(skeleton); }, 400);\n    };\n\n    const onMessage = (ev: MessageEvent) => {\n        if (ev.origin !== origin) return;\n        const data: any = ev.data;\n        if (!data || data.source !== 'cord' || !data.type) return;\n        if (iframe.contentWindow && ev.source !== iframe.contentWindow) return;\n\n        if (data.type === 'cord:resize') {\n            const h = Number(data.height);\n            if (Number.isFinite(h) && h > 0) iframe.style.height = Math.min(MAX_HEIGHT, Math.ceil(h)) + 'px';\n            return;\n        }\n        if (!(RELAYED as readonly string[]).includes(data.type)) return;\n        if (data.type === 'cord:ready') reveal();\n\n        // El payload viaja por postMessage sin garant\u00EDa est\u00E1tica de forma \u2014\n        // se castea a CordEvent (la uni\u00F3n discriminada documentada) en el\n        // \u00FAnico punto donde cruza la frontera no tipada.\n        const evt = { type: data.type, detail: data.detail && typeof data.detail === 'object' ? data.detail : {} } as CordEvent;\n        state.set((prev) => reduceQuoteView(prev, evt));\n        debugLog('event', evt.type, evt.detail);\n        if (opts.onEvent) opts.onEvent(evt);\n        switch (evt.type) {\n            case 'cord:ready':        opts.onReady?.(); break;\n            case 'cord:viewed':       opts.onViewed?.(evt.detail); break;\n            case 'cord:approved':     opts.onApproved?.(evt.detail); break;\n            case 'cord:signed':       opts.onSigned?.(evt.detail); break;\n            case 'cord:rejected':     opts.onRejected?.(evt.detail); break;\n            case 'cord:message':      opts.onMessage?.(evt.detail); break;\n            case 'cord:item_comment': opts.onItemComment?.(evt.detail); break;\n            case 'cord:pay':          opts.onPay?.(evt.detail); break;\n            case 'cord:updated':      opts.onUpdated?.(evt.detail); break;\n            case 'cord:status_changed': opts.onStatusChanged?.(evt.detail); break;\n            case 'cord:paid':         opts.onPaid?.(evt.detail); break;\n        }\n    };\n    window.addEventListener('message', onMessage);\n\n    // Fallback: si no llega 'cord:ready', revela al cargar el iframe.\n    const onLoad = () => window.setTimeout(reveal, 250);\n    iframe.addEventListener('load', onLoad);\n\n    return {\n        el: target,\n        state,\n        destroy() {\n            window.removeEventListener('message', onMessage);\n            iframe.removeEventListener('load', onLoad);\n            if (iframe.parentNode) iframe.parentNode.removeChild(iframe);\n            if (skeleton.parentNode) skeleton.parentNode.removeChild(skeleton);\n            target.classList.remove('cord-embed', 'is-ready');\n        },\n    };\n}\n\nexport { RELAYED };\n", "// Web Components de Cord Elements. Funcionan en HTML plano, Vue, Svelte, Angular,\n// Astro, Laravel o Rails. Viven en un Shadow DOM: sus estilos no tocan tu p\u00E1gina\n// y los tuyos no los rompen; se personalizan con ::part(frame), ::part(skeleton)\n// y las variables --cord-*. La sombra a\u00EDsla estilos, no es una frontera de\n// seguridad: firmar y pagar siguen dentro del iframe de Cord.\n//\n// Eventos: cada `cord:*` del cotizador se re-emite sin prefijo (cord:approved \u2192\n// 'approved'), con bubbles y composed para cruzar la sombra.\nimport { mountCotizador } from './core.js';\nimport type { CordAppearance, CordController } from './types.js';\nimport type { QuoteViewState } from './headless/quote-view.js';\nimport { INITIAL_QUOTE_VIEW } from './headless/quote-view.js';\nimport { getCordConfig } from './config.js';\nimport { enableDebug } from './debug.js';\n\n// `extends HTMLElement` se eval\u00FAa al definir la clase: en Node no existe.\nconst ElementBase: typeof HTMLElement =\n    typeof HTMLElement !== 'undefined' ? HTMLElement : (class {} as unknown as typeof HTMLElement);\n\nconst HOST_CSS = ':host{display:block;position:relative;width:100%}:host([hidden]){display:none}.root{position:relative;width:100%}';\n\nexport class CordQuoteElement extends ElementBase {\n    private controller: CordController | null = null;\n    private unsubscribe: (() => void) | null = null;\n    private root: ShadowRoot | null = null;\n    private container: HTMLDivElement | null = null;\n    private _appearance: CordAppearance | undefined;\n    private _state: QuoteViewState = INITIAL_QUOTE_VIEW;\n    private scheduled = false;\n\n    static get observedAttributes() {\n        return ['token', 'base-url', 'min-height', 'appearance', 'debug'];\n    }\n\n    /** Appearance como objeto (preferible al atributo JSON). */\n    get appearance(): CordAppearance | undefined { return this._appearance; }\n    set appearance(value: CordAppearance | undefined) {\n        this._appearance = value;\n        this.schedule();\n    }\n\n    /** Qu\u00E9 documento monta este elemento. */\n    protected get documentKind(): 'quote' | 'invoice' { return 'quote'; }\n\n    /** Estado en vivo: ready, status, total, approved, paid\u2026 */\n    get state(): QuoteViewState { return this._state; }\n\n    connectedCallback() {\n        if (!this.root) {\n            this.root = this.attachShadow({ mode: 'open' });\n            const style = document.createElement('style');\n            style.textContent = HOST_CSS;\n            this.container = document.createElement('div');\n            this.container.className = 'root';\n            this.container.setAttribute('part', 'root');\n            this.root.append(style, this.container);\n        }\n        this.schedule();\n    }\n\n    disconnectedCallback() {\n        this.teardown();\n    }\n\n    attributeChangedCallback() {\n        if (this.isConnected) this.schedule();\n    }\n\n    // Varios atributos cambian juntos (token + appearance): un solo montaje.\n    private schedule() {\n        if (this.scheduled) return;\n        this.scheduled = true;\n        queueMicrotask(() => {\n            this.scheduled = false;\n            if (this.isConnected) this.render();\n        });\n    }\n\n    private teardown() {\n        this.unsubscribe?.();\n        this.unsubscribe = null;\n        this.controller?.destroy();\n        this.controller = null;\n    }\n\n    private resolvedAppearance(): CordAppearance | undefined {\n        if (this._appearance) return this._appearance;\n        const attr = this.getAttribute('appearance');\n        if (attr) {\n            try { return JSON.parse(attr); } catch { console.warn('[Cord] el atributo appearance no es JSON v\u00E1lido.'); }\n        }\n        return getCordConfig().appearance;\n    }\n\n    private render() {\n        const token = this.getAttribute('token');\n        this.teardown();\n        if (!token || !this.container || !this.root) {\n            if (!token) console.warn(`[Cord] <${this.localName}> requiere el atributo token`);\n            return;\n        }\n        if (this.hasAttribute('debug')) enableDebug();\n        const minAttr = this.getAttribute('min-height');\n        const emit = (name: string, detail: unknown) =>\n            this.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true }));\n\n        this.controller = mountCotizador(this.container, {\n            token,\n            document: this.documentKind,\n            baseUrl: this.getAttribute('base-url') || undefined,\n            minHeight: minAttr ? parseInt(minAttr, 10) : undefined,\n            appearance: this.resolvedAppearance(),\n            onEvent: (event) => emit(event.type.replace(/^cord:/, ''), event.detail),\n        }, this.root);\n        this.unsubscribe = this.controller.state.subscribe((s) => {\n            this._state = s;\n            emit('statechange', s);\n        });\n    }\n}\n\n/** Alias hist\u00F3rico: los embeds publicados con <cord-cotizador> siguen funcionando. */\nexport class CordCotizadorElement extends CordQuoteElement {}\n\n/** <cord-invoice>: la factura de /i/{token}. Emite adem\u00E1s 'paid'. */\nexport class CordInvoiceElement extends CordQuoteElement {\n    protected override get documentKind(): 'invoice' { return 'invoice'; }\n}\n\n/** Registra los elementos (idempotente). Se llama solo al importar el paquete. */\nexport function defineCordElements(tag?: string) {\n    if (typeof customElements === 'undefined') return;\n    if (!customElements.get('cord-quote')) customElements.define('cord-quote', CordQuoteElement);\n    if (!customElements.get('cord-cotizador')) customElements.define('cord-cotizador', CordCotizadorElement);\n    if (!customElements.get('cord-invoice')) customElements.define('cord-invoice', CordInvoiceElement);\n    if (tag && !customElements.get(tag)) customElements.define(tag, class extends CordQuoteElement {});\n}\n\ndeclare global {\n    interface HTMLElementTagNameMap {\n        'cord-quote': CordQuoteElement;\n        'cord-cotizador': CordCotizadorElement;\n        'cord-invoice': CordInvoiceElement;\n    }\n}\n", "// Identificadores fiscales por pa\u00EDs. Fuente \u00FAnica para la app (src/lib/tax-id.ts\n// la reexporta) y para el Fiscal Element: el navegador valida mientras se\n// escribe y el servidor vuelve a validar con este mismo c\u00F3digo.\n\nexport type RfcPersona = 'fisica' | 'moral' | 'generico';\n\nconst RFC_RE = /^([A-Z\u00D1&]{3,4})(\\d{2})(\\d{2})(\\d{2})([A-Z0-9]{2})([0-9A])$/;\nconst RFC_DICT = '0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ \u00D1';\n// P\u00FAblico en general y extranjeros: el SAT los publica fijos, sin d\u00EDgito calculado.\nexport const RFC_GENERICOS = new Set(['XAXX010101000', 'XEXX010101000']);\n\nexport function normalizeRfc(value: string): string {\n    return String(value || '').trim().toUpperCase().replace(/[\\s-]/g, '');\n}\n\nfunction rfcCheckDigit(rfc: string): string {\n    const base = (rfc.length === 12 ? ' ' + rfc : rfc).slice(0, 12);\n    let sum = 0;\n    for (let i = 0; i < 12; i++) sum += RFC_DICT.indexOf(base[i]) * (13 - i);\n    const r = sum % 11;\n    if (r === 0) return '0';\n    return 11 - r === 10 ? 'A' : String(11 - r);\n}\n\nfunction validDate(yy: string, mm: string, dd: string): boolean {\n    const m = Number(mm);\n    const d = Number(dd);\n    if (m < 1 || m > 12 || d < 1) return false;\n    const daysInMonth = new Date(Date.UTC(2000 + Number(yy), m, 0)).getUTCDate();\n    return d <= Math.max(daysInMonth, m === 2 ? 29 : 0);\n}\n\n/** RFC con forma, fecha y d\u00EDgito verificador del SAT. */\nexport function validRfc(value: string): boolean {\n    const rfc = normalizeRfc(value);\n    if (RFC_GENERICOS.has(rfc)) return true;\n    const m = RFC_RE.exec(rfc);\n    if (!m || !validDate(m[2], m[3], m[4])) return false;\n    return rfcCheckDigit(rfc) === m[6];\n}\n\n/** 13 caracteres = persona f\u00EDsica; 12 = persona moral. */\nexport function rfcPersona(value: string): RfcPersona | null {\n    const rfc = normalizeRfc(value);\n    if (RFC_GENERICOS.has(rfc)) return 'generico';\n    if (!validRfc(rfc)) return null;\n    return rfc.length === 13 ? 'fisica' : 'moral';\n}\n\n// Letra de control espa\u00F1ola: resto entre 23 indexado en esta tabla. Misma\n// f\u00F3rmula para NIF y NIE (el NIE antepone X/Y/Z como 0/1/2).\nconst NIF_LETTERS = 'TRWAGMYFPDXBNJZSQVHLCKE';\n\n// El prefijo \"ES\" es el NIF-IVA (el mismo NIF con el c\u00F3digo de pa\u00EDs delante):\n// se quita solo cuando lo que sigue tiene la forma de un NIF. Sin esto,\n// \"ESB12345674\" se le\u00EDa como un CIF de letra E y se rechazaba.\nconst cleanEs = (value: string) => String(value || '').trim().toUpperCase()\n    .replace(/[\\s.\\-/]/g, '')\n    .replace(/^ES(?=[0-9A-Z]\\d{7}[0-9A-Z]$)/, '');\n\n/**\n * NIF de persona f\u00EDsica: DNI (8 d\u00EDgitos) o K/L/M + 7 d\u00EDgitos (menores sin DNI,\n * espa\u00F1oles en el extranjero, extranjeros sin NIE). Los K/L/M usan la letra del\n * DNI sobre sus 7 d\u00EDgitos, no el control del CIF (Orden EHA/451/2008).\n */\nexport function validNif(value: string): boolean {\n    const m = /^(\\d{8}|[KLM]\\d{7})([A-Z])$/.exec(cleanEs(value));\n    if (!m) return false;\n    return NIF_LETTERS[Number(m[1].replace(/^[KLM]/, '')) % 23] === m[2];\n}\n\nexport function validNie(value: string): boolean {\n    const m = /^([XYZ])(\\d{7})([A-Z])$/.exec(cleanEs(value));\n    if (!m) return false;\n    const prefix = { X: '0', Y: '1', Z: '2' }[m[1]] as string;\n    return NIF_LETTERS[Number(prefix + m[2]) % 23] === m[3];\n}\n\n// Para las siglas cuya forma de control declara la norma se exige esa forma;\n// para el resto se aceptan las dos: un CIF real rechazado bloquea a un negocio.\nconst CIF_DIGIT_ONLY = new Set(['A', 'B', 'E', 'H']);\nconst CIF_LETTER_ONLY = new Set(['N', 'P', 'Q', 'R', 'S', 'W']);\nconst CIF_CONTROL_LETTERS = 'JABCDEFGHI';\n\nexport function validCif(value: string): boolean {\n    // K, L y M no son CIF: son NIF de persona f\u00EDsica (ver validNif).\n    const m = /^([A-HJNP-SUVW])(\\d{7})([0-9A-J])$/.exec(cleanEs(value));\n    if (!m) return false;\n    const [, letter, digits, control] = m;\n    let sumEven = 0;\n    let sumOdd = 0;\n    for (let i = 0; i < 7; i++) {\n        const d = Number(digits[i]);\n        if (i % 2 === 1) sumEven += d;\n        else sumOdd += d * 2 >= 10 ? d * 2 - 9 : d * 2;\n    }\n    const controlDigit = (10 - ((sumEven + sumOdd) % 10)) % 10;\n    const controlLetter = CIF_CONTROL_LETTERS[controlDigit];\n    if (CIF_DIGIT_ONLY.has(letter)) return control === String(controlDigit);\n    if (CIF_LETTER_ONLY.has(letter)) return control === controlLetter;\n    return control === String(controlDigit) || control === controlLetter;\n}\n\n/** NIF, NIE o CIF espa\u00F1ol (con o sin prefijo \"ES\"), seg\u00FAn el primer car\u00E1cter. */\nexport function validSpainTaxId(value: string): boolean {\n    const clean = cleanEs(value);\n    if (/^[XYZ]/.test(clean)) return validNie(clean);\n    if (/^[\\dKLM]/.test(clean)) return validNif(clean);\n    return validCif(clean);\n}\n\n// Prefijos que el IRS nunca ha asignado a un EIN. Su tabla de campus es la\n// fuente: un EIN con estos dos primeros d\u00EDgitos no existe.\nconst EIN_NO_ASIGNADOS = '00 07 08 09 17 18 19 28 29 49 69 70 78 79 89 96 97';\n\n/** EIN de Estados Unidos: nueve d\u00EDgitos, con o sin guion tras el segundo, y prefijo asignado. */\nexport function validEin(value: string): boolean {\n    const v = String(value || '').trim();\n    return /^\\d{2}-?\\d{7}$/.test(v) && !EIN_NO_ASIGNADOS.includes(v.slice(0, 2));\n}\n\n// \u2500\u2500 validateTaxId: el identificador fiscal de los pa\u00EDses que Cord ofrece \u2500\u2500\u2500\u2500\u2500\n// Un solo validador por pa\u00EDs para la organizaci\u00F3n, sus clientes, el alta de\n// cobros y el Fiscal Element (reglas 24 y 28). Lo que se puede demostrar mal\n// \u2014forma imposible, prefijo inexistente, d\u00EDgito verificador que no cuadra\u2014 se\n// rechaza aqu\u00ED con un mensaje que nombra el dato local, en vez de dejar que lo\n// rechace el proveedor con un error que no le dice nada al negocio (regla 14).\n// Todo lo dem\u00E1s pasa: un falso rechazo deja a un negocio sin poder facturar ni\n// cobrar, as\u00ED que un pa\u00EDs sin validador devuelve ok y no se inventan reglas.\n// Los algoritmos est\u00E1n contrastados con python-stdnum y con la fuente oficial\n// de cada pa\u00EDs; los casos reales viven en test/tax-id.test.ts.\n\nexport type TaxIdLocale = 'es' | 'en' | 'pt' | 'fr' | 'de';\n\nexport interface TaxIdOptions {\n    /** Idioma del motivo de rechazo. Default: 'es'; uno desconocido tambi\u00E9n cae a 'es'. */\n    locale?: TaxIdLocale;\n    /**\n     * 'fisica' acepta adem\u00E1s los identificadores de persona que no se usan\n     * para facturar a una empresa: SSN/ITIN (US), National Insurance (GB),\n     * n\u00FAmero fiscal (FR) y DNI (AR, PE). Sin persona, solo los de negocio.\n     */\n    persona?: 'fisica' | 'moral';\n}\n\nexport type TaxIdResult =\n    | { ok: true; normalized: string; kind?: string }\n    | { ok: false; reason: string };\n\ntype Miss = { e: 'fmt' | 'chk' | 'pre'; k?: string; p?: string };\ntype Check = [kind: string, normalized: string] | Miss;\ntype CountryCheck = (s: string, raw: string, fisica: boolean) => Check;\n\nconst fmt: Miss = { e: 'fmt' };\nconst chk = (k: string): Miss => ({ e: 'chk', k });\nconst pre = (k: string, s: string): Miss => ({ e: 'pre', k, p: s.slice(0, 2) });\nconst digit = (s: string, i: number) => s.charCodeAt(i) - 48;\n\nfunction luhn(d: string): boolean {\n    let t = 0;\n    for (let i = 0; i < d.length; i++) {\n        let n = digit(d, d.length - 1 - i);\n        if (i % 2) n = n * 2 > 9 ? n * 2 - 9 : n * 2;\n        t += n;\n    }\n    return t % 10 === 0;\n}\n\n/** Suma ponderada de los primeros `weights.length` caracteres. */\nfunction weighted(s: string, weights: number[]): number {\n    let t = 0;\n    for (let i = 0; i < weights.length; i++) t += digit(s, i) * weights[i];\n    return t;\n}\n\n// M\u00F3dulo 11 con pesos 2..9 c\u00EDclicos desde la derecha (CNPJ). Cada car\u00E1cter\n// vale su c\u00F3digo ASCII \u2212 48: as\u00ED el CNPJ alfanum\u00E9rico (julio de 2026) usa la\n// misma cuenta que el num\u00E9rico, como lo public\u00F3 la Receita Federal.\nfunction mod11Dv(s: string, n: number, cycle: number): number {\n    let t = 0;\n    for (let i = 0; i < n; i++) t += digit(s, i) * (((n - 1 - i) % cycle) + 2);\n    const r = t % 11;\n    return r < 2 ? 0 : 11 - r;\n}\n\n/** ISO 7064 MOD 11,10: d\u00EDgito de control de la USt-IdNr alemana (BZSt). */\nfunction mod1110(d: string): boolean {\n    let p = 10;\n    for (let i = 0; i < d.length - 1; i++) p = (2 * ((digit(d, i) + p) % 10 || 10)) % 11;\n    return (11 - p) % 10 === digit(d, d.length - 1);\n}\n\nconst AR_PE_WEIGHTS = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2];\nconst CO_WEIGHTS = [3, 7, 13, 17, 19, 23, 29, 37, 41, 43, 47, 53, 59, 67, 71];\nconst GB_WEIGHTS = [8, 7, 6, 5, 4, 3, 2, 10, 1];\n\nconst VALIDATORS: Record<string, CountryCheck> = {\n    MX: (s) => {\n        const persona = rfcPersona(s);\n        if (persona) return ['rfc_' + persona, s];\n        const m = RFC_RE.exec(s);\n        return m && validDate(m[2], m[3], m[4]) ? chk('rfc') : fmt;\n    },\n    ES: (s) => {\n        const v = cleanEs(s);\n        const kind = /^[XYZ]/.test(v) ? 'nie' : /^[\\dKLM]/.test(v) ? 'nif' : 'cif';\n        if (validSpainTaxId(v)) return [kind, v];\n        return /^(\\d{8}[A-Z]|[KLMXYZ]\\d{7}[A-Z]|[A-HJNP-SUVW]\\d{7}[0-9A-J])$/.test(v) ? chk(kind) : fmt;\n    },\n    US: (s, _, fisica) => {\n        if (!/^\\d{9}$/.test(s)) return fmt;\n        if (fisica) {\n            // SSN: \u00E1rea 000, 666 y 9xx nunca se asignan; grupo 00 y serie 0000 tampoco.\n            const area = s.slice(0, 3);\n            if (area !== '000' && area !== '666' && s[0] !== '9' && s.slice(3, 5) !== '00' && s.slice(5) !== '0000') return ['ssn', s];\n            // ITIN: empieza en 9 y el 4.\u00BA-5.\u00BA d\u00EDgito cae en los rangos del IRS.\n            const g = Number(s.slice(3, 5));\n            if (s[0] === '9' && ((g >= 50 && g <= 65) || (g >= 70 && g <= 88) || (g >= 90 && g <= 92) || g >= 94)) return ['itin', s];\n        }\n        return validEin(s) ? ['ein', s] : pre('ein', s);\n    },\n    FR: (s, _, fisica) => {\n        // TVA intracomunitaria: clave de 2 caracteres + SIREN. Las claves\n        // alfanum\u00E9ricas existen y no se verifican; M\u00F3naco usa SIREN 000\u2026\n        const tva = /^(?:FR)?([0-9A-HJ-NP-Z]{2})(\\d{9})$/.exec(s);\n        if (tva) {\n            const [, key, siren] = tva;\n            if (!siren.startsWith('000') && !luhn(siren)) return chk('tva');\n            if (/^\\d\\d$/.test(key) && Number(key) !== (Number(siren) * 100 + 12) % 97) return chk('tva');\n            return ['tva', 'FR' + key + siren];\n        }\n        if (/^\\d{9}$/.test(s)) return luhn(s) ? ['siren', s] : chk('siren');\n        if (/^\\d{14}$/.test(s)) {\n            // La Poste numera sus establecimientos sin Luhn: la suma de los\n            // d\u00EDgitos es m\u00FAltiplo de 5 (salvo la sede, que s\u00ED cumple Luhn).\n            const poste = s.startsWith('356000000') && s !== '35600000000048';\n            const ok = poste ? s.split('').reduce((t, c) => t + Number(c), 0) % 5 === 0 : luhn(s);\n            return ok && luhn(s.slice(0, 9)) ? ['siret', s] : chk('siret');\n        }\n        if (fisica && /^[0-3]\\d{12}$/.test(s)) return Number(s.slice(0, 10)) % 511 === Number(s.slice(10)) ? ['spi', s] : chk('spi');\n        return fmt;\n    },\n    DE: (s) => {\n        const m = /^(?:DE)?([1-9]\\d{8})$/.exec(s);\n        if (m) return mod1110(m[1]) ? ['ust_idnr', 'DE' + m[1]] : chk('ust_idnr');\n        // Steuernummer: 10 u 11 d\u00EDgitos (formato del Land) o 13 (federal). No\n        // tiene un d\u00EDgito de control com\u00FAn a todos los L\u00E4nder: solo la forma.\n        return /^(\\d{10,11}|\\d{13})$/.test(s) ? ['steuernummer', s] : fmt;\n    },\n    GB: (s, _, fisica) => {\n        const vat = /^(GB|XI)?(\\d{9}|\\d{12})$/.exec(s);\n        if (vat) {\n            // HMRC: m\u00F3dulo 97 y, para los n\u00FAmeros nuevos, la variante \"9755\"\n            // (suma + 55 m\u00FAltiplo de 97). Los \u2265100 tambi\u00E9n aceptan resto 55.\n            const r = weighted(vat[2], GB_WEIGHTS) % 97;\n            const ok = r === 0 || r === 42 || (r === 55 && Number(vat[2].slice(0, 3)) >= 100);\n            return ok ? ['vat', (vat[1] || 'GB') + vat[2]] : chk('vat');\n        }\n        const gov = /^(?:GB)?(GD[0-4]\\d\\d|HA[5-9]\\d\\d)$/.exec(s);\n        if (gov) return ['vat', 'GB' + gov[1]];\n        const utr = /^(\\d{10})K?$/.exec(s);\n        if (utr) return ['utr', utr[1]];\n        // Company Number de Companies House: lo que el alta de cobros pide a una empresa.\n        if (/^(\\d{8}|(?!GB|XI)[A-Z]{2}\\d{6})$/.test(s)) return ['crn', s];\n        if (fisica && /^(?!BG|GB|NK|KN|TN|NT|ZZ)[A-CEGHJ-PR-TW-Z][A-CEGHJ-NPR-TW-Z]\\d{6}[A-D]$/.test(s)) return ['nino', s];\n        return fmt;\n    },\n    CA: (s) => {\n        // Business Number (o SIN de una persona: misma forma) con Luhn, solo o\n        // con su cuenta de programa: RT es GST/HST; RC, RM, RP, RR y RZ, otras.\n        const bn = /^(\\d{9})(R[CMPRTZ]\\d{4})?$/.exec(s);\n        const kind = !bn || !bn[2] ? 'bn' : bn[2].startsWith('RT') ? 'gst_hst' : 'bn15';\n        if (bn) return luhn(bn[1]) ? [kind, s] : chk(kind);\n        return /^\\d{10}TQ\\d{4}$/.test(s) ? ['qst', s] : fmt;\n    },\n    BR: (s) => {\n        if (/^(.)\\1*$/.test(s)) return fmt;\n        if (/^\\d{11}$/.test(s)) {\n            // CPF: dos d\u00EDgitos m\u00F3dulo 11 con pesos 10..2 y 11..2.\n            const dv = (n: number) => { const r = weighted(s, Array.from({ length: n }, (_, i) => n + 1 - i)) % 11; return r < 2 ? 0 : 11 - r; };\n            return dv(9) === digit(s, 9) && dv(10) === digit(s, 10) ? ['cpf', s] : chk('cpf');\n        }\n        if (/^[0-9A-Z]{12}\\d\\d$/.test(s)) {\n            return mod11Dv(s, 12, 8) === digit(s, 12) && mod11Dv(s, 13, 8) === digit(s, 13) ? ['cnpj', s] : chk('cnpj');\n        }\n        return fmt;\n    },\n    CO: (_, raw) => {\n        // El DV solo se verifica cuando viene separado con guion: sin \u00E9l, un\n        // NIT de persona (c\u00E9dula) de 10 d\u00EDgitos y uno de 9 + DV son\n        // indistinguibles, y adivinar rechazar\u00EDa NIT reales.\n        const m = /^(\\d{5,15})(?:-(\\d))?$/.exec(raw.replace(/[\\s.,]/g, ''));\n        if (!m) return fmt;\n        if (m[2] === undefined) return ['nit', m[1]];\n        let t = 0;\n        for (let i = 0; i < m[1].length; i++) t += digit(m[1], m[1].length - 1 - i) * CO_WEIGHTS[i];\n        const r = t % 11;\n        return (r > 1 ? 11 - r : r) === Number(m[2]) ? ['nit', m[1] + '-' + m[2]] : chk('nit');\n    },\n    AR: (s, _, fisica) => {\n        if (/^\\d{11}$/.test(s)) {\n            if (!/^(2[0347]|3[034]|5[015])/.test(s)) return pre('cuit', s);\n            // Un resto que da 10 no se asigna (la AFIP cambia el prefijo a 23/33);\n            // los padrones antiguos traen DV 9 en ese caso y se aceptan.\n            const r = 11 - (weighted(s, AR_PE_WEIGHTS) % 11);\n            return (r === 11 ? 0 : r === 10 ? 9 : r) === digit(s, 10) ? ['cuit', s] : chk('cuit');\n        }\n        return fisica && /^\\d{7,8}$/.test(s) ? ['dni', s] : fmt;\n    },\n    CL: (_, raw) => {\n        const m = /^(\\d{6,8})-?([\\dK])$/.exec(raw.replace(/[\\s.]/g, '').replace(/^CL/, ''));\n        if (!m) return fmt;\n        let t = 0;\n        for (let i = 0; i < m[1].length; i++) t += digit(m[1], m[1].length - 1 - i) * ((i % 6) + 2);\n        const r = 11 - (t % 11);\n        return (r === 11 ? '0' : r === 10 ? 'K' : String(r)) === m[2] ? ['rut', m[1] + '-' + m[2]] : chk('rut');\n    },\n    PE: (s, _, fisica) => {\n        if (/^\\d{11}$/.test(s)) {\n            if (!/^(1[0567]|20)/.test(s)) return pre('ruc', s);\n            return (11 - (weighted(s, AR_PE_WEIGHTS) % 11)) % 10 === digit(s, 10) ? ['ruc', s] : chk('ruc');\n        }\n        return fisica && /^\\d{8}$/.test(s) ? ['dni', s] : fmt;\n    },\n};\n\n/** Pa\u00EDses cuyo identificador fiscal valida validateTaxId; el resto pasa sin bloquear. */\nexport const TAX_ID_COUNTRIES: string[] = /* @__PURE__ */ Object.keys(VALIDATORS);\n\nconst cleanTaxIdInput = (value: unknown) => String(value ?? '').trim().toUpperCase().replace(/[\\u2010-\\u2015]/g, '-');\n\n// null = pa\u00EDs sin validador. Separado del texto para que los bundles que solo\n// necesitan saber si pasa (el Fiscal Element habla con c\u00F3digos de error y los\n// traduce con fiscalText) no carguen los motivos en cinco idiomas.\nfunction matchTaxId(cc: string, raw: string, fisica: boolean): Check | 'empty' | null {\n    const s = raw.replace(/[\\s.\\-/,]/g, '');\n    if (!s) return 'empty';\n    const check = VALIDATORS[cc];\n    if (!check) return null;\n    return s.length > 20 || /^0+$/.test(s) ? fmt : check(s, raw, fisica);\n}\n\n/** validateTaxId sin el motivo: lo que usa el receptor fiscal. */\nexport function checkTaxId(country: string, value: string, options: TaxIdOptions = {}): Extract<TaxIdResult, { ok: true }> | { ok: false } {\n    const raw = cleanTaxIdInput(value);\n    const m = matchTaxId(String(country || '').trim().toUpperCase(), raw, options.persona === 'fisica');\n    if (m === null) return { ok: true, normalized: raw.replace(/\\s+/g, ' ') };\n    return Array.isArray(m) ? { ok: true, normalized: m[1], kind: m[0] } : { ok: false };\n}\n\n// Nombre del dato local: las siglas oficiales no se traducen; los dem\u00E1s viven en `names` de cada idioma.\nconst NAMES: Record<string, string> = {\n    rfc: 'RFC', nif: 'NIF', nie: 'NIE', cif: 'CIF', ein: 'EIN', ssn: 'SSN', itin: 'ITIN',\n    siren: 'SIREN', siret: 'SIRET', ust_idnr: 'USt-IdNr.', steuernummer: 'Steuernummer', utr: 'UTR',\n    bn: 'Business Number', cpf: 'CPF', cnpj: 'CNPJ', nit: 'NIT', cuit: 'CUIT', rut: 'RUT', ruc: 'RUC',\n};\n\n// Qu\u00E9 se nombra cuando la forma no corresponde a ninguno, y un ejemplo v\u00E1lido.\nconst FORMATS: Record<string, [kinds: string[], example: string]> = {\n    MX: [['rfc'], 'EKU9003173C9'],\n    ES: [['nif', 'nie', 'cif'], 'B12345674'],\n    US: [['ein'], '12-3456789'],\n    FR: [['siren', 'siret', 'tva'], '732 829 320'],\n    DE: [['ust_idnr', 'steuernummer'], 'DE136695976'],\n    GB: [['vat', 'utr'], 'GB980780684'],\n    CA: [['bn', 'gst_hst'], '123456782RT0001'],\n    BR: [['cnpj', 'cpf'], '16.727.230/0001-97'],\n    CO: [['nit'], '900.123.456-8'],\n    AR: [['cuit'], '30-54668997-9'],\n    CL: [['rut'], '76.086.428-5'],\n    PE: [['ruc'], '20131312955'],\n};\n\ntype LocalName = 'tva' | 'spi' | 'vat' | 'gst_hst' | 'bn15';\ntype TaxIdText = { or: string; id: string; fmt: string; chk: string; chkEs: string; pre: string; empty: string; names: Record<LocalName, string> };\n\nconst TEXT: Record<TaxIdLocale, TaxIdText> = {\n    es: {\n        or: ' o ', id: 'identificador fiscal',\n        fmt: 'Revisa el {l}: no tiene el formato correcto (ej. {x}).',\n        chk: 'Revisa el {l}: el d\u00EDgito verificador no coincide.',\n        chkEs: 'Revisa el {l}: la letra o el d\u00EDgito de control no coincide.',\n        pre: 'Revisa el {l}: no existe con el prefijo {p}.',\n        empty: 'Captura el {l}.',\n        names: { tva: 'n\u00FAmero de TVA', spi: 'n\u00FAmero fiscal', vat: 'n\u00FAmero de VAT', gst_hst: 'n\u00FAmero de GST/HST', bn15: 'n\u00FAmero de programa' },\n    },\n    en: {\n        or: ' or ', id: 'tax ID',\n        fmt: 'Check the {l}: the format is not valid (e.g. {x}).',\n        chk: 'Check the {l}: the check digit does not match.',\n        chkEs: 'Check the {l}: the control letter or digit does not match.',\n        pre: 'Check the {l}: it does not exist with prefix {p}.',\n        empty: 'Enter the {l}.',\n        names: { tva: 'TVA number', spi: 'tax number', vat: 'VAT number', gst_hst: 'GST/HST number', bn15: 'program account' },\n    },\n    pt: {\n        or: ' ou ', id: 'identifica\u00E7\u00E3o fiscal',\n        fmt: 'Verifique o campo {l}: o formato n\u00E3o \u00E9 v\u00E1lido (p. ex. {x}).',\n        chk: 'Verifique o campo {l}: o d\u00EDgito verificador n\u00E3o confere.',\n        chkEs: 'Verifique o campo {l}: a letra ou o d\u00EDgito de controle n\u00E3o confere.',\n        pre: 'Verifique o campo {l}: o prefixo {p} n\u00E3o existe.',\n        empty: 'Preencha o campo {l}.',\n        names: { tva: 'n\u00FAmero de TVA', spi: 'n\u00FAmero fiscal', vat: 'n\u00FAmero de VAT', gst_hst: 'n\u00FAmero de GST/HST', bn15: 'n\u00FAmero de conta de programa' },\n    },\n    fr: {\n        or: ' ou ', id: 'identifiant fiscal',\n        fmt: 'V\u00E9rifiez le champ {l} : le format n\u2019est pas valide (p. ex. {x}).',\n        chk: 'V\u00E9rifiez le champ {l} : le chiffre de contr\u00F4le ne correspond pas.',\n        chkEs: 'V\u00E9rifiez le champ {l} : la lettre ou le chiffre de contr\u00F4le ne correspond pas.',\n        pre: 'V\u00E9rifiez le champ {l} : le pr\u00E9fixe {p} n\u2019existe pas.',\n        empty: 'Renseignez le champ {l}.',\n        names: { tva: 'num\u00E9ro de TVA', spi: 'num\u00E9ro fiscal', vat: 'num\u00E9ro de VAT', gst_hst: 'num\u00E9ro de GST/HST', bn15: 'num\u00E9ro de compte de programme' },\n    },\n    de: {\n        or: ' oder ', id: 'Steuernummer',\n        fmt: '{l}: Das Format ist ung\u00FCltig (z. B. {x}).',\n        chk: '{l}: Die Pr\u00FCfziffer stimmt nicht.',\n        chkEs: '{l}: Der Kontrollbuchstabe oder die Pr\u00FCfziffer stimmt nicht.',\n        pre: '{l}: Das Pr\u00E4fix {p} wird nicht vergeben.',\n        empty: '{l} fehlt.',\n        names: { tva: 'TVA-Nummer', spi: 'Steuernummer', vat: 'VAT-Nummer', gst_hst: 'GST/HST-Nummer', bn15: 'Programmkontonummer' },\n    },\n};\n\n/**\n * Valida el identificador fiscal de `country` (ISO 3166-1 alpha-2). Normaliza\n * (may\u00FAsculas, sin espacios, puntos, guiones ni diagonales; con el prefijo de\n * pa\u00EDs en los n\u00FAmeros de IVA europeos y del Reino Unido, sin \"ES\" en el NIF\n * espa\u00F1ol) y devuelve `kind` con el tipo detectado. Un pa\u00EDs sin validador\n * devuelve ok con el valor limpio: nunca bloquea lo que no puede demostrar.\n */\nexport function validateTaxId(country: string, value: string, options: TaxIdOptions = {}): TaxIdResult {\n    const t = TEXT[options.locale && Object.prototype.hasOwnProperty.call(TEXT, options.locale) ? options.locale : 'es'];\n    const cc = String(country || '').trim().toUpperCase();\n    const raw = cleanTaxIdInput(value);\n    const m = matchTaxId(cc, raw, options.persona === 'fisica');\n    if (m === null) return { ok: true, normalized: raw.replace(/\\s+/g, ' ') };\n    if (Array.isArray(m)) return { ok: true, normalized: m[1], kind: m[0] };\n\n    const name = (k: string) => (t.names as Record<string, string | undefined>)[k] ?? NAMES[k] ?? k;\n    const [kinds, example]: [string[], string] = FORMATS[cc] ?? [[], ''];\n    const label = kinds.length ? kinds.map(name).join(', ').replace(/, ([^,]*)$/, t.or + '$1') : t.id;\n    if (m === 'empty') return { ok: false, reason: t.empty.replace('{l}', label) };\n    const msg = m.e === 'fmt' ? t.fmt : m.e === 'pre' ? t.pre : cc === 'ES' ? t.chkEs : t.chk;\n    return { ok: false, reason: msg.replace('{l}', m.k ? name(m.k) : label).replace('{x}', example).replace('{p}', m.p ?? '') };\n}\n", "// Cat\u00E1logos del SAT (subconjunto usado en cotizaciones B2B) con la persona a la\n// que aplica cada clave. El CFDI 4.0 rechaza un r\u00E9gimen que no corresponde al\n// tipo de RFC; filtrar aqu\u00ED evita que el error aparezca hasta el timbrado.\n\nexport type PersonaFiscal = 'fisica' | 'moral';\n\nexport interface SatClave {\n    codigo: string;\n    nombre: string;\n    personas: readonly PersonaFiscal[];\n}\n\nconst AMBAS: readonly PersonaFiscal[] = ['fisica', 'moral'];\n\n// c_RegimenFiscal\nexport const REGIMENES_FISCALES: SatClave[] = [\n    { codigo: '601', nombre: '601 \u2014 General de Ley Personas Morales', personas: ['moral'] },\n    { codigo: '603', nombre: '603 \u2014 Personas Morales con Fines no Lucrativos', personas: ['moral'] },\n    { codigo: '605', nombre: '605 \u2014 Sueldos y Salarios e Ingresos Asimilados a Salarios', personas: ['fisica'] },\n    { codigo: '606', nombre: '606 \u2014 Arrendamiento', personas: ['fisica'] },\n    { codigo: '612', nombre: '612 \u2014 Personas F\u00EDsicas con Actividades Empresariales y Profesionales', personas: ['fisica'] },\n    { codigo: '616', nombre: '616 \u2014 Sin obligaciones fiscales', personas: ['fisica'] },\n    { codigo: '620', nombre: '620 \u2014 Sociedades Cooperativas de Producci\u00F3n', personas: ['moral'] },\n    { codigo: '621', nombre: '621 \u2014 Incorporaci\u00F3n Fiscal', personas: ['fisica'] },\n    { codigo: '626', nombre: '626 \u2014 R\u00E9gimen Simplificado de Confianza (RESICO)', personas: AMBAS },\n];\n\n// c_UsoCFDI\nexport const USOS_CFDI: SatClave[] = [\n    { codigo: 'G01', nombre: 'G01 \u2014 Adquisici\u00F3n de mercanc\u00EDas', personas: AMBAS },\n    { codigo: 'G03', nombre: 'G03 \u2014 Gastos en general', personas: AMBAS },\n    { codigo: 'I01', nombre: 'I01 \u2014 Construcciones', personas: AMBAS },\n    { codigo: 'I02', nombre: 'I02 \u2014 Mobiliario y equipo de oficina', personas: AMBAS },\n    { codigo: 'I04', nombre: 'I04 \u2014 Equipo de c\u00F3mputo y accesorios', personas: AMBAS },\n    { codigo: 'I08', nombre: 'I08 \u2014 Otra maquinaria y equipo', personas: AMBAS },\n    { codigo: 'S01', nombre: 'S01 \u2014 Sin efectos fiscales', personas: AMBAS },\n    { codigo: 'CP01', nombre: 'CP01 \u2014 Pagos', personas: AMBAS },\n];\n\nexport function regimenesPara(persona: PersonaFiscal | null): SatClave[] {\n    return persona ? REGIMENES_FISCALES.filter((r) => r.personas.includes(persona)) : REGIMENES_FISCALES;\n}\n\nexport function usosCfdiPara(persona: PersonaFiscal | null): SatClave[] {\n    return persona ? USOS_CFDI.filter((u) => u.personas.includes(persona)) : USOS_CFDI;\n}\n", "// Datos fiscales del receptor (el cliente al que se le factura). Lo usan el\n// Fiscal Element mientras se escribe y el servidor antes de guardar: la misma\n// funci\u00F3n, as\u00ED que lo que el navegador acepta es exactamente lo que el servidor\n// acepta. Solo los pa\u00EDses con riel fiscal real tienen reglas propias.\nimport { checkTaxId, normalizeRfc, rfcPersona, RFC_GENERICOS, TAX_ID_COUNTRIES } from './tax-id.js';\nimport { regimenesPara, usosCfdiPara } from './sat.js';\n\nexport type FiscalField = 'tax_id' | 'legal_name' | 'regimen_fiscal' | 'uso_cfdi' | 'cp_fiscal' | 'country';\n\nexport type FiscalIssueCode =\n    | 'required'\n    | 'too_long'\n    | 'invalid_tax_id'\n    | 'invalid_postal_code'\n    | 'regimen_not_for_persona'\n    | 'uso_not_for_persona'\n    | 'generic_requires_616_s01'\n    | 'legal_name_has_regime_suffix'\n    | 'unsupported_country';\n\nexport interface FiscalIssue { field: FiscalField; code: FiscalIssueCode }\n\nexport interface FiscalReceptorInput {\n    country?: string;\n    tax_id?: string;\n    legal_name?: string;\n    regimen_fiscal?: string;\n    uso_cfdi?: string;\n    cp_fiscal?: string;\n}\n\nexport interface FiscalReceptor {\n    country: string;\n    tax_id: string;\n    legal_name: string;\n    regimen_fiscal: string | null;\n    uso_cfdi: string | null;\n    cp_fiscal: string | null;\n}\n\nexport interface FiscalValidation {\n    ok: boolean;\n    value: FiscalReceptor;\n    /** Bloquean: el documento ser\u00EDa rechazado. */\n    errors: FiscalIssue[];\n    /** Avisan: probable rechazo, pero el dato puede ser correcto. */\n    warnings: FiscalIssue[];\n    persona: 'fisica' | 'moral' | 'generico' | null;\n}\n\n/**\n * Pa\u00EDses con reglas fiscales completas en este validador (c\u00F3digo postal,\n * r\u00E9gimen y uso de CFDI donde aplican). El identificador fiscal se valida\n * adem\u00E1s en todos los de TAX_ID_COUNTRIES.\n */\nexport const FISCAL_COUNTRIES = ['MX', 'ES', 'US'] as const;\n\nconst MAX = { tax_id: 20, legal_name: 300 };\n// CFDI 4.0: el nombre va como en la Constancia de Situaci\u00F3n Fiscal, SIN el\n// r\u00E9gimen societario. Es la causa m\u00E1s com\u00FAn de rechazo del receptor.\nconst REGIME_SUFFIX = /[,\\s]+(S\\.?\\s?A\\.?\\s?P?\\.?\\s?I?\\.?\\s?(DE\\s+C\\.?\\s?V\\.?)?|S\\.?\\s?DE\\s+R\\.?\\s?L\\.?(\\s?DE\\s+C\\.?\\s?V\\.?)?|S\\.?\\s?C\\.?|A\\.?\\s?C\\.?|S\\.?\\s?A\\.?\\s?S\\.?)\\s*$/i;\n\nconst clean = (v: unknown, max: number) => String(v ?? '').trim().replace(/\\s+/g, ' ').slice(0, max + 1);\n\nexport function validateFiscalReceptor(input: FiscalReceptorInput): FiscalValidation {\n    const errors: FiscalIssue[] = [];\n    const warnings: FiscalIssue[] = [];\n    const country = String(input.country || '').trim().toUpperCase();\n    const legalName = clean(input.legal_name, MAX.legal_name);\n    let taxId = clean(input.tax_id, MAX.tax_id).toUpperCase();\n    let regimen: string | null = String(input.regimen_fiscal || '').trim() || null;\n    let uso: string | null = String(input.uso_cfdi || '').trim().toUpperCase() || null;\n    let cp: string | null = String(input.cp_fiscal || '').trim() || null;\n    let persona: FiscalValidation['persona'] = null;\n\n    if (!country) errors.push({ field: 'country', code: 'required' });\n    if (!legalName) errors.push({ field: 'legal_name', code: 'required' });\n    if (legalName.length > MAX.legal_name) errors.push({ field: 'legal_name', code: 'too_long' });\n    if (!taxId) errors.push({ field: 'tax_id', code: 'required' });\n    if (taxId.length > MAX.tax_id) errors.push({ field: 'tax_id', code: 'too_long' });\n\n    if (country === 'MX') {\n        taxId = normalizeRfc(taxId);\n        persona = taxId ? rfcPersona(taxId) : null;\n        if (taxId && !persona) errors.push({ field: 'tax_id', code: 'invalid_tax_id' });\n        if (!cp) errors.push({ field: 'cp_fiscal', code: 'required' });\n        else if (!/^\\d{5}$/.test(cp)) errors.push({ field: 'cp_fiscal', code: 'invalid_postal_code' });\n        if (!regimen) errors.push({ field: 'regimen_fiscal', code: 'required' });\n        if (!uso) errors.push({ field: 'uso_cfdi', code: 'required' });\n\n        if (persona === 'generico') {\n            if ((regimen && regimen !== '616') || (uso && uso !== 'S01')) {\n                errors.push({ field: 'regimen_fiscal', code: 'generic_requires_616_s01' });\n            }\n        } else if (persona) {\n            if (regimen && !regimenesPara(persona).some((r) => r.codigo === regimen)) {\n                errors.push({ field: 'regimen_fiscal', code: 'regimen_not_for_persona' });\n            }\n            if (uso && !usosCfdiPara(persona).some((u) => u.codigo === uso)) {\n                errors.push({ field: 'uso_cfdi', code: 'uso_not_for_persona' });\n            }\n            if (persona === 'moral' && REGIME_SUFFIX.test(legalName)) {\n                warnings.push({ field: 'legal_name', code: 'legal_name_has_regime_suffix' });\n            }\n        }\n    } else if (country) {\n        // Fuera de M\u00E9xico el identificador sale del validador por pa\u00EDs: el\n        // mismo que usan la organizaci\u00F3n, sus clientes y el alta de cobros.\n        // Se guarda normalizado (sin \"ES\" en un NIF, con \"DE\" en una USt-IdNr).\n        regimen = uso = null;\n        if (taxId) {\n            const r = checkTaxId(country, taxId);\n            if (r.ok) taxId = r.normalized;\n            else errors.push({ field: 'tax_id', code: 'invalid_tax_id' });\n        }\n        if (country === 'ES' && cp && !/^\\d{5}$/.test(cp)) errors.push({ field: 'cp_fiscal', code: 'invalid_postal_code' });\n        if (country === 'US' && cp && !/^\\d{5}(-\\d{4})?$/.test(cp)) errors.push({ field: 'cp_fiscal', code: 'invalid_postal_code' });\n        if (!TAX_ID_COUNTRIES.includes(country)) warnings.push({ field: 'country', code: 'unsupported_country' });\n    }\n\n    return {\n        ok: errors.length === 0,\n        value: { country, tax_id: taxId, legal_name: legalName, regimen_fiscal: regimen, uso_cfdi: uso, cp_fiscal: cp },\n        errors,\n        warnings,\n        persona,\n    };\n}\n\nexport { RFC_GENERICOS };\n", "// Fiscal Form headless: captura de los datos fiscales del receptor con la misma\n// validaci\u00F3n que aplica el servidor. Filtra reg\u00EDmenes y usos de CFDI seg\u00FAn el\n// tipo de RFC, y solo muestra errores de campos que la persona ya toc\u00F3.\nimport { validateFiscalReceptor, type FiscalField, type FiscalIssue, type FiscalReceptorInput, type FiscalValidation } from '../fiscal/receptor.js';\nimport { regimenesPara, usosCfdiPara, type SatClave } from '../fiscal/sat.js';\nimport { createStore, type ReadableStore } from './store.js';\n\nexport interface FiscalFormState {\n    values: Required<FiscalReceptorInput>;\n    touched: Partial<Record<FiscalField, boolean>>;\n    validation: FiscalValidation;\n    /** Errores visibles: solo de campos tocados (o todos tras submit). */\n    visibleErrors: FiscalIssue[];\n    regimenes: SatClave[];\n    usosCfdi: SatClave[];\n    /** Campos que aplican al pa\u00EDs elegido. */\n    fields: FiscalField[];\n    submitted: boolean;\n}\n\nexport interface FiscalForm extends ReadableStore<FiscalFormState> {\n    set(field: keyof FiscalReceptorInput, value: string): void;\n    touch(field: FiscalField): void;\n    /** Marca todo como tocado y devuelve el resultado listo para enviar, o null. */\n    submit(): FiscalValidation['value'] | null;\n}\n\nconst FIELDS_BY_COUNTRY: Record<string, FiscalField[]> = {\n    MX: ['tax_id', 'legal_name', 'regimen_fiscal', 'uso_cfdi', 'cp_fiscal'],\n    ES: ['tax_id', 'legal_name', 'cp_fiscal'],\n    US: ['tax_id', 'legal_name', 'cp_fiscal'],\n};\n\nexport function createFiscalForm(initial: FiscalReceptorInput = {}): FiscalForm {\n    const values: Required<FiscalReceptorInput> = {\n        country: (initial.country || 'MX').toUpperCase(),\n        tax_id: initial.tax_id ?? '',\n        legal_name: initial.legal_name ?? '',\n        regimen_fiscal: initial.regimen_fiscal ?? '',\n        uso_cfdi: initial.uso_cfdi ?? '',\n        cp_fiscal: initial.cp_fiscal ?? '',\n    };\n    const store = createStore<FiscalFormState>(derive(values, {}, false));\n\n    return {\n        get: store.get,\n        subscribe: store.subscribe,\n        set(field, value) {\n            const s = store.get();\n            const next = { ...s.values, [field]: String(value ?? '') };\n            if (field === 'tax_id' && next.country === 'MX') {\n                const v = validateFiscalReceptor({ ...next });\n                if (v.persona === 'generico') { next.regimen_fiscal = '616'; next.uso_cfdi = 'S01'; }\n            }\n            store.set(derive(next, s.touched, s.submitted));\n        },\n        touch(field) {\n            const s = store.get();\n            store.set(derive(s.values, { ...s.touched, [field]: true }, s.submitted));\n        },\n        submit() {\n            const s = store.get();\n            const next = derive(s.values, s.touched, true);\n            store.set(next);\n            return next.validation.ok ? next.validation.value : null;\n        },\n    };\n}\n\nfunction derive(values: Required<FiscalReceptorInput>, touched: FiscalFormState['touched'], submitted: boolean): FiscalFormState {\n    const validation = validateFiscalReceptor(values);\n    const persona = validation.persona === 'fisica' || validation.persona === 'moral' ? validation.persona : null;\n    const generico = validation.persona === 'generico';\n    return {\n        values,\n        touched,\n        validation,\n        visibleErrors: validation.errors.filter((e) => submitted || touched[e.field]),\n        regimenes: generico ? regimenesPara('fisica').filter((r) => r.codigo === '616') : regimenesPara(persona),\n        usosCfdi: generico ? usosCfdiPara('fisica').filter((u) => u.codigo === 'S01') : usosCfdiPara(persona),\n        fields: FIELDS_BY_COUNTRY[values.country] ?? ['tax_id', 'legal_name'],\n        submitted,\n    };\n}\n", "// Textos del Fiscal Element en los cinco idiomas de Cord. Las etiquetas salen\n// del pa\u00EDs: RFC en M\u00E9xico, NIF/CIF en Espa\u00F1a, EIN en Estados Unidos (regla 24).\nimport type { FiscalField, FiscalIssueCode } from './receptor.js';\nimport { cordLocale, type CordLocale } from '../locale.js';\n\nexport type FiscalLocale = CordLocale;\n\n// Los doce mercados que Cord ofrece (SUPPORTED_COUNTRIES). Solo conoc\u00EDa tres,\n// as\u00ED que el formulario de un negocio en Lyon o en Bogot\u00E1 ped\u00EDa un \"Tax ID\"\n// gen\u00E9rico en vez del SIREN o el NIT que su cliente s\u00ED reconoce. Los nombres\n// van en el vocabulario del pa\u00EDs, no traducidos: es lo que imprime la factura.\nconst TAX_ID: Record<string, string | Record<FiscalLocale, string>> = {\n    MX: { es: 'RFC', en: 'RFC (Mexican tax ID)', pt: 'RFC (identifica\u00E7\u00E3o fiscal mexicana)', fr: 'RFC (identifiant fiscal mexicain)', de: 'RFC (mexikanische Steuernummer)' },\n    US: { es: 'EIN', en: 'EIN / Tax ID', pt: 'EIN / Tax ID', fr: 'EIN / Tax ID', de: 'EIN / Tax ID' },\n    CA: { es: 'BN / n\u00FAmero de GST/HST', en: 'BN / GST/HST number', pt: 'BN / n\u00FAmero de GST/HST', fr: 'NE / num\u00E9ro de TPS/TVH', de: 'BN / GST/HST-Nummer' },\n    BR: 'CNPJ / CPF',\n    ES: 'NIF / CIF',\n    GB: 'VAT reg. no. / UTR',\n    DE: { es: 'Steuernummer / USt-IdNr.', en: 'Steuernummer / VAT ID (USt-IdNr.)', pt: 'Steuernummer / USt-IdNr.', fr: 'Steuernummer / USt-IdNr.', de: 'Steuernummer / USt-IdNr.' },\n    FR: { es: 'SIREN / N\u00B0 de TVA', en: 'SIREN / VAT number (N\u00B0 TVA)', pt: 'SIREN / N\u00B0 de TVA', fr: 'SIREN / N\u00B0 de TVA', de: 'SIREN / TVA-Nummer' },\n    CO: 'NIT',\n    AR: 'CUIT',\n    CL: 'RUT',\n    PE: 'RUC',\n};\n\ntype Labels = Record<Exclude<FiscalField, 'tax_id'>, string> & { tax_id: string; choose: string };\n\nconst LABELS: Record<FiscalLocale, Labels> = {\n    es: { tax_id: 'Identificador fiscal', country: 'Pa\u00EDs', choose: 'Elige\u2026', legal_name: 'Nombre o raz\u00F3n social', regimen_fiscal: 'R\u00E9gimen fiscal', uso_cfdi: 'Uso del CFDI', cp_fiscal: 'C\u00F3digo postal fiscal' },\n    en: { tax_id: 'Tax ID', country: 'Country', choose: 'Choose\u2026', legal_name: 'Legal name', regimen_fiscal: 'Tax regime', uso_cfdi: 'CFDI use', cp_fiscal: 'Tax postal code' },\n    pt: { tax_id: 'Identifica\u00E7\u00E3o fiscal', country: 'Pa\u00EDs', choose: 'Escolha\u2026', legal_name: 'Nome ou raz\u00E3o social', regimen_fiscal: 'Regime fiscal', uso_cfdi: 'Uso do CFDI', cp_fiscal: 'C\u00F3digo postal fiscal' },\n    fr: { tax_id: 'Identifiant fiscal', country: 'Pays', choose: 'Choisissez\u2026', legal_name: 'Nom ou raison sociale', regimen_fiscal: 'R\u00E9gime fiscal', uso_cfdi: 'Usage du CFDI', cp_fiscal: 'Code postal fiscal' },\n    de: { tax_id: 'Steuernummer', country: 'Land', choose: 'Ausw\u00E4hlen\u2026', legal_name: 'Name oder Firmenname', regimen_fiscal: 'Steuerregime', uso_cfdi: 'Verwendungszweck des CFDI', cp_fiscal: 'Steuerliche Postleitzahl' },\n};\n\nconst ISSUES: Record<FiscalLocale, Record<FiscalIssueCode, string>> = {\n    es: {\n        required: 'Este dato es obligatorio.',\n        too_long: 'Es demasiado largo.',\n        invalid_tax_id: 'Revisa el identificador fiscal: no es v\u00E1lido.',\n        invalid_postal_code: 'El c\u00F3digo postal no tiene el formato correcto.',\n        regimen_not_for_persona: 'Ese r\u00E9gimen no corresponde a este tipo de RFC.',\n        uso_not_for_persona: 'Ese uso de CFDI no corresponde a este tipo de RFC.',\n        generic_requires_616_s01: 'Para p\u00FAblico en general el r\u00E9gimen es 616 y el uso S01.',\n        legal_name_has_regime_suffix: 'Escr\u00EDbelo como en la Constancia de Situaci\u00F3n Fiscal, sin \"S.A. de C.V.\" ni similares.',\n        unsupported_country: 'Para este pa\u00EDs solo se valida que el dato exista.',\n    },\n    en: {\n        required: 'This field is required.',\n        too_long: 'It is too long.',\n        invalid_tax_id: 'Check the tax ID: it is not valid.',\n        invalid_postal_code: 'The postal code format is not correct.',\n        regimen_not_for_persona: 'That tax regime does not match this type of RFC.',\n        uso_not_for_persona: 'That CFDI use does not match this type of RFC.',\n        generic_requires_616_s01: 'For the general public, the regime is 616 and the use is S01.',\n        legal_name_has_regime_suffix: 'Write it as on the tax certificate, without \"S.A. de C.V.\" or similar.',\n        unsupported_country: 'For this country only presence is checked.',\n    },\n    pt: {\n        required: 'Este campo \u00E9 obrigat\u00F3rio.',\n        too_long: 'O texto \u00E9 longo demais.',\n        invalid_tax_id: 'Verifique a identifica\u00E7\u00E3o fiscal: ela n\u00E3o \u00E9 v\u00E1lida.',\n        invalid_postal_code: 'O c\u00F3digo postal n\u00E3o tem o formato correto.',\n        regimen_not_for_persona: 'Esse regime n\u00E3o corresponde a este tipo de RFC.',\n        uso_not_for_persona: 'Esse uso do CFDI n\u00E3o corresponde a este tipo de RFC.',\n        generic_requires_616_s01: 'Para \u201Cp\u00FAblico en general\u201D, o regime \u00E9 616 e o uso \u00E9 S01.',\n        legal_name_has_regime_suffix: 'Escreva como no comprovante de situa\u00E7\u00E3o fiscal do SAT, sem \u201CS.A. de C.V.\u201D ou similares.',\n        unsupported_country: 'Para este pa\u00EDs, s\u00F3 se verifica que o dado foi informado.',\n    },\n    fr: {\n        required: 'Ce champ est obligatoire.',\n        too_long: 'Le texte est trop long.',\n        invalid_tax_id: 'V\u00E9rifiez l\u2019identifiant fiscal : il n\u2019est pas valide.',\n        invalid_postal_code: 'Le code postal n\u2019a pas le bon format.',\n        regimen_not_for_persona: 'Ce r\u00E9gime ne correspond pas \u00E0 ce type de RFC.',\n        uso_not_for_persona: 'Cet usage du CFDI ne correspond pas \u00E0 ce type de RFC.',\n        generic_requires_616_s01: 'Pour \u00AB p\u00FAblico en general \u00BB, le r\u00E9gime est 616 et l\u2019usage S01.',\n        legal_name_has_regime_suffix: 'Saisissez-le comme sur l\u2019attestation de situation fiscale du SAT, sans \u00AB S.A. de C.V. \u00BB ni mention similaire.',\n        unsupported_country: 'Pour ce pays, seule la pr\u00E9sence de la donn\u00E9e est v\u00E9rifi\u00E9e.',\n    },\n    de: {\n        required: 'Dieses Feld ist erforderlich.',\n        too_long: 'Der Text ist zu lang.',\n        invalid_tax_id: 'Pr\u00FCfen Sie die Steuernummer: Sie ist ung\u00FCltig.',\n        invalid_postal_code: 'Die Postleitzahl hat nicht das richtige Format.',\n        regimen_not_for_persona: 'Dieses Steuerregime passt nicht zu dieser Art von RFC.',\n        uso_not_for_persona: 'Dieser Verwendungszweck des CFDI passt nicht zu dieser Art von RFC.',\n        generic_requires_616_s01: 'F\u00FCr \u201Ep\u00FAblico en general\u201C gelten das Steuerregime 616 und der Verwendungszweck S01.',\n        legal_name_has_regime_suffix: 'Geben Sie ihn wie in der Steuerbescheinigung des SAT ein, ohne \u201ES.A. de C.V.\u201C oder \u00C4hnliches.',\n        unsupported_country: 'F\u00FCr dieses Land wird nur gepr\u00FCft, ob die Angabe vorhanden ist.',\n    },\n};\n\n/** Textos del formulario fiscal; un idioma que no se reconoce cae a ingl\u00E9s. */\nexport function fiscalText(locale: FiscalLocale) {\n    const l = cordLocale(locale);\n    return {\n        choose: LABELS[l].choose,\n        label(field: FiscalField, country: string): string {\n            if (field !== 'tax_id') return LABELS[l][field];\n            const name = TAX_ID[country];\n            return name === undefined ? LABELS[l].tax_id : typeof name === 'string' ? name : name[l];\n        },\n        issue(code: FiscalIssueCode | string): string {\n            return (ISSUES[l] as Record<string, string>)[code] ?? code;\n        },\n    };\n}\n", "// <cord-fiscal-form>: captura de datos fiscales del receptor en un Shadow DOM.\n// Es un elemento asociado a formularios: dentro de tu <form> aporta su valor\n// (JSON del receptor normalizado) bajo su atributo `name` y bloquea el env\u00EDo\n// mientras haya errores, igual que un <input required>. Valida con el mismo\n// c\u00F3digo que el servidor, as\u00ED que lo que acepta aqu\u00ED lo acepta Cord.\n//\n// Atributos: country (MX | ES | US | otro), lang (es | en | pt | fr | de; otro cae a en), name.\n// Eventos: 'fiscalchange' (estado completo), 'fiscalvalid' (receptor listo).\n// Partes: ::part(field), ::part(label), ::part(input), ::part(error), ::part(warning).\nimport { createFiscalForm, type FiscalForm, type FiscalFormState } from './headless/fiscal-form.js';\nimport type { FiscalField, FiscalReceptorInput } from './fiscal/receptor.js';\nimport { fiscalText, type FiscalLocale } from './fiscal/messages.js';\nimport { cordLocale } from './locale.js';\n\nconst ElementBase: typeof HTMLElement =\n    typeof HTMLElement !== 'undefined' ? HTMLElement : (class {} as unknown as typeof HTMLElement);\n\nconst CSS = `\n:host{display:block;font-family:var(--cord-font-family,system-ui,-apple-system,sans-serif);color:var(--cord-color-text,#050505)}\n:host([hidden]){display:none}\n.grid{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}\n.field{display:flex;flex-direction:column;gap:6px}\nlabel{font-size:13px;font-weight:600}\ninput,select{font:inherit;font-size:15px;padding:12px 14px;border:0;border-radius:var(--cord-border-radius,12px);background:var(--cord-color-input,#f5f5f7);color:inherit;outline:none;min-height:44px;box-sizing:border-box;width:100%}\ninput:focus-visible,select:focus-visible{box-shadow:0 0 0 2px var(--cord-color-primary,#0a192f)}\ninput[aria-invalid=\"true\"],select[aria-invalid=\"true\"]{box-shadow:0 0 0 2px var(--cord-color-danger,#c0392b)}\n.error{font-size:12px;color:var(--cord-color-danger,#c0392b)}\n.warning{font-size:12px;color:var(--cord-color-text-secondary,#6b7280)}\n`;\n\nconst FIELD_INPUT: Record<FiscalField, keyof FiscalReceptorInput | null> = {\n    country: null, tax_id: 'tax_id', legal_name: 'legal_name', regimen_fiscal: 'regimen_fiscal', uso_cfdi: 'uso_cfdi', cp_fiscal: 'cp_fiscal',\n};\n\nexport class CordFiscalFormElement extends ElementBase {\n    static formAssociated = true;\n    static get observedAttributes() { return ['country', 'lang']; }\n\n    private internals: ElementInternals | null = null;\n    private form: FiscalForm | null = null;\n    private unsubscribe: (() => void) | null = null;\n    private root: ShadowRoot | null = null;\n    private grid: HTMLDivElement | null = null;\n\n    constructor() {\n        super();\n        if (typeof (this as any).attachInternals === 'function') {\n            const internals: ElementInternals = (this as any).attachInternals();\n            // Navegadores con attachInternals pero sin la API de formularios (Safari < 16.4).\n            if (typeof internals.setFormValue === 'function' && typeof internals.setValidity === 'function') this.internals = internals;\n        }\n    }\n\n    /** Estado completo del formulario (valores, errores, opciones). */\n    get state(): FiscalFormState | null { return this.form?.get() ?? null; }\n    /** Receptor normalizado si es v\u00E1lido; si no, null. */\n    get value() { const s = this.form?.get(); return s?.validation.ok ? s.validation.value : null; }\n\n    /** Valores iniciales (por ejemplo, de un cliente ya guardado). */\n    setValues(values: FiscalReceptorInput) {\n        for (const [k, v] of Object.entries(values)) this.form?.set(k as keyof FiscalReceptorInput, String(v ?? ''));\n    }\n\n    /** Muestra todos los errores y devuelve el receptor si es v\u00E1lido. */\n    submit() { return this.form?.submit() ?? null; }\n\n    connectedCallback() {\n        if (!this.root) {\n            this.root = this.attachShadow({ mode: 'open' });\n            const style = document.createElement('style');\n            style.textContent = CSS;\n            this.grid = document.createElement('div');\n            this.grid.className = 'grid';\n            this.root.append(style, this.grid);\n        }\n        this.init();\n    }\n\n    disconnectedCallback() {\n        this.unsubscribe?.();\n        this.unsubscribe = null;\n    }\n\n    attributeChangedCallback(name: string) {\n        if (!this.isConnected) return;\n        if (name === 'country') this.init();\n        else this.renderFields();\n    }\n\n    private get locale(): FiscalLocale {\n        return cordLocale(this.getAttribute('lang') || document.documentElement.lang);\n    }\n\n    private init() {\n        this.unsubscribe?.();\n        const prev = this.form?.get().values;\n        this.form = createFiscalForm({ ...(prev ?? {}), country: this.getAttribute('country') || prev?.country || 'MX' });\n        this.unsubscribe = this.form.subscribe(() => this.sync());\n        this.renderFields();\n    }\n\n    private renderFields() {\n        if (!this.grid || !this.form) return;\n        const s = this.form.get();\n        const t = fiscalText(this.locale);\n        this.grid.textContent = '';\n        for (const field of s.fields) {\n            const key = FIELD_INPUT[field];\n            if (!key) continue;\n            const id = `cord-fiscal-${field}`;\n            const wrap = document.createElement('div');\n            wrap.className = 'field';\n            wrap.setAttribute('part', 'field');\n            const label = document.createElement('label');\n            label.htmlFor = id;\n            label.setAttribute('part', 'label');\n            label.textContent = t.label(field, s.values.country);\n            const control = field === 'regimen_fiscal' || field === 'uso_cfdi'\n                ? document.createElement('select')\n                : document.createElement('input');\n            control.id = id;\n            control.name = field;\n            control.setAttribute('part', 'input');\n            if (control instanceof HTMLInputElement) {\n                control.autocomplete = field === 'cp_fiscal' ? 'postal-code' : field === 'legal_name' ? 'organization' : 'off';\n                control.spellcheck = false;\n                if (field === 'cp_fiscal') control.inputMode = 'numeric';\n                control.maxLength = field === 'legal_name' ? 300 : 20;\n            }\n            control.addEventListener('input', () => this.form?.set(key, (control as HTMLInputElement).value));\n            control.addEventListener('change', () => this.form?.set(key, (control as HTMLInputElement).value));\n            control.addEventListener('blur', () => this.form?.touch(field));\n            const msg = document.createElement('div');\n            msg.id = `${id}-msg`;\n            msg.setAttribute('aria-live', 'polite');\n            control.setAttribute('aria-describedby', msg.id);\n            wrap.append(label, control, msg);\n            this.grid.append(wrap);\n        }\n        this.sync();\n    }\n\n    private sync() {\n        if (!this.grid || !this.form) return;\n        const s = this.form.get();\n        const t = fiscalText(this.locale);\n        for (const field of s.fields) {\n            const control = this.grid.querySelector<HTMLInputElement | HTMLSelectElement>(`[name=\"${field}\"]`);\n            const msg = this.grid.querySelector<HTMLDivElement>(`#cord-fiscal-${field}-msg`);\n            if (!control || !msg) continue;\n            const key = FIELD_INPUT[field] as keyof FiscalReceptorInput;\n            if (control instanceof HTMLSelectElement) {\n                const options = field === 'regimen_fiscal' ? s.regimenes : s.usosCfdi;\n                const wanted = ['', ...options.map((o) => o.codigo)].join('|');\n                if (control.dataset.options !== wanted) {\n                    control.textContent = '';\n                    control.append(new Option(t.choose, ''));\n                    for (const o of options) control.append(new Option(o.nombre, o.codigo));\n                    control.dataset.options = wanted;\n                }\n            }\n            if (control.value !== s.values[key]) control.value = s.values[key];\n            const error = s.visibleErrors.find((e) => e.field === field);\n            const warning = s.validation.warnings.find((w) => w.field === field);\n            control.setAttribute('aria-invalid', error ? 'true' : 'false');\n            msg.className = error ? 'error' : warning ? 'warning' : '';\n            msg.setAttribute('part', error ? 'error' : warning ? 'warning' : 'message');\n            msg.textContent = error ? t.issue(error.code) : warning ? t.issue(warning.code) : '';\n        }\n        this.internals?.setFormValue(s.validation.ok ? JSON.stringify(s.validation.value) : null);\n        const first = s.validation.errors[0];\n        const anchor = first ? this.grid.querySelector<HTMLElement>(`[name=\"${first.field}\"]`) ?? undefined : undefined;\n        if (first) this.internals?.setValidity({ customError: true }, t.issue(first.code), anchor);\n        else this.internals?.setValidity({});\n        this.dispatchEvent(new CustomEvent('fiscalchange', { detail: s, bubbles: true, composed: true }));\n        if (s.validation.ok) this.dispatchEvent(new CustomEvent('fiscalvalid', { detail: s.validation.value, bubbles: true, composed: true }));\n    }\n\n    formResetCallback() {\n        this.form = null;\n        this.init();\n    }\n}\n\nexport function defineFiscalElement() {\n    if (typeof customElements === 'undefined') return;\n    if (!customElements.get('cord-fiscal-form')) customElements.define('cord-fiscal-form', CordFiscalFormElement);\n}\n\ndeclare global {\n    interface HTMLElementTagNameMap { 'cord-fiscal-form': CordFiscalFormElement }\n}\n", "import type {\n    CreateQuoteInput,\n    CreateQuoteResponse,\n    CreateClientInput,\n    CreateProductInput,\n    CreateResponse,\n    PaginatedResponse,\n    CordProduct\n} from './types.js';\nimport { resolveApiBase } from './config.js';\n\n// C\u00F3digos reales que devuelve el servidor (src/lib/apiv1.ts, src/lib/apikey.ts,\n// src/lib/api-idempotency.ts). Manejar errores por c\u00F3digo, nunca por el mensaje.\nexport type CordErrorCode =\n    | 'invalid_json'\n    | 'invalid_request'\n    | 'unsupported_media_type'\n    | 'payload_too_large'\n    | 'missing_key'\n    | 'invalid_key'\n    | 'token_expired'\n    | 'insufficient_scope'\n    | 'insufficient_permissions'\n    | 'ip_not_allowed'\n    | 'key_expired'\n    | 'secret_key_in_browser'\n    | 'missing_origin'\n    | 'unauthorized_origin'\n    | 'invalid_origin'\n    | 'origin_allowlist_required'\n    | 'subscription_key_limit'\n    | 'subscription_verification_unavailable'\n    | 'api_quota_exceeded'\n    | 'payment_required'\n    | 'rate_limited'\n    | 'invalid_idempotency_key'\n    | 'idempotency_key_reused'\n    | 'idempotency_in_progress'\n    | 'idempotency_unavailable'\n    | 'not_found'\n    | 'missing_id'\n    | 'invalid_cliente_id'\n    | 'invalid_state'\n    | 'missing_text'\n    | 'text_too_long'\n    | 'fx_unavailable'\n    | 'tax_catalog_unavailable'\n    | 'send_failed'\n    | 'provider_error'\n    | 'unavailable'\n    | 'server_error'\n    | 'network_error'\n    | 'clients_require_proxy'\n    | 'unknown';\n\nexport class CordError extends Error {\n    readonly status: number;\n    readonly code: CordErrorCode;\n    readonly payload: any;\n    /** `req_\u2026` del header `Cord-Request-Id`. Incl\u00FAyelo al pedir soporte. */\n    readonly requestId: string | null;\n    /** P\u00E1gina de la documentaci\u00F3n que explica este c\u00F3digo. */\n    readonly docUrl: string | null;\n\n    constructor(status: number, payload: any, code?: CordErrorCode, requestId?: string | null) {\n        const resolvedCode: CordErrorCode = code ?? (typeof payload?.code === 'string' ? payload.code : 'unknown');\n        super(payload?.error || `Cord API error (${status})`);\n        this.name = 'CordError';\n        this.status = status;\n        this.code = resolvedCode;\n        this.payload = payload;\n        this.requestId = requestId ?? (typeof payload?.request_id === 'string' ? payload.request_id : null);\n        this.docUrl = typeof payload?.doc_url === 'string' ? payload.doc_url : null;\n    }\n}\n\nconst IS_BROWSER = typeof window !== 'undefined' && typeof document !== 'undefined';\n\n/** El servidor envuelve TODA respuesta en `{ data }` (ver src/lib/apiv1.ts `ok()`).\n * Desenvuelve defensivamente: si no hay `.data`, devuelve el body tal cual\n * (no rompe contra un proxy propio que no envuelva sus respuestas). */\nfunction unwrapEnvelope<T>(body: any): T {\n    return (body && typeof body === 'object' && 'data' in body ? body.data : body) as T;\n}\n\nexport class CordAPI {\n    private readonly baseUrl: string;\n    private readonly apiKey: string;\n\n    constructor(apiKey?: string, baseUrl?: string) {\n        const key = apiKey || (typeof process !== 'undefined' ? process.env.CORD_API_KEY : undefined);\n        if (!key) {\n            throw new Error('Cord API Key is required. Pass it to the constructor or set CORD_API_KEY environment variable.');\n        }\n        if (IS_BROWSER && /^(sk|rk)_/.test(key)) {\n            throw new Error(\n                '[Cord] CordAPI recibi\u00F3 una secret key (sk_ o rk_) en el navegador. Ya qued\u00F3 expuesta en el c\u00F3digo de la p\u00E1gina: rev\u00F3cala en Ajustes \u203A Developers y usa CordAPI solo en tu servidor.',\n            );\n        }\n        this.apiKey = key;\n        this.baseUrl = resolveApiBase(baseUrl);\n    }\n\n    /**\n     * `unwrap: false` para endpoints de LISTA \u2014 su forma real YA ES\n     * `PaginatedResponse` (`{ data: T[], meta }`), que coincide con el sobre\n     * del servidor; desenvolverla dos veces perder\u00EDa `meta`. Los endpoints de\n     * creaci\u00F3n s\u00ED necesitan desenvolver (esperan el objeto plano).\n     */\n    private async fetch<T>(path: string, init?: RequestInit, opts: { unwrap?: boolean } = {}): Promise<T> {\n        const { unwrap = true } = opts;\n        let response: Response;\n        try {\n            response = await fetch(`${this.baseUrl}${path}`, {\n                ...init,\n                headers: {\n                    'Authorization': `Bearer ${this.apiKey}`,\n                    'Content-Type': 'application/json',\n                    ...init?.headers,\n                },\n            });\n        } catch (err: any) {\n            throw new CordError(0, { error: err?.message || 'Error de red' }, 'network_error');\n        }\n\n        if (!response.ok) {\n            let payload;\n            try {\n                payload = await response.json();\n            } catch (e) {\n                payload = { error: response.statusText };\n            }\n            throw new CordError(response.status, payload, undefined, response.headers.get('cord-request-id'));\n        }\n\n        const body = await response.json();\n        return unwrap ? unwrapEnvelope<T>(body) : (body as T);\n    }\n\n    // ==== Quotes (Cotizaciones) ====\n    public readonly quotes = {\n        create: (data: CreateQuoteInput): Promise<CreateQuoteResponse> => {\n            return this.fetch<CreateQuoteResponse>('/cotizaciones', {\n                method: 'POST',\n                body: JSON.stringify(data),\n            });\n        },\n        list: (options?: { limit?: number; offset?: number; status?: string }): Promise<PaginatedResponse<unknown>> => {\n            const params = new URLSearchParams();\n            if (options?.limit) params.append('limit', options.limit.toString());\n            if (options?.offset) params.append('offset', options.offset.toString());\n            if (options?.status) params.append('status', options.status);\n            const query = params.toString() ? `?${params.toString()}` : '';\n            return this.fetch<PaginatedResponse<unknown>>(`/cotizaciones${query}`, undefined, { unwrap: false });\n        }\n    };\n\n    // ==== Clients (Clientes) ====\n    public readonly clients = {\n        create: (data: CreateClientInput): Promise<CreateResponse> => {\n            return this.fetch<CreateResponse>('/clientes', {\n                method: 'POST',\n                body: JSON.stringify(data),\n            });\n        },\n        list: (options?: { limit?: number; offset?: number }): Promise<PaginatedResponse<unknown>> => {\n            const params = new URLSearchParams();\n            if (options?.limit) params.append('limit', options.limit.toString());\n            if (options?.offset) params.append('offset', options.offset.toString());\n            const query = params.toString() ? `?${params.toString()}` : '';\n            return this.fetch<PaginatedResponse<unknown>>(`/clientes${query}`, undefined, { unwrap: false });\n        }\n    };\n\n    // ==== Products (Productos) ====\n    public readonly products = {\n        create: (data: CreateProductInput): Promise<CreateResponse> => {\n            return this.fetch<CreateResponse>('/productos', {\n                method: 'POST',\n                body: JSON.stringify(data),\n            });\n        },\n        list: (options?: { limit?: number; offset?: number }): Promise<PaginatedResponse<CordProduct>> => {\n            const params = new URLSearchParams();\n            if (options?.limit) params.append('limit', options.limit.toString());\n            if (options?.offset) params.append('offset', options.offset.toString());\n            const query = params.toString() ? `?${params.toString()}` : '';\n            return this.fetch<PaginatedResponse<CordProduct>>(`/productos${query}`, undefined, { unwrap: false });\n        }\n    };\n}\n", "/**\n * Motor Matem\u00E1tico de Cord.\n * Se comparte entre el frontend (CordBuilder) y el backend (/api/cotizaciones)\n * para asegurar 100% de paridad en el c\u00E1lculo de subtotales, IVA y totales.\n */\n\n// N\u00FAmero FINITO y no-negativo, o el fallback. Cierra el hueco de montos negativos,\n// NaN (string basura) o Infinity (JSON 1e999) que envenenar\u00EDan subtotal/IVA/total.\nexport const num = (v: unknown, fallback = 0): number => {\n    const n = Number(v);\n    return Number.isFinite(n) && n >= 0 ? n : fallback;\n};\n\nexport interface EngineItemInput {\n    producto_id?: string | null;\n    descripcion?: string;\n    cantidad?: number | string;\n    precio_unitario?: number | string;\n    precio_negociado?: number | string | null;\n    costo_unitario?: number | string | null;\n}\n\nexport interface EngineItem {\n    producto_id: string | null;\n    descripcion: string;\n    cantidad: number;\n    precio_unitario: number;\n    precio_negociado: number | null;\n    costo_unitario: number | null;\n}\n\n// Sanea una l\u00EDnea: n\u00FAmeros finitos no-negativos y descripci\u00F3n acotada. Se aplica\n// UNA vez y el arreglo saneado alimenta todo (subtotal, aprobaci\u00F3n, inserts, snapshot).\nexport function sanitizeItem(it: EngineItemInput): EngineItem {\n    const nego = it.precio_negociado;\n    const q = num(it.cantidad, 1);\n    return {\n        producto_id: it.producto_id || null,\n        descripcion: String(it.descripcion ?? '').slice(0, 500),\n        cantidad: q > 0 ? q : 1,\n        precio_unitario: num(it.precio_unitario, 0),\n        precio_negociado: (nego === null || nego === undefined) ? null : num(nego, 0),\n        costo_unitario: (it.costo_unitario === null || it.costo_unitario === undefined) ? null : num(it.costo_unitario, 0),\n    };\n}\n\nexport interface EngineTotals {\n    subtotal: number;\n    iva: number;\n    total: number;\n    sumPrecios: number;\n    ivaIncluido: boolean;\n    ivaPct: number;\n}\n\n/** Redondeo a `dp` decimales \u2014 SOLO para mostrar en pantalla. Nunca se aplica\n * dentro de `calculateTotals` (cambiar el redondeo ah\u00ED reescribir\u00EDa en\n * silencio la aritm\u00E9tica de cotizaciones ya guardadas en producci\u00F3n). */\nexport function roundMoney(n: number, dp = 2): number {\n    const f = 10 ** dp;\n    return Math.round(n * f) / f;\n}\n\nexport function calculateTotals(items: EngineItemInput[], ivaPct: number, ivaIncluido: boolean): EngineTotals {\n    // `num(ivaPct, 0.16)` NO es la soluci\u00F3n aqu\u00ED: caer en silencio a 16% para\n    // una org con IVA 0% (o cualquier NaN/fuera de rango) es un bug PEOR que\n    // el que reemplaza \u2014 un 500 expl\u00EDcito le gana a un total incorrecto que\n    // nadie audita. Este motor lo importa el servidor directamente\n    // (src/lib/cotizaciones.ts) para escribir totales reales en producci\u00F3n.\n    if (!Number.isFinite(ivaPct) || ivaPct < 0 || ivaPct > 1) {\n        throw new RangeError(`calculateTotals: ivaPct debe ser un n\u00FAmero entre 0 y 1 (recibido: ${ivaPct}).`);\n    }\n\n    const sanitized = items.map(sanitizeItem);\n    \n    let sumPrecios = 0;\n    for (const it of sanitized) {\n        const p = it.precio_negociado ?? it.precio_unitario ?? 0;\n        sumPrecios += num(p) * num(it.cantidad, 1);\n    }\n\n    let subtotal = 0;\n    let iva = 0;\n    let total = 0;\n\n    if (ivaIncluido) {\n        total = sumPrecios;\n        subtotal = total / (1 + ivaPct);\n        iva = total - subtotal;\n    } else {\n        subtotal = sumPrecios;\n        iva = subtotal * ivaPct;\n        total = subtotal + iva;\n    }\n\n    return { subtotal, iva, total, sumPrecios, ivaIncluido, ivaPct };\n}\n\n// \u2500\u2500 Facturaci\u00F3n: una tasa POR L\u00CDNEA \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// `calculateTotals` aplana una sola tasa para toda la cotizaci\u00F3n, que es lo\n// correcto ah\u00ED: se est\u00E1 negociando un precio, no emitiendo un documento fiscal.\n// Una factura es otra cosa. Vender mezclando tasas \u2014un concepto exento junto a\n// uno con IVA, o servicios y bienes con tratamiento distinto\u2014 es normal en\n// cuanto sales de un solo pa\u00EDs, y aplanarlo produce un documento que no cuadra\n// con lo que la autoridad espera.\n//\n// Esta funci\u00F3n NO reemplaza a la de arriba: la de arriba la usan cotizaciones y\n// /api/v1 para escribir totales ya guardados en producci\u00F3n, y tocarla\n// reescribir\u00EDa su aritm\u00E9tica en silencio.\n\nexport interface InvoiceItemInput extends EngineItemInput {\n    /** Fracci\u00F3n, no porcentaje: 0.16, nunca 16. */\n    tax_rate?: number | string | null;\n}\n\nexport interface InvoiceItem extends EngineItem {\n    tax_rate: number;\n    /** Precio efectivo por unidad: negociado si existe, si no el de lista. */\n    precio_final: number;\n    /** Base imponible NETA: ya descontado el descuento de documento que le toca. */\n    base: number;\n    impuesto: number;\n    total: number;\n    /**\n     * Descuento de documento repartido a esta l\u00EDnea, ANTES de impuestos: lo que\n     * baj\u00F3 su base. La base bruta de la l\u00EDnea es `base + descuento`. 0 sin descuento.\n     */\n    descuento: number;\n}\n\nexport interface TaxBreakdown {\n    tasa: number;\n    base: number;\n    impuesto: number;\n}\n\nexport interface InvoiceTotals {\n    lineas: InvoiceItem[];\n    /** Suma de bases NETAS (despu\u00E9s del descuento de documento). */\n    subtotal: number;\n    impuestos: number;\n    total: number;\n    /** Base imponible e impuesto agrupados por tasa \u2014 lo que imprime el PDF. */\n    porTasa: TaxBreakdown[];\n    ivaIncluido: boolean;\n    /**\n     * Descuento de documento, antes de impuestos: la suma de `lineas[].descuento`.\n     * El subtotal bruto (antes del descuento) es `subtotal + descuentoTotal`.\n     */\n    descuentoTotal: number;\n}\n\n/**\n * Descuento de DOCUMENTO: una rebaja sobre la venta completa, no sobre un\n * concepto. Se aplica antes de impuestos y se reparte entre las l\u00EDneas en\n * proporci\u00F3n a su importe bruto (precio final \u00D7 cantidad).\n *\n * - `'porcentaje'`: `valor` en puntos porcentuales (10 = 10 %), de 0 a 100.\n * - `'monto'`: `valor` en la divisa del documento. Se topa en el bruto del\n *   documento: un descuento nunca deja un total negativo.\n *\n * Con `ivaIncluido` los precios capturados ya traen el impuesto, as\u00ED que el\n * descuento rebaja ese importe con impuesto y la base se desagrega despu\u00E9s: un\n * \"100 de descuento\" sobre precios con IVA baja 100 lo que el cliente paga.\n */\nexport interface DescuentoInput {\n    tipo: 'porcentaje' | 'monto';\n    valor: number | string;\n}\n\n/**\n * Opciones de redondeo del documento.\n *\n * `roundLines` = decimales de la divisa (2 para MXN/EUR, 0 para JPY/CLP, 3 para\n * KWD). Cuando viene, CADA l\u00EDnea se redondea \u2014base e impuesto\u2014 y los totales\n * del documento son la SUMA de los valores ya redondeados. Es la regla de\n * cualquier documento fiscal: el CFDI exige que el subtotal sea la suma de los\n * importes de sus conceptos, y la AEAT valida la cuota contra la base por\n * l\u00EDnea. Sin ella, tres l\u00EDneas de 1.5 \u00D7 33.33 al 16% daban un subtotal de\n * documento de 149.98 contra 150.00 de las l\u00EDneas: el timbrado fallaba y una\n * nota de cr\u00E9dito por el total era imposible de cuadrar.\n *\n * Sin la opci\u00F3n el motor conserva la aritm\u00E9tica sin redondeo de siempre: es la\n * que usan los integradores del paquete publicado y no se cambia por debajo.\n */\nexport interface RoundingOptions {\n    roundLines?: number;\n    /**\n     * C\u00F3mo se redondea el IMPUESTO cuando hay `roundLines` (sin `roundLines` no\n     * hay nada que redondear y los dos modos dan lo mismo).\n     *\n     * - `'line'` (default, el comportamiento de siempre): cada l\u00EDnea redondea\n     *   su impuesto y el del documento es la SUMA de esos importes. Es lo que\n     *   valida el CFDI y lo que la AEAT desglosa.\n     * - `'document'`: el impuesto de cada tasa es el redondeo de\n     *   (suma de las bases de esa tasa \u00D7 tasa), no la suma de impuestos ya\n     *   redondeados. Es la regla de Chile: en el DTE el IVA es\n     *   \"Monto neto \u00D7 tasa IVA\" (Formato DTE v2.2 del SII, campos 107, 111 y\n     *   112) y los montos son enteros. Con redondeo por l\u00EDnea, tres l\u00EDneas de\n     *   $ 1.003 al 19 % suman $ 573 de IVA (191 + 191 + 191) contra los $ 572\n     *   del documento (round(3.009 \u00D7 0,19)).\n     *\n     *   Lo que se ve por L\u00CDNEA sigue cuadrando: el impuesto de cada tasa se\n     *   reparte entre sus l\u00EDneas por mayor residuo (unidades m\u00EDnimas, empate\n     *   por orden de l\u00EDnea), as\u00ED que la suma de las l\u00EDneas es exactamente el\n     *   impuesto del documento y cada l\u00EDnea difiere a lo m\u00E1s en una unidad de\n     *   round(base \u00D7 tasa). Con precios con impuesto incluido, la base de cada\n     *   tasa es el redondeo de (suma de importes con impuesto \u00F7 (1 + tasa))\n     *   \u2014el \"Monto neto\" del SII con montos brutos, campo 107\u2014 repartida igual\n     *   entre sus l\u00EDneas, y el impuesto es esa base \u00D7 tasa redondeado: el total\n     *   puede quedar a una unidad de la suma capturada, como ya pasa por l\u00EDnea.\n     */\n    taxRounding?: TaxRounding;\n}\n\nexport type TaxRounding = 'line' | 'document';\n\nconst roundTo = (n: number, decimals: number): number => {\n    const f = 10 ** decimals;\n    return Math.round((n + Number.EPSILON) * f) / f;\n};\n\n/**\n * Reparte `total` (ya en los decimales de la divisa) entre las l\u00EDneas en\n * proporci\u00F3n a `exactos` (sus valores SIN redondear, que suman \u2248 `total`) por\n * mayor residuo, en unidades m\u00EDnimas: la suma del reparto es exactamente\n * `total` y cada parte queda a menos de una unidad de su valor exacto. Empates\n * por orden de l\u00EDnea, para que el mismo documento d\u00E9 siempre lo mismo.\n */\nfunction repartirPorResiduo(total: number, exactos: number[], decimals: number): number[] {\n    const f = 10 ** decimals;\n    const meta = Math.round(total * f);\n    const x = exactos.map((v) => v * f);\n    const pisos = x.map((v) => Math.floor(v + 1e-7));\n    let resto = meta - pisos.reduce((s, v) => s + v, 0);\n    const orden = x.map((_, i) => i).sort((a, b) => (x[b] - pisos[b]) - (x[a] - pisos[a]) || a - b);\n    for (let k = 0; resto > 0 && orden.length; k++) { pisos[orden[k % orden.length]]++; resto--; }\n    for (let k = orden.length - 1; resto < 0 && k >= 0; k--) {\n        const i = orden[k];\n        if (pisos[i] > 0) { pisos[i]--; resto++; }\n    }\n    return pisos.map((v) => v / f);\n}\n\n/**\n * Reparte el descuento de documento entre los importes brutos de las l\u00EDneas,\n * en proporci\u00F3n a cada uno. Devuelve cu\u00E1nto le toca a cada l\u00EDnea, en los mismos\n * t\u00E9rminos que los importes (con impuesto si los precios lo incluyen).\n *\n * Con `decimals` el reparto se hace en UNIDADES M\u00CDNIMAS de la divisa por el\n * m\u00E9todo del mayor residuo: la suma de lo repartido es exactamente el descuento\n * del documento \u2014ni un centavo de m\u00E1s o de menos\u2014 y ninguna l\u00EDnea recibe m\u00E1s que\n * su propio importe. Los empates se resuelven por orden de l\u00EDnea, as\u00ED que el\n * mismo documento da siempre el mismo reparto.\n */\nfunction repartirDescuento(brutos: number[], d: DescuentoInput | null | undefined, decimals: number | undefined): number[] {\n    const valor = Number(d?.valor);\n    // Mismo criterio que las tasas: un descuento negativo, NaN o de m\u00E1s del\n    // 100 % es un error de programaci\u00F3n, no algo que se ajusta en silencio.\n    if (d && ((d.tipo !== 'porcentaje' && d.tipo !== 'monto') || !(valor >= 0 && valor <= (d.tipo === 'monto' ? Infinity : 100)))) {\n        throw new RangeError(`descuento fuera de rango: ${d.tipo} ${d.valor}`);\n    }\n    const bruto = brutos.reduce((s, b) => s + b, 0);\n    if (!d || !(valor > 0) || !(bruto > 0)) return brutos.map(() => 0);\n    const deseado = d.tipo === 'porcentaje' ? bruto * valor / 100 : valor;\n\n    if (decimals === undefined) {\n        const total = Math.min(deseado, bruto);\n        return brutos.map((b) => (total >= bruto ? b : total * b / bruto));\n    }\n\n    const f = 10 ** decimals;\n    const u = brutos.map((b) => Math.round(b * f));\n    const tu = u.reduce((s, x) => s + x, 0);\n    const D = Math.min(Math.round(roundTo(deseado, decimals) * f), tu);\n    // Cociente entero de (descuento \u00D7 importe) / total. La divisi\u00F3n en punto\n    // flotante puede redondear hacia arriba un cociente que no es exacto: se\n    // corrige, y el ajuste final por residuo cubre lo que quede.\n    const q = u.map((x) => {\n        const k = Math.floor(D * x / tu);\n        return k * tu > D * x ? k - 1 : k;\n    });\n    let resto = D - q.reduce((s, x) => s + x, 0);\n    // Mayor residuo primero; empate por orden de l\u00EDnea. Si falta, se suma una\n    // unidad a quien tiene cupo; si sobra (importes enormes), se quita al rev\u00E9s.\n    const orden = u.map((_, i) => i).sort((a, b) => (D * u[b] - q[b] * tu) - (D * u[a] - q[a] * tu) || a - b);\n    for (const i of resto < 0 ? orden.reverse() : orden) {\n        if (resto > 0 && q[i] < u[i]) { q[i]++; resto--; }\n        else if (resto < 0 && q[i] > 0) { q[i]--; resto++; }\n    }\n    return q.map((x) => x / f);\n}\n\n/**\n * Totales de una factura con impuesto por l\u00EDnea.\n *\n * `ivaIncluido = true` significa que los precios capturados YA traen el\n * impuesto dentro: cada l\u00EDnea se desagrega con su propia tasa\n * (`base = precio / (1 + tasa)`), no con una tasa promedio \u2014 promediar tasas\n * distintas devuelve una base que no corresponde a ninguna de ellas.\n */\nexport function calculateInvoiceTotals(\n    items: InvoiceItemInput[],\n    opts: { ivaIncluido?: boolean; descuento?: DescuentoInput | null } & RoundingOptions = {},\n): InvoiceTotals {\n    const ivaIncluido = opts.ivaIncluido === true;\n    const decimals = opts.roundLines;\n    if (decimals !== undefined && !(Number.isInteger(decimals) && decimals >= 0 && decimals <= 4)) {\n        throw new RangeError(`calculateInvoiceTotals: roundLines debe ser un entero entre 0 y 4 (recibido: ${decimals}).`);\n    }\n    if (opts.taxRounding !== undefined && opts.taxRounding !== 'line' && opts.taxRounding !== 'document') {\n        throw new RangeError(`calculateInvoiceTotals: taxRounding inv\u00E1lido (${String(opts.taxRounding)}).`);\n    }\n    const r = (n: number) => (decimals === undefined ? n : roundTo(n, decimals));\n    const previas = items.map((raw) => {\n        const it = sanitizeItem(raw);\n        const rate = Number(raw.tax_rate ?? 0);\n        // Mismo criterio que calculateTotals: una tasa fuera de rango es un\n        // error de programaci\u00F3n, y un 500 expl\u00EDcito le gana a una factura con\n        // impuestos mal calculados que nadie audita hasta la auditor\u00EDa.\n        if (!Number.isFinite(rate) || rate < 0 || rate > 1) {\n            throw new RangeError(`calculateInvoiceTotals: tax_rate debe estar entre 0 y 1 (recibido: ${raw.tax_rate}).`);\n        }\n        const precioFinal = it.precio_negociado ?? it.precio_unitario ?? 0;\n        // Importe bruto en los t\u00E9rminos capturados (con impuesto si los precios\n        // lo incluyen). Con redondeo, ya en los decimales de la divisa.\n        const bruto = decimals === undefined ? precioFinal * it.cantidad : r(precioFinal * it.cantidad);\n        return { it, rate, precioFinal, bruto };\n    });\n    // Lo que le toca a cada l\u00EDnea del descuento de documento, en los mismos\n    // t\u00E9rminos que su importe bruto. Sin descuento, ceros: la aritm\u00E9tica de\n    // abajo queda id\u00E9ntica a la de siempre.\n    const rebajas = repartirDescuento(previas.map((p) => p.bruto), opts.descuento, decimals);\n\n    const netos: number[] = [];\n    const lineas: InvoiceItem[] = previas.map(({ it, rate, precioFinal, bruto }, i) => {\n        const rebaja = rebajas[i];\n        const neto = rebaja === 0 ? bruto : (decimals === undefined ? bruto - rebaja : r(bruto - rebaja));\n        netos.push(neto);\n        let base: number;\n        let impuesto: number;\n        let descuento: number;\n        if (decimals === undefined) {\n            base = ivaIncluido ? neto / (1 + rate) : neto;\n            impuesto = ivaIncluido ? neto - base : base * rate;\n            descuento = ivaIncluido ? rebaja / (1 + rate) : rebaja;\n        } else {\n            // Con redondeo, el impuesto SIEMPRE es base \u00D7 tasa redondeado \u2014\n            // tambi\u00E9n con precio con impuesto incluido\u2014, que es lo que el PAC y\n            // la AEAT recalculan por su cuenta. Desagregar `bruto \u2212 base`\n            // pod\u00EDa dejar el impuesto un centavo distinto del que el proveedor\n            // fiscal calcula para esa misma base.\n            base = ivaIncluido ? r(neto / (1 + rate)) : neto;\n            impuesto = r(base * rate);\n            // Lo que baj\u00F3 la base: base bruta desagregada menos la neta. As\u00ED\n            // `base + descuento` es exactamente la base que tendr\u00EDa la l\u00EDnea\n            // sin descuento.\n            descuento = rebaja === 0 ? 0 : (ivaIncluido ? r(r(bruto / (1 + rate)) - base) : rebaja);\n        }\n        return {\n            ...it,\n            tax_rate: rate,\n            precio_final: precioFinal,\n            base,\n            impuesto,\n            total: r(base + impuesto),\n            descuento,\n        };\n    });\n\n    // Impuesto por documento (RoundingOptions.taxRounding): por cada tasa, la\n    // base y el impuesto del documento se redondean UNA vez y se reparten\n    // entre sus l\u00EDneas por mayor residuo, as\u00ED que todo lo que suma (subtotal,\n    // impuestos, desglose por tasa, retenciones) sale de las mismas l\u00EDneas.\n    if (decimals !== undefined && opts.taxRounding === 'document') {\n        const grupos = new Map<number, number[]>();\n        lineas.forEach((l, i) => {\n            const key = Math.round(l.tax_rate * 1e9) / 1e9;\n            grupos.set(key, [...(grupos.get(key) ?? []), i]);\n        });\n        for (const indices of grupos.values()) {\n            const rate = lineas[indices[0]].tax_rate;\n            if (ivaIncluido) {\n                const exactas = indices.map((i) => netos[i] / (1 + rate));\n                const bases = repartirPorResiduo(r(exactas.reduce((s, v) => s + v, 0)), exactas, decimals);\n                indices.forEach((i, k) => {\n                    const l = lineas[i];\n                    l.base = bases[k];\n                    l.descuento = rebajas[i] === 0 ? 0 : Math.max(0, r(r(previas[i].bruto / (1 + rate)) - l.base));\n                });\n            }\n            const baseTasa = r(indices.reduce((s, i) => s + lineas[i].base, 0));\n            const impuestos = repartirPorResiduo(r(baseTasa * rate), indices.map((i) => lineas[i].base * rate), decimals);\n            indices.forEach((i, k) => {\n                const l = lineas[i];\n                l.impuesto = impuestos[k];\n                l.total = r(l.base + l.impuesto);\n            });\n        }\n    }\n\n    const subtotal = r(lineas.reduce((sum, l) => sum + l.base, 0));\n    const impuestos = r(lineas.reduce((sum, l) => sum + l.impuesto, 0));\n    const descuentoTotal = r(lineas.reduce((sum, l) => sum + l.descuento, 0));\n\n    // Agrupado por tasa, en orden ascendente: el exento primero, como se lee en\n    // cualquier factura. Se agrupa sobre el n\u00FAmero crudo, no sobre el\n    // redondeado, para que el desglose sume exactamente el total.\n    //\n    // La CLAVE del mapa s\u00ED se redondea a 9 decimales (misma tolerancia que\n    // `close()` en impuestos.ts e impuestos-db.ts): dos l\u00EDneas con 0.10667 y\n    // 0.106670000000001 \u2014el mismo 10.667% mexicano, uno capturado a mano y\n    // otro venido de `tasa/100` sobre un `numeric` de Neon\u2014 son la MISMA tasa\n    // y deben sumar en la misma fila del desglose, no separarse en dos filas\n    // que impriman el mismo porcentaje.\n    const mapa = new Map<number, TaxBreakdown>();\n    for (const l of lineas) {\n        const key = Math.round(l.tax_rate * 1e9) / 1e9;\n        const acc = mapa.get(key) ?? { tasa: l.tax_rate, base: 0, impuesto: 0 };\n        acc.base = r(acc.base + l.base);\n        acc.impuesto = r(acc.impuesto + l.impuesto);\n        mapa.set(key, acc);\n    }\n\n    return {\n        lineas,\n        subtotal,\n        impuestos,\n        total: r(subtotal + impuestos),\n        porTasa: [...mapa.values()].sort((a, b) => a.tasa - b.tasa),\n        ivaIncluido,\n        descuentoTotal,\n    };\n}\n\n// \u2500\u2500 Retenciones \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Un impuesto de consumo se SUMA a la base; una retenci\u00F3n se RESTA del total.\n// Es el mismo dato con signo contrario, y confundirlos no produce un error\n// visible: produce una factura que cuadra consigo misma y no con lo que el\n// cliente realmente debe pagar.\n//\n// Base de c\u00E1lculo: el SUBTOTAL del documento (suma de bases gravables). Es lo\n// correcto para el caso que origin\u00F3 esto \u2014en M\u00E9xico la retenci\u00F3n de IVA es\n// 10.667% del valor de los actos, que es exactamente 2/3 del IVA del 16%\u2014 y es\n// el criterio que cualquier negocio puede verificar en su propia factura. Cord\n// no modela la base especial de cada r\u00E9gimen de cada pa\u00EDs: si un negocio\n// necesita otra base, ajusta la tasa con su contador.\n\nexport interface RetencionInput {\n    /** Nombre en el vocabulario del pa\u00EDs: 'Retenci\u00F3n IVA 10.667%', 'ReteFuente 2,5%'. */\n    nombre: string;\n    /** Fracci\u00F3n, no porcentaje: 0.10667, nunca 10.667. */\n    tasa: number | string;\n    /** Subc\u00F3digo del pa\u00EDs. Solo M\u00E9xico lo usa (lo mapea el CFDI). */\n    tipo?: string;\n    /**\n     * Sobre qu\u00E9 se calcula esta retenci\u00F3n. `'subtotal'` (default) es correcto\n     * para M\u00E9xico, donde la Retenci\u00F3n de IVA (10.667%) es 2/3 del IVA del 16%\n     * calculado sobre el mismo subtotal \u2014 pero no es una ley universal. La\n     * ReteIVA colombiana es 15% DEL IVA, no del subtotal: modelarla como\n     * 'subtotal' calcula 5.26\u00D7 de m\u00E1s (15% de 1,000 = 150, cuando la DIAN\n     * espera 15% de 190 = 28.50). Cord no reimplementa el r\u00E9gimen especial de\n     * cada pa\u00EDs \u2014 esto es la \u00FAnica bifurcaci\u00F3n que necesita para no mentir.\n     */\n    base?: RetencionBase;\n}\n\n/**\n * Base de una retenci\u00F3n:\n * - `'subtotal'`: todas las bases del documento.\n * - `'impuesto'`: el impuesto trasladado (ReteIVA colombiana, 15% DEL IVA).\n * - `'gravado'`: solo las bases de los conceptos que S\u00CD llevan impuesto. Es la\n *   Retenci\u00F3n de IVA mexicana (LIVA art. 1-A): se retiene el IVA que se\n *   traslada, as\u00ED que un concepto exento o a tasa 0 no entra en la base.\n *   Calcularla sobre el subtotal completo reten\u00EDa IVA que nunca se cobr\u00F3.\n */\nexport type RetencionBase = 'subtotal' | 'impuesto' | 'gravado';\n\n/** Normaliza un valor guardado (columna, snapshot, JSON) a una base conocida. */\nexport function retencionBase(value: unknown): RetencionBase {\n    return value === 'impuesto' || value === 'gravado' ? value : 'subtotal';\n}\n\nexport interface RetencionApplied {\n    nombre: string;\n    tipo: string;\n    tasa: number;\n    /** Monto BASE sobre el que se calcul\u00F3 esta retenci\u00F3n (no el tipo \u2014 ver baseTipo). */\n    base: number;\n    monto: number;\n    /**\n     * Sobre qu\u00E9 se calcul\u00F3: 'subtotal' o 'impuesto' (ver RetencionInput.base).\n     * Viaja en el resultado para que un snapshot guardado (retenciones_snapshot)\n     * pueda recalcularse en vivo contra un subtotal nuevo SIN perder de vista\n     * si esta retenci\u00F3n era del tipo \"sobre el IVA\" \u2014 sin esto, recomputar la\n     * ReteIVA colombiana desde su propio snapshot volv\u00EDa a calcularla sobre el\n     * subtotal por default.\n     */\n    baseTipo: RetencionBase;\n}\n\nexport interface DocumentTotals extends InvoiceTotals {\n    retenciones: RetencionApplied[];\n    retencionTotal: number;\n}\n\n/**\n * Totales completos de un documento comercial: impuesto por l\u00EDnea + retenciones.\n *\n * Es el motor \u00DANICO de cotizaciones y facturas nuevas. `calculateTotals` queda\n * como camino heredado porque escribi\u00F3 los totales que hoy viven en producci\u00F3n\n * y cambiar su aritm\u00E9tica los reescribir\u00EDa en silencio; `calculateInvoiceTotals`\n * sigue siendo el caso sin retenciones y esta funci\u00F3n lo envuelve, no lo repite.\n *\n * `total = subtotal + impuestos \u2212 retenciones`, con `subtotal` ya neto del\n * descuento de documento (`descuento`, ver DescuentoInput).\n */\nexport function calculateDocumentTotals(\n    items: InvoiceItemInput[],\n    opts: { ivaIncluido?: boolean; retenciones?: RetencionInput[]; descuento?: DescuentoInput | null } & RoundingOptions = {},\n): DocumentTotals {\n    // Las retenciones se calculan sobre las bases YA descontadas: el descuento\n    // baja el valor de la operaci\u00F3n, y con \u00E9l lo que se retiene.\n    const base = calculateInvoiceTotals(items, {\n        ivaIncluido: opts.ivaIncluido, roundLines: opts.roundLines, taxRounding: opts.taxRounding, descuento: opts.descuento,\n    });\n    const rnd = (n: number) => (opts.roundLines === undefined ? n : roundTo(n, opts.roundLines));\n\n    const retenciones: RetencionApplied[] = (opts.retenciones ?? []).map((r) => {\n        const tasa = Number(r.tasa);\n        // Mismo criterio que el resto del motor: una tasa fuera de rango es un\n        // error de programaci\u00F3n, y un 500 expl\u00EDcito le gana a un documento con\n        // una retenci\u00F3n mal calculada que nadie audita hasta la auditor\u00EDa.\n        if (!Number.isFinite(tasa) || tasa < 0 || tasa > 1) {\n            throw new RangeError(`calculateDocumentTotals: la tasa de retenci\u00F3n debe estar entre 0 y 1 (recibido: ${r.tasa}).`);\n        }\n        const baseTipo = retencionBase(r.base);\n        const baseAmount = baseTipo === 'impuesto' ? base.impuestos\n            : baseTipo === 'gravado' ? rnd(base.lineas.reduce((sum, l) => sum + (l.tax_rate > 0 ? l.base : 0), 0))\n            : base.subtotal;\n        return {\n            nombre: String(r.nombre ?? '').slice(0, 80),\n            tipo: String(r.tipo ?? 'ret_iva'),\n            tasa,\n            base: baseAmount,\n            monto: rnd(baseAmount * tasa),\n            baseTipo,\n        };\n    }).filter((ret) => ret.tasa > 0);\n\n    const retencionTotal = rnd(retenciones.reduce((sum, ret) => sum + ret.monto, 0));\n\n    return {\n        ...base,\n        total: rnd(base.total - retencionTotal),\n        retenciones,\n        retencionTotal,\n    };\n}\n", "// Entry principal de @flouviahq/elements (vanilla / Web Component).\n// Importarlo registra autom\u00E1ticamente <cord-cotizador>.\nexport { mountCotizador } from './core.js';\nexport { CordQuoteElement, CordCotizadorElement, CordInvoiceElement, defineCordElements } from './element.js';\nexport { CordFiscalFormElement, defineFiscalElement } from './fiscal-element.js';\nexport { CordAPI, CordError } from './api.js';\nexport {\n    num, sanitizeItem, calculateTotals, roundMoney,\n    calculateInvoiceTotals, calculateDocumentTotals,\n} from './engine.js';\nexport { configureCord, getCordConfig } from './config.js';\nexport { enableDebug, debugLog } from './debug.js';\nexport type {\n    EngineItem, EngineItemInput, EngineTotals,\n    InvoiceItemInput, InvoiceItem, InvoiceTotals, TaxBreakdown,\n    RetencionInput, RetencionApplied, RetencionBase, DocumentTotals, DescuentoInput, RoundingOptions, TaxRounding,\n} from './engine.js';\nexport type { CordGlobalConfig } from './config.js';\nexport type { CordErrorCode } from './api.js';\nexport type { CordLocale } from './locale.js';\nexport type {\n    CordAppearance,\n    CordAppearanceVariables,\n    CordElementOptions,\n    CordController,\n    CordEventDetail,\n    CordEvent,\n    CordReadyDetail,\n    CordViewedDetail,\n    CordApprovedDetail,\n    CordSignedDetail,\n    CordRejectedDetail,\n    CordMessageDetail,\n    CordItemCommentDetail,\n    CordPayDetail,\n    CordUpdatedDetail,\n    CordStatusChangedDetail,\n    CordPaidDetail,\n    CordProduct,\n    CordClient,\n    QuoteStatus,\n    Terminos,\n    NivelCliente,\n    QuoteItemInput,\n    CreateQuoteInput,\n    CreateQuoteResponse,\n    CreateClientInput,\n    CreateProductInput,\n    CreateResponse,\n    PaginatedResponse\n} from './types.js';\nexport type { CordElements, CordElementKey } from './elements.js';\n\nimport { defineCordElements } from './element.js';\nimport { defineFiscalElement } from './fiscal-element.js';\n// Auto-registro al importar (no-op en SSR / sin customElements).\ndefineCordElements();\ndefineFiscalElement();\n"],
  "mappings": "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",
  "names": ["INTL_TAG", "cordLocale", "value", "base", "MAX", "entries", "listeners", "enabled", "TEXT", "host", "keys", "size", "max", "localeOverride", "debugText", "localeOverride", "TEXT", "cordLocale", "enableDebug", "publishableKey", "debugText", "enabled", "mountPanel", "debugLog", "kind", "summary", "detail", "entries", "safeJson", "MAX", "l", "listeners", "v", "CSS", "root", "style", "panel", "head", "title", "clear", "toggle", "labels", "t", "list", "render", "empty", "e", "row", "meta", "sum", "pre", "DEFAULT_ORIGIN", "globalConfig", "configureCord", "config", "enableDebug", "getCordConfig", "resolveOrigin", "explicit", "resolveApiBase", "VARIABLES", "APPEARANCE_VARIABLES", "APPEARANCE_SELECTORS", "RULE_PROPERTIES", "APPEARANCE_RULE_PROPERTIES", "FONT_HOSTS", "MAX_FONTS", "MAX_RULES", "MAX_APPEARANCE_BYTES", "COLOR", "LENGTH", "FONT_FAMILY", "SPACING", "FORBIDDEN", "validValue", "kind", "value", "fontUrl", "src", "u", "href", "cssVariableName", "key", "m", "sanitizeAppearance", "input", "_a", "out", "a", "fontFamily", "raw", "f", "i", "fam", "selector", "decls", "declarations", "prop", "createStore", "initial", "state", "listeners", "next", "value", "l", "listener", "INITIAL_QUOTE_VIEW", "PAID", "reduceQuoteView", "state", "event", "_a", "_b", "_c", "_d", "_e", "_f", "_g", "next", "d", "STYLE_ID", "FRAME_TITLE", "REDUCED", "RELAYED", "EMBED_CSS", "injectStyles", "root", "st", "shadow", "sheet", "MAX_HEIGHT", "isDev", "mountCotizador", "target", "opts", "styleRoot", "_a", "_b", "_c", "rejected", "sanitizeAppearance", "debugText", "debugLog", "state", "createStore", "INITIAL_QUOTE_VIEW", "base", "resolveOrigin", "origin", "minH", "skeleton", "params", "appearanceJson", "MAX_APPEARANCE_BYTES", "query", "iframe", "invoice", "cordLocale", "ready", "reveal", "onMessage", "ev", "_d", "_e", "_f", "_g", "_h", "_i", "_j", "_k", "data", "h", "evt", "prev", "reduceQuoteView", "onLoad", "ElementBase", "HOST_CSS", "CordQuoteElement", "INITIAL_QUOTE_VIEW", "value", "style", "_a", "_b", "attr", "getCordConfig", "token", "enableDebug", "minAttr", "emit", "name", "detail", "mountCotizador", "event", "s", "CordCotizadorElement", "CordInvoiceElement", "defineCordElements", "tag", "RFC_RE", "RFC_DICT", "RFC_GENERICOS", "normalizeRfc", "value", "rfcCheckDigit", "rfc", "base", "sum", "i", "validDate", "yy", "mm", "dd", "m", "d", "daysInMonth", "validRfc", "rfcPersona", "NIF_LETTERS", "cleanEs", "validNif", "validNie", "prefix", "CIF_DIGIT_ONLY", "CIF_LETTER_ONLY", "CIF_CONTROL_LETTERS", "validCif", "letter", "digits", "control", "sumEven", "sumOdd", "controlDigit", "controlLetter", "validSpainTaxId", "clean", "EIN_NO_ASIGNADOS", "validEin", "v", "fmt", "chk", "k", "pre", "s", "digit", "luhn", "t", "n", "weighted", "weights", "mod11Dv", "cycle", "r", "mod1110", "p", "AR_PE_WEIGHTS", "CO_WEIGHTS", "GB_WEIGHTS", "VALIDATORS", "persona", "kind", "_", "fisica", "area", "g", "tva", "key", "siren", "c", "vat", "gov", "utr", "bn", "dv", "raw", "TAX_ID_COUNTRIES", "cleanTaxIdInput", "matchTaxId", "cc", "check", "checkTaxId", "country", "options", "AMBAS", "REGIMENES_FISCALES", "USOS_CFDI", "regimenesPara", "persona", "r", "usosCfdiPara", "u", "MAX", "REGIME_SUFFIX", "clean", "v", "max", "validateFiscalReceptor", "input", "errors", "warnings", "country", "legalName", "taxId", "regimen", "uso", "cp", "persona", "normalizeRfc", "rfcPersona", "regimenesPara", "r", "usosCfdiPara", "u", "checkTaxId", "TAX_ID_COUNTRIES", "FIELDS_BY_COUNTRY", "createFiscalForm", "initial", "_a", "_b", "_c", "_d", "_e", "values", "store", "createStore", "derive", "field", "value", "s", "next", "validateFiscalReceptor", "touched", "submitted", "validation", "persona", "generico", "e", "regimenesPara", "r", "usosCfdiPara", "u", "TAX_ID", "LABELS", "ISSUES", "fiscalText", "locale", "l", "cordLocale", "field", "country", "name", "code", "_a", "ElementBase", "CSS", "FIELD_INPUT", "CordFiscalFormElement", "internals", "_a", "_b", "s", "values", "k", "v", "style", "name", "cordLocale", "prev", "createFiscalForm", "t", "fiscalText", "field", "key", "id", "wrap", "label", "control", "msg", "_c", "_d", "options", "wanted", "o", "error", "e", "warning", "w", "first", "anchor", "defineFiscalElement", "CordError", "status", "payload", "code", "requestId", "resolvedCode", "IS_BROWSER", "unwrapEnvelope", "body", "CordAPI", "apiKey", "baseUrl", "data", "options", "params", "query", "key", "resolveApiBase", "path", "init", "opts", "unwrap", "response", "err", "num", "v", "fallback", "n", "sanitizeItem", "it", "_a", "nego", "q", "roundMoney", "dp", "f", "calculateTotals", "items", "ivaPct", "ivaIncluido", "_b", "sanitized", "sumPrecios", "p", "subtotal", "iva", "total", "roundTo", "decimals", "repartirPorResiduo", "exactos", "meta", "x", "pisos", "resto", "orden", "_", "i", "a", "b", "k", "repartirDescuento", "brutos", "d", "valor", "bruto", "s", "deseado", "u", "tu", "D", "calculateInvoiceTotals", "opts", "r", "previas", "raw", "_c", "rate", "precioFinal", "rebajas", "netos", "lineas", "rebaja", "neto", "base", "impuesto", "descuento", "grupos", "l", "key", "indices", "exactas", "bases", "baseTasa", "impuestos", "sum", "descuentoTotal", "mapa", "acc", "retencionBase", "value", "calculateDocumentTotals", "rnd", "retenciones", "tasa", "baseTipo", "baseAmount", "ret", "retencionTotal", "defineCordElements", "defineFiscalElement"]
}
