@orangecheck/auth-client 2.33.4 → 2.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/appearance.mjs +23 -0
  2. package/dist/appearance.mjs.map +1 -0
  3. package/dist/bond.mjs +20 -0
  4. package/dist/bond.mjs.map +1 -0
  5. package/dist/chunk-7ST4Q5KR.mjs +346 -0
  6. package/dist/chunk-7ST4Q5KR.mjs.map +1 -0
  7. package/dist/chunk-7UYPMTAV.mjs +652 -0
  8. package/dist/chunk-7UYPMTAV.mjs.map +1 -0
  9. package/dist/chunk-BYAF2P2L.mjs +253 -0
  10. package/dist/chunk-BYAF2P2L.mjs.map +1 -0
  11. package/dist/chunk-CYR7J4UY.mjs +118 -0
  12. package/dist/chunk-CYR7J4UY.mjs.map +1 -0
  13. package/dist/chunk-D3HXJ64H.mjs +914 -0
  14. package/dist/chunk-D3HXJ64H.mjs.map +1 -0
  15. package/dist/chunk-FDWEXEZL.mjs +490 -0
  16. package/dist/chunk-FDWEXEZL.mjs.map +1 -0
  17. package/dist/chunk-H2TXOCXH.mjs +23 -0
  18. package/dist/chunk-H2TXOCXH.mjs.map +1 -0
  19. package/dist/chunk-IQVBEYSW.mjs +1172 -0
  20. package/dist/chunk-IQVBEYSW.mjs.map +1 -0
  21. package/dist/chunk-TJJNTITX.mjs +187 -0
  22. package/dist/chunk-TJJNTITX.mjs.map +1 -0
  23. package/dist/chunk-VRLFZAGK.mjs +37 -0
  24. package/dist/chunk-VRLFZAGK.mjs.map +1 -0
  25. package/dist/chunk-XCZVSE7M.mjs +40 -0
  26. package/dist/chunk-XCZVSE7M.mjs.map +1 -0
  27. package/dist/components.mjs +19 -0
  28. package/dist/components.mjs.map +1 -0
  29. package/dist/index.mjs +112 -4001
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/linked-identities.mjs +41 -0
  32. package/dist/linked-identities.mjs.map +1 -0
  33. package/dist/provider.mjs +17 -0
  34. package/dist/provider.mjs.map +1 -0
  35. package/dist/return-to.mjs +18 -0
  36. package/dist/return-to.mjs.map +1 -0
  37. package/dist/signin.mjs +21 -0
  38. package/dist/signin.mjs.map +1 -0
  39. package/dist/sudo.mjs +16 -0
  40. package/dist/sudo.mjs.map +1 -0
  41. package/dist/tab-session.mjs +29 -0
  42. package/dist/tab-session.mjs.map +1 -0
  43. package/dist/types.mjs +17 -0
  44. package/dist/types.mjs.map +1 -0
  45. package/dist/webauthn.mjs +15 -0
  46. package/dist/webauthn.mjs.map +1 -0
  47. package/package.json +2 -1
  48. package/dist/index.d.mts +0 -303
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/bond.tsx"],"sourcesContent":["'use client';\n\n/**\n * OcBond · back the signed-in account with bitcoin (oc-attest-protocol\n * BOND.md). The person signs for one coin they hold. It stays in their wallet,\n * and spending it ends the backing. Apps they sign in to see floors and a\n * number unique to that app, never the coin. Optional: every account signs in\n * without one.\n *\n * Runs against the auth host's /api/auth/bond with the family cookie, like\n * OcLinkedIdentities, so any *.ochk.io site can mount it. A change re-mints\n * the session there, and a tab pinned to this account re-pins with the fresh\n * token; `onChange` lets the site refresh its session view.\n */\nimport * as React from 'react';\n\nimport { SIGNIN_FONT } from './appearance';\nimport {\n bodyStyle,\n dangerBtnStyle,\n ErrorLine,\n FormButtons,\n ghostBtnStyle,\n hintStyle,\n inputStyle,\n LazyWalletButton,\n panelStyle,\n primaryBtnStyle,\n SectionLabel,\n V,\n} from './linked-identities';\nimport { readTabSession, writeTabSession } from './tab-session';\n\nconst DEFAULT_AUTH_ORIGIN = 'https://ochk.io';\nconst MIN_CONFIRMATIONS = 6;\n/** Smaller coins meet no floor, so the auth host refuses them (`coin_too_small`). */\nconst MIN_SATS = 1_000;\n\ninterface Floors {\n sats_floor: number;\n days_floor: number;\n}\n\n/** The account's bond as the auth host shows it to the account itself. */\nexport interface OcBondView extends Floors {\n address: string;\n outpoint: string;\n sats: number;\n confirmed_height: number;\n checked_at: string;\n checked_height: number;\n created_at: string;\n}\n\ninterface Coin extends Floors {\n outpoint: string;\n sats: number;\n age_blocks: number;\n}\n\nexport interface OcBondProps {\n /** The auth host. Default https://ochk.io; pass the current origin on ochk.io itself. */\n authOrigin?: string;\n /** After a bond is made or released, so the site can refresh its session. */\n onChange?: (bond: OcBondView | null) => void;\n className?: string;\n}\n\nconst n = (v: number) => v.toLocaleString('en-US');\n\n/** \"at least 100,000 sats, held 90 days or more\". */\nexport function bondFloorsText(f: Floors): string {\n const sats = f.sats_floor > 0 ? `at least ${n(f.sats_floor)} sats` : 'under 1,000 sats';\n const days = f.days_floor > 0 ? `held ${f.days_floor} days or more` : 'held under 7 days';\n return `${sats}, ${days}`;\n}\n\nconst short = (outpoint: string) => {\n const [txid = '', vout = ''] = outpoint.split(':');\n return `${txid.slice(0, 8)}…${txid.slice(-4)}:${vout}`;\n};\n\nconst usable = (c: Coin) => c.sats >= MIN_SATS && c.age_blocks >= MIN_CONFIRMATIONS;\n\nconst dustText = (count: number) =>\n `${n(count)} ${count === 1 ? 'coin' : 'coins'} under ${n(MIN_SATS)} sats, ` +\n 'too small to back an account';\n\nconst REFUSAL: Record<string, string> = {\n invalid_address: \"that isn't a Bitcoin address we can read\",\n chain_unavailable: \"couldn't read the chain just now · nothing changed, try again in a minute\",\n sig_invalid:\n \"that signature isn't from this coin's address · sign with the wallet that holds it\",\n bond_expired: 'the message expired · start again',\n bond_not_yet_valid: \"your device's clock looks wrong · check it and start again\",\n bond_subject_mismatch: 'that message was for another account · start again',\n bond_malformed: 'the signed message changed on the way · start again',\n bond_window_too_long: \"that message's signing window is too long · start again\",\n coin_not_found: \"that coin doesn't exist on-chain\",\n coin_address_mismatch: \"that coin isn't at this address\",\n coin_unconfirmed: \"that coin isn't confirmed yet\",\n coin_too_recent: 'that coin needs six confirmations first, about an hour',\n coin_spent: 'that coin has been spent · pick one still in your wallet',\n coin_too_small: `that coin is under ${n(MIN_SATS)} sats, too small to back an account`,\n coin_backs_another_account: 'that coin already backs another orangecheck account',\n coin_backed_another_recently:\n 'that coin backed another account until recently · ' +\n 'it can back this one 30 days after it was released',\n not_authenticated: 'your session ended · sign in again',\n rate_limited: 'too many tries · wait a minute, then try again',\n};\n\n/** A refusal from /api/auth/bond, in the component's voice. Not exported from the index. */\nexport const bondRefusal = (reason?: string): string =>\n (reason && REFUSAL[reason]) || \"your backing didn't save · nothing changed, try again\";\n\n/* Small print stays legible: 12px or more, and never dimmed below the muted tone. */\nconst smallStyle: React.CSSProperties = { ...bodyStyle, fontSize: 12, margin: 0 };\nconst explainerStyle: React.CSSProperties = {\n ...hintStyle,\n fontSize: 12,\n lineHeight: 1.55,\n opacity: 1,\n margin: 0,\n};\nconst fieldLabelStyle: React.CSSProperties = {\n display: 'block',\n color: V.foreground,\n fontSize: 13,\n fontWeight: 500,\n margin: '0 0 4px',\n};\nconst addressStyle: React.CSSProperties = { wordBreak: 'break-all', color: V.foreground };\n\nfunction coinStyle(picked: boolean, young: boolean): React.CSSProperties {\n return {\n background: V.card,\n border: `1px ${young ? 'dashed' : 'solid'} ${picked ? V.primary : V.border}`,\n padding: '0.75rem',\n display: 'flex',\n gap: 10,\n alignItems: 'flex-start',\n cursor: young ? 'not-allowed' : 'pointer',\n };\n}\n\n/** The account's bond, or null. Throws when the auth host can't be read. */\nexport async function fetchOcBond(opts?: { authOrigin?: string }): Promise<OcBondView | null> {\n const r = await fetch(`${opts?.authOrigin ?? DEFAULT_AUTH_ORIGIN}/api/auth/bond`, {\n credentials: 'include',\n });\n const j = (await r.json().catch(() => ({}))) as { ok?: boolean; bond?: OcBondView | null };\n if (!r.ok || !j.ok) throw new Error(`http_${r.status}`);\n return j.bond ?? null;\n}\n\nexport function OcBond({\n authOrigin = DEFAULT_AUTH_ORIGIN,\n onChange,\n className,\n}: OcBondProps): React.ReactElement {\n const [bond, setBond] = React.useState<OcBondView | null | undefined>(undefined);\n const [loadErr, setLoadErr] = React.useState(false);\n const [nonce, setNonce] = React.useState(0);\n const [adding, setAdding] = React.useState(false);\n const [confirming, setConfirming] = React.useState(false);\n const [busy, setBusy] = React.useState(false);\n const [err, setErr] = React.useState<string | null>(null);\n\n React.useEffect(() => {\n let alive = true;\n fetchOcBond({ authOrigin }).then(\n (b) => alive && setBond(b),\n () => alive && setLoadErr(true)\n );\n return () => {\n alive = false;\n };\n }, [authOrigin, nonce]);\n\n const call = React.useCallback(\n async (method: string, body?: unknown) => {\n const r = await fetch(`${authOrigin}/api/auth/bond`, {\n method,\n credentials: 'include',\n headers: body ? { 'Content-Type': 'application/json' } : undefined,\n body: body ? JSON.stringify(body) : undefined,\n });\n const j = (await r.json().catch(() => ({}))) as Record<string, unknown> & {\n ok?: boolean;\n reason?: string;\n token?: unknown;\n };\n // The host minted for the account this tab shows; keep the pin current.\n const pin = readTabSession();\n if (pin && r.ok && typeof j.token === 'string') {\n writeTabSession({ token: j.token, didOc: pin.didOc });\n }\n return { ok: r.ok && j.ok === true, ...j };\n },\n [authOrigin]\n );\n\n async function release(): Promise<void> {\n setBusy(true);\n setErr(null);\n const j = await call('DELETE').catch(() => ({ ok: false, reason: 'network' }));\n setBusy(false);\n if (!j.ok) return setErr(bondRefusal(j.reason));\n setConfirming(false);\n setBond(null);\n onChange?.(null);\n }\n\n if (loadErr) {\n return (\n <div className={className} data-oc-bond=\"\" style={panelStyle('warn')} role=\"alert\">\n <p style={bodyStyle}>couldn&apos;t read your backing · nothing was changed</p>\n <button\n type=\"button\"\n style={ghostBtnStyle(false)}\n onClick={() => {\n setLoadErr(false);\n setNonce((x) => x + 1);\n }}\n >\n try again\n </button>\n </div>\n );\n }\n if (bond === undefined) {\n return (\n <div className={className} data-oc-bond=\"\" style={panelStyle()}>\n <span style={hintStyle}>reading your backing…</span>\n </div>\n );\n }\n\n return (\n <div className={className} data-oc-bond=\"\" style={{ display: 'grid', gap: 16 }}>\n {bond && !adding ? (\n <div style={panelStyle('success')}>\n <SectionLabel tone=\"success\">§ backed by bitcoin</SectionLabel>\n <p style={{ ...bodyStyle, color: V.foreground }}>\n apps see a coin {bondFloorsText(bond)}.\n </p>\n <p style={bodyStyle}>\n coin {short(bond.outpoint)}, {n(bond.sats)} sats · last found unspent at\n block {n(bond.checked_height)} · only you and orangecheck see this line\n </p>\n {confirming ? (\n <div role=\"group\" aria-label=\"stop backing\" data-oc-bond-confirm=\"\">\n <p style={{ ...bodyStyle, color: V.foreground, margin: 0 }}>\n stop backing? apps that ask for a backed account may stop letting\n you in.\n </p>\n <FormButtons>\n <button\n type=\"button\"\n style={dangerBtnStyle(busy)}\n disabled={busy}\n onClick={() => void release()}\n >\n stop backing\n </button>\n <button\n type=\"button\"\n style={ghostBtnStyle(busy)}\n disabled={busy}\n autoFocus\n onClick={() => {\n setErr(null);\n setConfirming(false);\n }}\n >\n keep\n </button>\n </FormButtons>\n </div>\n ) : (\n <FormButtons>\n <button\n type=\"button\"\n style={ghostBtnStyle(false)}\n onClick={() => {\n setErr(null);\n setAdding(true);\n }}\n >\n use another coin\n </button>\n <button\n type=\"button\"\n style={dangerBtnStyle(false)}\n onClick={() => setConfirming(true)}\n >\n stop backing\n </button>\n </FormButtons>\n )}\n {err ? <ErrorLine>{err}</ErrorLine> : null}\n </div>\n ) : null}\n {!bond && !adding ? (\n <div style={panelStyle()}>\n <SectionLabel>§ not backed</SectionLabel>\n <p style={bodyStyle}>\n your account works everywhere as it is. some apps let in only accounts\n backed by a coin you hold. it stays in your wallet, and apps never see\n which coin.\n </p>\n <button\n type=\"button\"\n style={primaryBtnStyle(false)}\n onClick={() => setAdding(true)}\n >\n back your account\n </button>\n </div>\n ) : null}\n {adding ? (\n <BondForm\n call={call}\n onCancel={() => setAdding(false)}\n onDone={(b) => {\n setBond(b);\n setAdding(false);\n onChange?.(b);\n }}\n />\n ) : null}\n <p style={explainerStyle}>\n Apps see only rough floors, like “at least 100,000 sats, held 30 days or\n more”, and a number unique to that app. Never the coin, your address or your\n balance. An app can block that number; only moving the coin gets past it, and a\n moved coin starts its age again.\n </p>\n </div>\n );\n}\n\ntype Call = (\n method: string,\n body?: unknown\n) => Promise<Record<string, unknown> & { ok: boolean; reason?: string }>;\n\nfunction BondForm({\n call,\n onCancel,\n onDone,\n}: {\n call: Call;\n onCancel: () => void;\n onDone: (bond: OcBondView) => void;\n}): React.ReactElement {\n const [address, setAddress] = React.useState('');\n const [coins, setCoins] = React.useState<Coin[] | null>(null);\n const [chosen, setChosen] = React.useState('');\n const [message, setMessage] = React.useState<string | null>(null);\n const [busy, setBusy] = React.useState(false);\n const [err, setErr] = React.useState<string | null>(null);\n const id = React.useId();\n\n const addr = address.trim();\n const canFind = addr.length >= 14;\n\n async function run(fn: () => Promise<void>): Promise<void> {\n setBusy(true);\n setErr(null);\n try {\n await fn();\n } catch {\n setErr(bondRefusal('chain_unavailable'));\n } finally {\n setBusy(false);\n }\n }\n\n const findCoins = () =>\n run(async () => {\n const j = await call('POST', { action: 'coins', address: addr });\n if (!j.ok) return setErr(bondRefusal(j.reason));\n const list = (j.coins as Coin[]) ?? [];\n setCoins(list);\n setChosen(list.find(usable)?.outpoint ?? '');\n });\n\n const getMessage = () =>\n run(async () => {\n const j = await call('POST', { action: 'message', address: addr, outpoint: chosen });\n if (!j.ok || typeof j.message !== 'string') return setErr(bondRefusal(j.reason));\n setMessage(j.message);\n });\n\n const submit = (signature: string) =>\n run(async () => {\n const j = await call('POST', { action: 'bond', message, signature });\n if (!j.ok || !j.bond) return setErr(bondRefusal(j.reason));\n onDone(j.bond as OcBondView);\n });\n\n /** Back one step: from signing to the coin list, or from the coins to the address. */\n function back(): void {\n setErr(null);\n if (message) setMessage(null);\n else setCoins(null);\n }\n\n const error = err ? <ErrorLine>{err}</ErrorLine> : null;\n const backButton = (\n <button type=\"button\" style={ghostBtnStyle(busy)} disabled={busy} onClick={back}>\n back\n </button>\n );\n const cancelButton = (\n <button type=\"button\" style={ghostBtnStyle(busy)} disabled={busy} onClick={onCancel}>\n cancel\n </button>\n );\n\n let step: React.ReactNode;\n if (message) {\n step = (\n <>\n <p style={bodyStyle}>\n sign with the wallet that holds <span style={addressStyle}>{addr}</span>.\n signing spends nothing, and the coin stays in your wallet.\n </p>\n <LazyWalletButton\n address={addr}\n message={message}\n showManual\n onSigned={(sig) => void submit(sig)}\n onError={(e) => setErr(e.message ?? 'the wallet refused to sign')}\n />\n {error}\n <FormButtons>\n {backButton}\n {cancelButton}\n </FormButtons>\n </>\n );\n } else if (coins) {\n const eligible = coins.filter((c) => c.sats >= MIN_SATS);\n const dust = coins.length - eligible.length;\n step = (\n <>\n {coins.length === 0 ? (\n <p style={bodyStyle}>\n no confirmed coins at that address · send at least {n(MIN_SATS)} sats\n there and wait for six confirmations, about an hour. the longer a coin\n sits, the more it says.\n </p>\n ) : eligible.length === 0 ? (\n <>\n <p style={{ ...bodyStyle, color: V.foreground }}>{dustText(dust)}</p>\n <p style={bodyStyle}>\n send at least {n(MIN_SATS)} sats there in one payment and wait for six\n confirmations, about an hour. coins aren&apos;t added together.\n </p>\n </>\n ) : (\n <>\n <p id={`${id}-pick`} style={bodyStyle}>\n pick one coin · coins aren&apos;t added together\n </p>\n <div\n role=\"radiogroup\"\n aria-labelledby={`${id}-pick`}\n style={{ display: 'grid', gap: 8 }}\n >\n {eligible.map((c) => {\n const young = c.age_blocks < MIN_CONFIRMATIONS;\n return (\n <label\n key={c.outpoint}\n style={coinStyle(chosen === c.outpoint, young)}\n >\n <input\n type=\"radio\"\n name=\"oc-bond-coin\"\n value={c.outpoint}\n checked={chosen === c.outpoint}\n disabled={young}\n onChange={() => setChosen(c.outpoint)}\n style={{ accentColor: V.primary, margin: '2px 0 0' }}\n />\n <span style={{ display: 'grid', gap: 2, minWidth: 0 }}>\n <span\n style={{\n color: young ? V.muted : V.foreground,\n fontSize: 13,\n }}\n >\n {n(c.sats)} sats, held{' '}\n {Math.floor(c.age_blocks / 144)} days\n </span>\n <span style={smallStyle}>\n {young\n ? 'too recent: needs six confirmations'\n : `apps would see ${bondFloorsText(c)}`}\n </span>\n <span\n style={{\n ...smallStyle,\n fontFamily: SIGNIN_FONT,\n wordBreak: 'break-all',\n }}\n >\n {short(c.outpoint)}\n </span>\n </span>\n </label>\n );\n })}\n </div>\n {dust > 0 ? (\n <p style={{ ...smallStyle, marginTop: 8 }}>{dustText(dust)}</p>\n ) : null}\n </>\n )}\n {error}\n <FormButtons>\n {eligible.length > 0 ? (\n <button\n type=\"button\"\n style={primaryBtnStyle(busy || !chosen)}\n disabled={busy || !chosen}\n onClick={() => void getMessage()}\n >\n continue\n </button>\n ) : null}\n {backButton}\n {cancelButton}\n </FormButtons>\n </>\n );\n } else {\n step = (\n <form\n style={{ margin: 0 }}\n onSubmit={(e) => {\n e.preventDefault();\n if (canFind && !busy) void findCoins();\n }}\n >\n <label htmlFor={`${id}-address`} style={fieldLabelStyle}>\n bitcoin address that holds the coin\n </label>\n <p id={`${id}-advice`} style={{ ...bodyStyle, margin: '0 0 8px' }}>\n use one that holds nothing else of yours: orangecheck learns its address and\n amount. apps never do.\n </p>\n <input\n id={`${id}-address`}\n aria-describedby={`${id}-advice`}\n style={inputStyle}\n value={address}\n onChange={(e) => setAddress(e.target.value)}\n placeholder=\"bc1q…\"\n spellCheck={false}\n autoComplete=\"off\"\n autoCapitalize=\"off\"\n />\n {error}\n <FormButtons>\n <button\n type=\"submit\"\n style={primaryBtnStyle(busy || !canFind)}\n disabled={busy || !canFind}\n >\n find its coins\n </button>\n {cancelButton}\n </FormButtons>\n </form>\n );\n }\n\n return (\n <div style={panelStyle('accent')} data-oc-bond-form=\"\">\n <SectionLabel>§ back your account</SectionLabel>\n {step}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAcA,YAAY,WAAW;AA0MX,SAgNA,UA/MI,KADJ;AAvLZ,IAAM,sBAAsB;AAC5B,IAAM,oBAAoB;AAE1B,IAAM,WAAW;AAgCjB,IAAM,IAAI,CAAC,MAAc,EAAE,eAAe,OAAO;AAG1C,SAAS,eAAe,GAAmB;AAC9C,QAAM,OAAO,EAAE,aAAa,IAAI,YAAY,EAAE,EAAE,UAAU,CAAC,UAAU;AACrE,QAAM,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,UAAU,kBAAkB;AACtE,SAAO,GAAG,IAAI,KAAK,IAAI;AAC3B;AAEA,IAAM,QAAQ,CAAC,aAAqB;AAChC,QAAM,CAAC,OAAO,IAAI,OAAO,EAAE,IAAI,SAAS,MAAM,GAAG;AACjD,SAAO,GAAG,KAAK,MAAM,GAAG,CAAC,CAAC,SAAI,KAAK,MAAM,EAAE,CAAC,IAAI,IAAI;AACxD;AAEA,IAAM,SAAS,CAAC,MAAY,EAAE,QAAQ,YAAY,EAAE,cAAc;AAElE,IAAM,WAAW,CAAC,UACd,GAAG,EAAE,KAAK,CAAC,IAAI,UAAU,IAAI,SAAS,OAAO,UAAU,EAAE,QAAQ,CAAC;AAGtE,IAAM,UAAkC;AAAA,EACpC,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,aACI;AAAA,EACJ,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,uBAAuB;AAAA,EACvB,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB,gBAAgB;AAAA,EAChB,uBAAuB;AAAA,EACvB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,gBAAgB,sBAAsB,EAAE,QAAQ,CAAC;AAAA,EACjD,4BAA4B;AAAA,EAC5B,8BACI;AAAA,EAEJ,mBAAmB;AAAA,EACnB,cAAc;AAClB;AAGO,IAAM,cAAc,CAAC,WACvB,UAAU,QAAQ,MAAM,KAAM;AAGnC,IAAM,aAAkC,EAAE,GAAG,WAAW,UAAU,IAAI,QAAQ,EAAE;AAChF,IAAM,iBAAsC;AAAA,EACxC,GAAG;AAAA,EACH,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,QAAQ;AACZ;AACA,IAAM,kBAAuC;AAAA,EACzC,SAAS;AAAA,EACT,OAAO,EAAE;AAAA,EACT,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,QAAQ;AACZ;AACA,IAAM,eAAoC,EAAE,WAAW,aAAa,OAAO,EAAE,WAAW;AAExF,SAAS,UAAU,QAAiB,OAAqC;AACrE,SAAO;AAAA,IACH,YAAY,EAAE;AAAA,IACd,QAAQ,OAAO,QAAQ,WAAW,OAAO,IAAI,SAAS,EAAE,UAAU,EAAE,MAAM;AAAA,IAC1E,SAAS;AAAA,IACT,SAAS;AAAA,IACT,KAAK;AAAA,IACL,YAAY;AAAA,IACZ,QAAQ,QAAQ,gBAAgB;AAAA,EACpC;AACJ;AAGA,eAAsB,YAAY,MAA4D;AAC1F,QAAM,IAAI,MAAM,MAAM,GAAG,MAAM,cAAc,mBAAmB,kBAAkB;AAAA,IAC9E,aAAa;AAAA,EACjB,CAAC;AACD,QAAM,IAAK,MAAM,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC1C,MAAI,CAAC,EAAE,MAAM,CAAC,EAAE,GAAI,OAAM,IAAI,MAAM,QAAQ,EAAE,MAAM,EAAE;AACtD,SAAO,EAAE,QAAQ;AACrB;AAEO,SAAS,OAAO;AAAA,EACnB,aAAa;AAAA,EACb;AAAA,EACA;AACJ,GAAoC;AAChC,QAAM,CAAC,MAAM,OAAO,IAAU,eAAwC,MAAS;AAC/E,QAAM,CAAC,SAAS,UAAU,IAAU,eAAS,KAAK;AAClD,QAAM,CAAC,OAAO,QAAQ,IAAU,eAAS,CAAC;AAC1C,QAAM,CAAC,QAAQ,SAAS,IAAU,eAAS,KAAK;AAChD,QAAM,CAAC,YAAY,aAAa,IAAU,eAAS,KAAK;AACxD,QAAM,CAAC,MAAM,OAAO,IAAU,eAAS,KAAK;AAC5C,QAAM,CAAC,KAAK,MAAM,IAAU,eAAwB,IAAI;AAExD,EAAM,gBAAU,MAAM;AAClB,QAAI,QAAQ;AACZ,gBAAY,EAAE,WAAW,CAAC,EAAE;AAAA,MACxB,CAAC,MAAM,SAAS,QAAQ,CAAC;AAAA,MACzB,MAAM,SAAS,WAAW,IAAI;AAAA,IAClC;AACA,WAAO,MAAM;AACT,cAAQ;AAAA,IACZ;AAAA,EACJ,GAAG,CAAC,YAAY,KAAK,CAAC;AAEtB,QAAM,OAAa;AAAA,IACf,OAAO,QAAgB,SAAmB;AACtC,YAAM,IAAI,MAAM,MAAM,GAAG,UAAU,kBAAkB;AAAA,QACjD;AAAA,QACA,aAAa;AAAA,QACb,SAAS,OAAO,EAAE,gBAAgB,mBAAmB,IAAI;AAAA,QACzD,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,MACxC,CAAC;AACD,YAAM,IAAK,MAAM,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAM1C,YAAM,MAAM,eAAe;AAC3B,UAAI,OAAO,EAAE,MAAM,OAAO,EAAE,UAAU,UAAU;AAC5C,wBAAgB,EAAE,OAAO,EAAE,OAAO,OAAO,IAAI,MAAM,CAAC;AAAA,MACxD;AACA,aAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,MAAM,GAAG,EAAE;AAAA,IAC7C;AAAA,IACA,CAAC,UAAU;AAAA,EACf;AAEA,iBAAe,UAAyB;AACpC,YAAQ,IAAI;AACZ,WAAO,IAAI;AACX,UAAM,IAAI,MAAM,KAAK,QAAQ,EAAE,MAAM,OAAO,EAAE,IAAI,OAAO,QAAQ,UAAU,EAAE;AAC7E,YAAQ,KAAK;AACb,QAAI,CAAC,EAAE,GAAI,QAAO,OAAO,YAAY,EAAE,MAAM,CAAC;AAC9C,kBAAc,KAAK;AACnB,YAAQ,IAAI;AACZ,eAAW,IAAI;AAAA,EACnB;AAEA,MAAI,SAAS;AACT,WACI,qBAAC,SAAI,WAAsB,gBAAa,IAAG,OAAO,WAAW,MAAM,GAAG,MAAK,SACvE;AAAA,0BAAC,OAAE,OAAO,WAAW,iEAAqD;AAAA,MAC1E;AAAA,QAAC;AAAA;AAAA,UACG,MAAK;AAAA,UACL,OAAO,cAAc,KAAK;AAAA,UAC1B,SAAS,MAAM;AACX,uBAAW,KAAK;AAChB,qBAAS,CAAC,MAAM,IAAI,CAAC;AAAA,UACzB;AAAA,UACH;AAAA;AAAA,MAED;AAAA,OACJ;AAAA,EAER;AACA,MAAI,SAAS,QAAW;AACpB,WACI,oBAAC,SAAI,WAAsB,gBAAa,IAAG,OAAO,WAAW,GACzD,8BAAC,UAAK,OAAO,WAAW,wCAAqB,GACjD;AAAA,EAER;AAEA,SACI,qBAAC,SAAI,WAAsB,gBAAa,IAAG,OAAO,EAAE,SAAS,QAAQ,KAAK,GAAG,GACxE;AAAA,YAAQ,CAAC,SACN,qBAAC,SAAI,OAAO,WAAW,SAAS,GAC5B;AAAA,0BAAC,gBAAa,MAAK,WAAU,oCAAmB;AAAA,MAChD,qBAAC,OAAE,OAAO,EAAE,GAAG,WAAW,OAAO,EAAE,WAAW,GAAG;AAAA;AAAA,QAC5B,eAAe,IAAI;AAAA,QAAE;AAAA,SAC1C;AAAA,MACA,qBAAC,OAAE,OAAO,WAAW;AAAA;AAAA,QACX,MAAM,KAAK,QAAQ;AAAA,QAAE;AAAA,QAAG,EAAE,KAAK,IAAI;AAAA,QAAE;AAAA,QACpC,EAAE,KAAK,cAAc;AAAA,QAAE;AAAA,SAClC;AAAA,MACC,aACG,qBAAC,SAAI,MAAK,SAAQ,cAAW,gBAAe,wBAAqB,IAC7D;AAAA,4BAAC,OAAE,OAAO,EAAE,GAAG,WAAW,OAAO,EAAE,YAAY,QAAQ,EAAE,GAAG,uFAG5D;AAAA,QACA,qBAAC,eACG;AAAA;AAAA,YAAC;AAAA;AAAA,cACG,MAAK;AAAA,cACL,OAAO,eAAe,IAAI;AAAA,cAC1B,UAAU;AAAA,cACV,SAAS,MAAM,KAAK,QAAQ;AAAA,cAC/B;AAAA;AAAA,UAED;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACG,MAAK;AAAA,cACL,OAAO,cAAc,IAAI;AAAA,cACzB,UAAU;AAAA,cACV,WAAS;AAAA,cACT,SAAS,MAAM;AACX,uBAAO,IAAI;AACX,8BAAc,KAAK;AAAA,cACvB;AAAA,cACH;AAAA;AAAA,UAED;AAAA,WACJ;AAAA,SACJ,IAEA,qBAAC,eACG;AAAA;AAAA,UAAC;AAAA;AAAA,YACG,MAAK;AAAA,YACL,OAAO,cAAc,KAAK;AAAA,YAC1B,SAAS,MAAM;AACX,qBAAO,IAAI;AACX,wBAAU,IAAI;AAAA,YAClB;AAAA,YACH;AAAA;AAAA,QAED;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACG,MAAK;AAAA,YACL,OAAO,eAAe,KAAK;AAAA,YAC3B,SAAS,MAAM,cAAc,IAAI;AAAA,YACpC;AAAA;AAAA,QAED;AAAA,SACJ;AAAA,MAEH,MAAM,oBAAC,aAAW,eAAI,IAAe;AAAA,OAC1C,IACA;AAAA,IACH,CAAC,QAAQ,CAAC,SACP,qBAAC,SAAI,OAAO,WAAW,GACnB;AAAA,0BAAC,gBAAa,6BAAY;AAAA,MAC1B,oBAAC,OAAE,OAAO,WAAW,uKAIrB;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACG,MAAK;AAAA,UACL,OAAO,gBAAgB,KAAK;AAAA,UAC5B,SAAS,MAAM,UAAU,IAAI;AAAA,UAChC;AAAA;AAAA,MAED;AAAA,OACJ,IACA;AAAA,IACH,SACG;AAAA,MAAC;AAAA;AAAA,QACG;AAAA,QACA,UAAU,MAAM,UAAU,KAAK;AAAA,QAC/B,QAAQ,CAAC,MAAM;AACX,kBAAQ,CAAC;AACT,oBAAU,KAAK;AACf,qBAAW,CAAC;AAAA,QAChB;AAAA;AAAA,IACJ,IACA;AAAA,IACJ,oBAAC,OAAE,OAAO,gBAAgB,8RAK1B;AAAA,KACJ;AAER;AAOA,SAAS,SAAS;AAAA,EACd;AAAA,EACA;AAAA,EACA;AACJ,GAIuB;AACnB,QAAM,CAAC,SAAS,UAAU,IAAU,eAAS,EAAE;AAC/C,QAAM,CAAC,OAAO,QAAQ,IAAU,eAAwB,IAAI;AAC5D,QAAM,CAAC,QAAQ,SAAS,IAAU,eAAS,EAAE;AAC7C,QAAM,CAAC,SAAS,UAAU,IAAU,eAAwB,IAAI;AAChE,QAAM,CAAC,MAAM,OAAO,IAAU,eAAS,KAAK;AAC5C,QAAM,CAAC,KAAK,MAAM,IAAU,eAAwB,IAAI;AACxD,QAAM,KAAW,YAAM;AAEvB,QAAM,OAAO,QAAQ,KAAK;AAC1B,QAAM,UAAU,KAAK,UAAU;AAE/B,iBAAe,IAAI,IAAwC;AACvD,YAAQ,IAAI;AACZ,WAAO,IAAI;AACX,QAAI;AACA,YAAM,GAAG;AAAA,IACb,QAAQ;AACJ,aAAO,YAAY,mBAAmB,CAAC;AAAA,IAC3C,UAAE;AACE,cAAQ,KAAK;AAAA,IACjB;AAAA,EACJ;AAEA,QAAM,YAAY,MACd,IAAI,YAAY;AACZ,UAAM,IAAI,MAAM,KAAK,QAAQ,EAAE,QAAQ,SAAS,SAAS,KAAK,CAAC;AAC/D,QAAI,CAAC,EAAE,GAAI,QAAO,OAAO,YAAY,EAAE,MAAM,CAAC;AAC9C,UAAM,OAAQ,EAAE,SAAoB,CAAC;AACrC,aAAS,IAAI;AACb,cAAU,KAAK,KAAK,MAAM,GAAG,YAAY,EAAE;AAAA,EAC/C,CAAC;AAEL,QAAM,aAAa,MACf,IAAI,YAAY;AACZ,UAAM,IAAI,MAAM,KAAK,QAAQ,EAAE,QAAQ,WAAW,SAAS,MAAM,UAAU,OAAO,CAAC;AACnF,QAAI,CAAC,EAAE,MAAM,OAAO,EAAE,YAAY,SAAU,QAAO,OAAO,YAAY,EAAE,MAAM,CAAC;AAC/E,eAAW,EAAE,OAAO;AAAA,EACxB,CAAC;AAEL,QAAM,SAAS,CAAC,cACZ,IAAI,YAAY;AACZ,UAAM,IAAI,MAAM,KAAK,QAAQ,EAAE,QAAQ,QAAQ,SAAS,UAAU,CAAC;AACnE,QAAI,CAAC,EAAE,MAAM,CAAC,EAAE,KAAM,QAAO,OAAO,YAAY,EAAE,MAAM,CAAC;AACzD,WAAO,EAAE,IAAkB;AAAA,EAC/B,CAAC;AAGL,WAAS,OAAa;AAClB,WAAO,IAAI;AACX,QAAI,QAAS,YAAW,IAAI;AAAA,QACvB,UAAS,IAAI;AAAA,EACtB;AAEA,QAAM,QAAQ,MAAM,oBAAC,aAAW,eAAI,IAAe;AACnD,QAAM,aACF,oBAAC,YAAO,MAAK,UAAS,OAAO,cAAc,IAAI,GAAG,UAAU,MAAM,SAAS,MAAM,kBAEjF;AAEJ,QAAM,eACF,oBAAC,YAAO,MAAK,UAAS,OAAO,cAAc,IAAI,GAAG,UAAU,MAAM,SAAS,UAAU,oBAErF;AAGJ,MAAI;AACJ,MAAI,SAAS;AACT,WACI,iCACI;AAAA,2BAAC,OAAE,OAAO,WAAW;AAAA;AAAA,QACe,oBAAC,UAAK,OAAO,cAAe,gBAAK;AAAA,QAAO;AAAA,SAE5E;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACG,SAAS;AAAA,UACT;AAAA,UACA,YAAU;AAAA,UACV,UAAU,CAAC,QAAQ,KAAK,OAAO,GAAG;AAAA,UAClC,SAAS,CAAC,MAAM,OAAO,EAAE,WAAW,4BAA4B;AAAA;AAAA,MACpE;AAAA,MACC;AAAA,MACD,qBAAC,eACI;AAAA;AAAA,QACA;AAAA,SACL;AAAA,OACJ;AAAA,EAER,WAAW,OAAO;AACd,UAAM,WAAW,MAAM,OAAO,CAAC,MAAM,EAAE,QAAQ,QAAQ;AACvD,UAAM,OAAO,MAAM,SAAS,SAAS;AACrC,WACI,iCACK;AAAA,YAAM,WAAW,IACd,qBAAC,OAAE,OAAO,WAAW;AAAA;AAAA,QACmC,EAAE,QAAQ;AAAA,QAAE;AAAA,SAGpE,IACA,SAAS,WAAW,IACpB,iCACI;AAAA,4BAAC,OAAE,OAAO,EAAE,GAAG,WAAW,OAAO,EAAE,WAAW,GAAI,mBAAS,IAAI,GAAE;AAAA,QACjE,qBAAC,OAAE,OAAO,WAAW;AAAA;AAAA,UACF,EAAE,QAAQ;AAAA,UAAE;AAAA,WAE/B;AAAA,SACJ,IAEA,iCACI;AAAA,4BAAC,OAAE,IAAI,GAAG,EAAE,SAAS,OAAO,WAAW,4DAEvC;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACG,MAAK;AAAA,YACL,mBAAiB,GAAG,EAAE;AAAA,YACtB,OAAO,EAAE,SAAS,QAAQ,KAAK,EAAE;AAAA,YAEhC,mBAAS,IAAI,CAAC,MAAM;AACjB,oBAAM,QAAQ,EAAE,aAAa;AAC7B,qBACI;AAAA,gBAAC;AAAA;AAAA,kBAEG,OAAO,UAAU,WAAW,EAAE,UAAU,KAAK;AAAA,kBAE7C;AAAA;AAAA,sBAAC;AAAA;AAAA,wBACG,MAAK;AAAA,wBACL,MAAK;AAAA,wBACL,OAAO,EAAE;AAAA,wBACT,SAAS,WAAW,EAAE;AAAA,wBACtB,UAAU;AAAA,wBACV,UAAU,MAAM,UAAU,EAAE,QAAQ;AAAA,wBACpC,OAAO,EAAE,aAAa,EAAE,SAAS,QAAQ,UAAU;AAAA;AAAA,oBACvD;AAAA,oBACA,qBAAC,UAAK,OAAO,EAAE,SAAS,QAAQ,KAAK,GAAG,UAAU,EAAE,GAChD;AAAA;AAAA,wBAAC;AAAA;AAAA,0BACG,OAAO;AAAA,4BACH,OAAO,QAAQ,EAAE,QAAQ,EAAE;AAAA,4BAC3B,UAAU;AAAA,0BACd;AAAA,0BAEC;AAAA,8BAAE,EAAE,IAAI;AAAA,4BAAE;AAAA,4BAAY;AAAA,4BACtB,KAAK,MAAM,EAAE,aAAa,GAAG;AAAA,4BAAE;AAAA;AAAA;AAAA,sBACpC;AAAA,sBACA,oBAAC,UAAK,OAAO,YACR,kBACK,wCACA,kBAAkB,eAAe,CAAC,CAAC,IAC7C;AAAA,sBACA;AAAA,wBAAC;AAAA;AAAA,0BACG,OAAO;AAAA,4BACH,GAAG;AAAA,4BACH,YAAY;AAAA,4BACZ,WAAW;AAAA,0BACf;AAAA,0BAEC,gBAAM,EAAE,QAAQ;AAAA;AAAA,sBACrB;AAAA,uBACJ;AAAA;AAAA;AAAA,gBApCK,EAAE;AAAA,cAqCX;AAAA,YAER,CAAC;AAAA;AAAA,QACL;AAAA,QACC,OAAO,IACJ,oBAAC,OAAE,OAAO,EAAE,GAAG,YAAY,WAAW,EAAE,GAAI,mBAAS,IAAI,GAAE,IAC3D;AAAA,SACR;AAAA,MAEH;AAAA,MACD,qBAAC,eACI;AAAA,iBAAS,SAAS,IACf;AAAA,UAAC;AAAA;AAAA,YACG,MAAK;AAAA,YACL,OAAO,gBAAgB,QAAQ,CAAC,MAAM;AAAA,YACtC,UAAU,QAAQ,CAAC;AAAA,YACnB,SAAS,MAAM,KAAK,WAAW;AAAA,YAClC;AAAA;AAAA,QAED,IACA;AAAA,QACH;AAAA,QACA;AAAA,SACL;AAAA,OACJ;AAAA,EAER,OAAO;AACH,WACI;AAAA,MAAC;AAAA;AAAA,QACG,OAAO,EAAE,QAAQ,EAAE;AAAA,QACnB,UAAU,CAAC,MAAM;AACb,YAAE,eAAe;AACjB,cAAI,WAAW,CAAC,KAAM,MAAK,UAAU;AAAA,QACzC;AAAA,QAEA;AAAA,8BAAC,WAAM,SAAS,GAAG,EAAE,YAAY,OAAO,iBAAiB,iDAEzD;AAAA,UACA,oBAAC,OAAE,IAAI,GAAG,EAAE,WAAW,OAAO,EAAE,GAAG,WAAW,QAAQ,UAAU,GAAG,iHAGnE;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACG,IAAI,GAAG,EAAE;AAAA,cACT,oBAAkB,GAAG,EAAE;AAAA,cACvB,OAAO;AAAA,cACP,OAAO;AAAA,cACP,UAAU,CAAC,MAAM,WAAW,EAAE,OAAO,KAAK;AAAA,cAC1C,aAAY;AAAA,cACZ,YAAY;AAAA,cACZ,cAAa;AAAA,cACb,gBAAe;AAAA;AAAA,UACnB;AAAA,UACC;AAAA,UACD,qBAAC,eACG;AAAA;AAAA,cAAC;AAAA;AAAA,gBACG,MAAK;AAAA,gBACL,OAAO,gBAAgB,QAAQ,CAAC,OAAO;AAAA,gBACvC,UAAU,QAAQ,CAAC;AAAA,gBACtB;AAAA;AAAA,YAED;AAAA,YACC;AAAA,aACL;AAAA;AAAA;AAAA,IACJ;AAAA,EAER;AAEA,SACI,qBAAC,SAAI,OAAO,WAAW,QAAQ,GAAG,qBAAkB,IAChD;AAAA,wBAAC,gBAAa,oCAAmB;AAAA,IAChC;AAAA,KACL;AAER;","names":[]}
@@ -0,0 +1,23 @@
1
+ // src/appearance.ts
2
+ var SIGNIN_FONT = "var(--oc-signin-font, ui-monospace, SFMono-Regular, monospace)";
3
+ var SIGNIN_CASE = "var(--oc-signin-case, uppercase)";
4
+ var signinTracking = (em) => `var(--oc-signin-tracking, ${em})`;
5
+ var signinSize = (px) => `calc(${px}px * var(--oc-signin-scale, 1))`;
6
+ var signinRadius = (px) => `var(--oc-signin-radius, ${px}px)`;
7
+ var SIGNIN_BUTTON_RADIUS = "var(--oc-signin-button-radius, 6px)";
8
+ var SIGNIN_STRONG = "var(--oc-signin-strong, 600)";
9
+ var SIGNIN_ARROW = "var(--oc-signin-arrow, inline)";
10
+ var signinRoleSize = (role, fallback) => `var(--oc-signin-${role}-size, ${fallback})`;
11
+
12
+ export {
13
+ SIGNIN_FONT,
14
+ SIGNIN_CASE,
15
+ signinTracking,
16
+ signinSize,
17
+ signinRadius,
18
+ SIGNIN_BUTTON_RADIUS,
19
+ SIGNIN_STRONG,
20
+ SIGNIN_ARROW,
21
+ signinRoleSize
22
+ };
23
+ //# sourceMappingURL=chunk-H2TXOCXH.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/appearance.ts"],"sourcesContent":["import type * as React from 'react';\n\n/*\n * Every type and shape choice below reads a CSS variable whose fallback is the\n * family look, so a site with a design of its own (ochk.app) restyles the\n * ceremony by setting variables on an ancestor, never by forking it. Family\n * sites set none and render exactly as before.\n *\n * --oc-signin-font labels, buttons, fields (monospace)\n * --oc-signin-case labels and buttons (uppercase)\n * --oc-signin-tracking letter-spacing of labels (per label)\n * --oc-signin-scale multiplies the 10–12px label sizes (1)\n * --oc-signin-radius fields and notices (6px; 4px for the add notice)\n * --oc-signin-button-radius buttons (6px)\n * --oc-signin-strong weight of the submit text (600)\n * --oc-signin-arrow display of the → after a submit label (inline)\n *\n * Sizes by role. Each falls back to the family size, so a site that sets none\n * renders as before; app-design sets its own body, hint, label and button sizes.\n *\n * --oc-signin-text-size the lead under a tab, notices, the link-also row\n * --oc-signin-hint-size hints, errors, the \"or\" between blocks\n * --oc-signin-label-size field labels and the method tabs\n * --oc-signin-button-size the submit button and the text buttons beside it\n *\n * Copy is written in sentence case. The family's uppercase transform shows it\n * as before; a site that sets the case to `none` reads it as written.\n */\nexport const SIGNIN_FONT = 'var(--oc-signin-font, ui-monospace, SFMono-Regular, monospace)';\nexport const SIGNIN_CASE = 'var(--oc-signin-case, uppercase)' as React.CSSProperties['textTransform'];\nexport const signinTracking = (em: string): string => `var(--oc-signin-tracking, ${em})`;\nexport const signinSize = (px: number): string => `calc(${px}px * var(--oc-signin-scale, 1))`;\nexport const signinRadius = (px: number): string => `var(--oc-signin-radius, ${px}px)`;\nexport const SIGNIN_BUTTON_RADIUS = 'var(--oc-signin-button-radius, 6px)';\nexport const SIGNIN_STRONG = 'var(--oc-signin-strong, 600)' as React.CSSProperties['fontWeight'];\nexport const SIGNIN_ARROW = 'var(--oc-signin-arrow, inline)' as React.CSSProperties['display'];\n\nexport type SigninRole = 'text' | 'hint' | 'label' | 'button';\n/** A role's size: the site's, else `fallback`, the family size for that element. */\nexport const signinRoleSize = (role: SigninRole, fallback: string): string =>\n `var(--oc-signin-${role}-size, ${fallback})`;\n"],"mappings":";AA4BO,IAAM,cAAc;AACpB,IAAM,cAAc;AACpB,IAAM,iBAAiB,CAAC,OAAuB,6BAA6B,EAAE;AAC9E,IAAM,aAAa,CAAC,OAAuB,QAAQ,EAAE;AACrD,IAAM,eAAe,CAAC,OAAuB,2BAA2B,EAAE;AAC1E,IAAM,uBAAuB;AAC7B,IAAM,gBAAgB;AACtB,IAAM,eAAe;AAIrB,IAAM,iBAAiB,CAAC,MAAkB,aAC7C,mBAAmB,IAAI,UAAU,QAAQ;","names":[]}