@crvouga/mockingbird-service-stripe 1.10.0 → 1.11.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.
package/CHANGELOG.md CHANGED
@@ -1,14 +1,22 @@
1
1
  # Changelog — @crvouga/mockingbird-service-stripe
2
2
 
3
- ## 1.10.0 (2026-09-30)
3
+ ## 1.11.0 (2026-09-30)
4
4
 
5
5
  ### Features
6
6
 
7
- - state each mock's parity and share one CSS reset ([264b06e](https://github.com/crvouga/mockingbird/commit/264b06ef15efc1d5131bbf78c89f45e2ce86b557))
7
+ - boot Bolt over Socket Mode ([01322df](https://github.com/crvouga/mockingbird/commit/01322df315c66b1f2f5b53094cbbeeeef6d3ae6c))
8
+
9
+ ## 1.10.1 (2026-09-29)
10
+
11
+ ### Fixes and improvements
8
12
 
9
- ### Dependencies
13
+ - keep hosted pages inside narrow hosts and popups ([6512323](https://github.com/crvouga/mockingbird/commit/6512323198cb00b99005f3d2cfa5b9f1e6e321a7))
10
14
 
11
- - `@crvouga/mockingbird-service-sqlite`
15
+ ## 1.10.0 (2026-09-29)
16
+
17
+ ### Features
18
+
19
+ - state each mock's parity and share one CSS reset ([264b06e](https://github.com/crvouga/mockingbird/commit/264b06ef15efc1d5131bbf78c89f45e2ce86b557))
12
20
 
13
21
  ## 1.9.0 (2026-09-29)
14
22
 
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createRuntime,
3
3
  validateAccounts
4
- } from "./chunk-YUKBBY4J.js";
4
+ } from "./chunk-RPSJESGN.js";
5
5
 
6
6
  // src/server.ts
7
7
  import { readFileSync } from "node:fs";
@@ -239,6 +239,7 @@ var start = async (target, values, config) => {
239
239
  onLog: formatLog(config.log)
240
240
  });
241
241
  const listening = await listen(runtime, { port: config.port, host: config.host });
242
+ target.listening?.(listening);
242
243
  console.log(`${target.name} mock listening on ${listening.url}`);
243
244
  console.log(`${target.name} health: GET ${listening.url}/health`);
244
245
  console.log(`${target.name} admin: ${listening.url}/__admin (${config.adminKey ? "x-mockingbird-admin-key required" : "open \u2014 pass --admin-key to lock"})`);
@@ -386,4 +387,4 @@ export {
386
387
  createServer2 as createServer,
387
388
  serveTarget
388
389
  };
389
- //# sourceMappingURL=chunk-VCA4RIK5.js.map
390
+ //# sourceMappingURL=chunk-5YTYQI7H.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/server.ts", "../../../adapters/node/src/cli.ts", "../../../adapters/node/src/serve.ts", "../../../adapters/node/src/listen.ts"],
4
+ "sourcesContent": ["/// <reference types=\"node\" />\nimport { readFileSync } from \"node:fs\"\nimport { type Listening, listen, type ServeTarget } from \"@crvouga/mockingbird-adapter-node\"\nimport { validateAccounts } from \"./accounts.js\"\nimport { createRuntime, type StripeRuntime, type StripeRuntimeOptions } from \"./runtime.js\"\n\n/** Port `mockingbird-stripe serve` listens on when none is given. */\nexport const DEFAULT_PORT = 12111\n\nexport type StripeServerOptions = StripeRuntimeOptions & {\n /** Default `0`: the OS picks a free port (read it from `url` / `port`). */\n port?: number\n /** Default `127.0.0.1`. */\n host?: string\n}\n\nexport type StripeServer = Listening & { runtime: StripeRuntime }\n\n/** Serve the Stripe mock over `node:http`. Resolves once it is listening. */\nexport const createServer = async (options: StripeServerOptions = {}): Promise<StripeServer> => {\n const { port, host, ...rest } = options\n const runtime = createRuntime(rest)\n const listening = await listen(runtime, {\n port: port ?? 0,\n ...(host !== undefined ? { host } : {}),\n })\n return {\n ...listening,\n runtime,\n close: async () => {\n runtime.stop()\n await listening.close()\n },\n }\n}\n\nconst text = (value: string | boolean | undefined) =>\n typeof value === \"string\" && value !== \"\" ? value : undefined\n\n/** `--accounts` takes inline JSON or a path to a JSON file. */\nconst readAccounts = (value: string) => {\n const raw =\n value.trim().startsWith(\"[\") || value.trim().startsWith(\"{\")\n ? value\n : readFileSync(value, \"utf8\")\n const parsed = validateAccounts(JSON.parse(raw))\n if (typeof parsed === \"string\") throw new Error(`--accounts: ${parsed}`)\n return parsed\n}\n\n/** How `serve` (and `serve --config`) builds the Stripe mock from flags. */\nexport const serveTarget: ServeTarget = {\n name: \"stripe\",\n defaultPort: DEFAULT_PORT,\n options: {\n accounts: {\n type: \"string\",\n value: \"<json|file>\",\n description:\n 'Accounts and their keys, e.g. [{\"id\":\"acct_mso\",\"keys\":[\"sk_test_\u2026\"],\"webhookSecrets\":{\"http://\u2026/billing/webhooks/stripe/mso\":\"whsec_\u2026\"},\"corpus\":true}]',\n },\n \"webhook-url\": {\n type: \"string\",\n value: \"<url>\",\n description: \"Deliver every account's events here (signed with --webhook-secret)\",\n },\n \"webhook-secret\": {\n type: \"string\",\n value: \"<whsec_\u2026>\",\n description: \"Secret for --webhook-url's Stripe-Signature\",\n },\n \"public-url\": {\n type: \"string\",\n value: \"<url>\",\n description: \"Base URL of the hosted Checkout page and Stripe.js when behind a proxy\",\n },\n },\n create: (values, common) => {\n const url = text(values[\"webhook-url\"])\n const secret = text(values[\"webhook-secret\"])\n const accounts = text(values.accounts)\n const publicUrl = text(values[\"public-url\"])\n return createRuntime({\n ...(common.adminKey !== undefined ? { adminKey: common.adminKey } : {}),\n ...(common.seed !== undefined ? { seed: common.seed } : {}),\n ...(common.onLog ? { onLog: common.onLog } : {}),\n ...(accounts ? { accounts: readAccounts(accounts) } : {}),\n ...(url ? { webhooks: { endpoints: [{ url, ...(secret ? { secret } : {}) }] } } : {}),\n ...(publicUrl ? { publicUrl } : {}),\n tickMs: 1000,\n })\n },\n banner: () => [\n \"auth: Authorization: Bearer sk_test_<anything>; unconfigured keys are accounts of their own\",\n 'stripe-node: new Stripe(key, { host: \"127.0.0.1\", port: <port>, protocol: \"http\" })',\n \"accounts: PUT /__admin/accounts; webhooks: PUT /__admin/webhook-endpoints\",\n \"hosted Checkout: session.url \u2192 /c/pay/<id>; Stripe.js stand-in: /v3\",\n ],\n}\n", "import { readFile } from \"node:fs/promises\"\nimport { type ParseArgsConfig, parseArgs } from \"node:util\"\nimport type { RequestLog, ServiceInstance, ServiceRuntime } from \"@crvouga/mockingbird-service\"\nimport { type Listening, listen } from \"./listen.js\"\n\nexport type CliOption = {\n type: \"string\" | \"boolean\"\n description: string\n /** Shown in help; the value placeholder, e.g. `<port>`. */\n value?: string\n default?: string | boolean\n}\n\nexport type CliValues = Record<string, string | boolean | undefined>\n\nexport type CliCommand = {\n summary: string\n usage?: string\n options?: Record<string, CliOption>\n /** Resolves to an exit code; a server command resolves only when it stops. */\n run(values: CliValues, positionals: string[]): Promise<number>\n}\n\nexport type CliSpec = {\n bin: string\n description: string\n commands: Record<string, CliCommand>\n}\n\nconst optionHelp = (options: Record<string, CliOption>): string[] =>\n Object.entries(options).map(([name, option]) => {\n const flag = `--${name}${option.type === \"string\" ? ` ${option.value ?? \"<value>\"}` : \"\"}`\n const fallback = option.default !== undefined ? ` (default: ${String(option.default)})` : \"\"\n return ` ${flag.padEnd(30)} ${option.description}${fallback}`\n })\n\nconst help = (spec: CliSpec): string =>\n [\n `${spec.bin} \u2014 ${spec.description}`,\n \"\",\n \"Usage:\",\n ` ${spec.bin} <command> [options]`,\n \"\",\n \"Commands:\",\n ...Object.entries(spec.commands).map(([name, c]) => ` ${name.padEnd(30)} ${c.summary}`),\n \"\",\n `Run \\`${spec.bin} <command> --help\\` for a command's options.`,\n ].join(\"\\n\")\n\nconst commandHelp = (spec: CliSpec, name: string, command: CliCommand): string =>\n [\n `${spec.bin} ${name} \u2014 ${command.summary}`,\n \"\",\n \"Usage:\",\n ` ${command.usage ?? `${spec.bin} ${name} [options]`}`,\n ...(command.options ? [\"\", \"Options:\", ...optionHelp(command.options)] : []),\n ].join(\"\\n\")\n\n/** Parse `argv` against `spec` and run the chosen command. Resolves to an exit code. */\nexport const runCli = async (spec: CliSpec, argv: string[]): Promise<number> => {\n // Two-word commands (`corpus pull`) win over one-word ones.\n const pair = argv.length >= 2 ? `${argv[0]} ${argv[1]}` : undefined\n const words = pair !== undefined && spec.commands[pair] ? 2 : 1\n const name = words === 2 ? pair : argv[0]\n const rest = argv.slice(words)\n if (name === undefined || name === \"--help\" || name === \"-h\" || name === \"help\") {\n console.log(help(spec))\n return 0\n }\n const command = spec.commands[name]\n if (!command) {\n console.error(`${spec.bin}: unknown command ${JSON.stringify(name)}\\n\\n${help(spec)}`)\n return 2\n }\n if (rest.includes(\"--help\") || rest.includes(\"-h\")) {\n console.log(commandHelp(spec, name, command))\n return 0\n }\n let parsed: { values: CliValues; positionals: string[] }\n try {\n parsed = parseArgs({\n args: rest,\n allowPositionals: true,\n strict: true,\n options: Object.fromEntries(\n Object.entries(command.options ?? {}).map(([key, option]) => [\n key,\n {\n type: option.type,\n ...(option.default !== undefined ? { default: option.default } : {}),\n },\n ]),\n ) as ParseArgsConfig[\"options\"],\n }) as { values: CliValues; positionals: string[] }\n } catch (error) {\n console.error(\n `${spec.bin} ${name}: ${error instanceof Error ? error.message : String(error)}\\n\\n${commandHelp(spec, name, command)}`,\n )\n return 2\n }\n return command.run(parsed.values, parsed.positionals)\n}\n\n// \u2500\u2500 serve \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\nexport type LogFormat = \"pretty\" | \"json\" | \"off\"\n\nexport type CommonServeOptions = {\n adminKey: string | undefined\n seed: string | undefined\n onLog: ((entry: RequestLog) => void) | undefined\n}\n\n/**\n * What a service contributes to `serve`: how to build its runtime from CLI flags,\n * and what to say at startup. Every service's `./server` entry exports one as\n * `serveTarget`, which is also how `serve --config` finds services by name.\n */\nexport type ServeTarget = {\n name: string\n defaultPort: number\n /** Serve flags beyond the common ones. */\n options?: Record<string, CliOption>\n create(\n values: CliValues,\n common: CommonServeOptions,\n ): Promise<ServiceRuntime<ServiceInstance>> | ServiceRuntime<ServiceInstance>\n /** Startup lines after the listen address, e.g. the loaded corpus version. */\n banner?(runtime: ServiceRuntime<ServiceInstance>): string[]\n /** After the HTTP server is bound. A service that speaks more than HTTP attaches it here. */\n listening?(server: Listening): void\n}\n\nconst COMMON_SERVE_OPTIONS: Record<string, CliOption> = {\n port: { type: \"string\", value: \"<port>\", description: \"Port to listen on\" },\n host: { type: \"string\", value: \"<host>\", description: \"Interface to bind\", default: \"127.0.0.1\" },\n \"admin-key\": {\n type: \"string\",\n value: \"<key>\",\n description: \"Require x-mockingbird-admin-key on /__admin/* (env MOCKINGBIRD_ADMIN_KEY)\",\n },\n seed: { type: \"string\", value: \"<seed>\", description: \"Seed for every random choice\" },\n log: {\n type: \"string\",\n value: \"<pretty|json|off>\",\n description: \"Request log format\",\n default: \"pretty\",\n },\n \"log-requests\": {\n type: \"boolean\",\n description:\n \"One JSON line per request: namespace, operationId, status, ids touched (never bodies). Same as --log json\",\n },\n config: {\n type: \"string\",\n value: \"<file>\",\n description: \"Serve every service in a mockingbird.json config instead\",\n },\n}\n\nconst formatLog = (format: LogFormat) => {\n if (format === \"off\") return undefined\n if (format === \"json\") return (entry: RequestLog) => console.log(JSON.stringify(entry))\n return (entry: RequestLog) => {\n const op = entry.operationId ?? (entry.unmatched ? \"UNMATCHED\" : \"-\")\n const ns = entry.namespace === \"default\" ? \"\" : ` [${entry.namespace}]`\n const fault = entry.faultId ? ` fault=${entry.faultId}` : \"\"\n const adopted = entry.adopted ? \" adopted\" : \"\"\n // A rejection says what arrived (never the body) and why the service refused it.\n const received = entry.request\n ? ` received=${entry.request.bodyBytes === null ? \"?\" : `${entry.request.bodyBytes}B`} ct=${entry.request.contentType ?? \"-\"}${\n entry.request.transferEncoding ? ` te=${entry.request.transferEncoding}` : \"\"\n }`\n : \"\"\n const issues = entry.issues?.length\n ? ` issues=${entry.issues\n .slice(0, 3)\n .map((issue) => `${issue.path || \"$\"}: ${issue.message}`)\n .join(\"; \")}${entry.issues.length > 3 ? ` (+${entry.issues.length - 3})` : \"\"}`\n : \"\"\n console.log(\n `${entry.service} ${entry.method} ${entry.path} ${entry.status} ${op} ${entry.durationMs}ms${ns}${fault}${adopted}${received}${issues}`,\n )\n }\n}\n\nconst asString = (value: string | boolean | undefined): string | undefined =>\n typeof value === \"string\" ? value : undefined\n\n/** A service entry in `mockingbird.json`. */\nexport type ConfigService = {\n port?: number\n host?: string\n adminKey?: string\n seed?: string\n /** Service-specific serve flags, by long name: `{ \"webhook-url\": \"\u2026\" }`. */\n options?: Record<string, string | boolean>\n}\n\nexport type MockingbirdConfig = {\n /** Keyed by service name: `junction` loads `@crvouga/mockingbird-service-junction`. */\n services: Record<string, ConfigService>\n log?: LogFormat\n}\n\nconst loadTarget = async (name: string, own: ServeTarget): Promise<ServeTarget> => {\n if (name === own.name) return own\n const specifier = `@crvouga/mockingbird-service-${name}/server`\n try {\n const mod = (await import(specifier)) as { serveTarget?: ServeTarget }\n if (!mod.serveTarget) throw new Error(`${specifier} exports no serveTarget`)\n return mod.serveTarget\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error)\n throw new Error(\n `cannot load service \"${name}\": ${reason}. Install @crvouga/mockingbird-service-${name}.`,\n )\n }\n}\n\nconst start = async (\n target: ServeTarget,\n values: CliValues,\n config: { port: number; host: string; adminKey?: string; seed?: string; log: LogFormat },\n): Promise<Listening> => {\n const runtime = await target.create(values, {\n adminKey: config.adminKey,\n seed: config.seed,\n onLog: formatLog(config.log),\n })\n const listening = await listen(runtime, { port: config.port, host: config.host })\n target.listening?.(listening)\n console.log(`${target.name} mock listening on ${listening.url}`)\n console.log(`${target.name} health: GET ${listening.url}/health`)\n console.log(\n `${target.name} admin: ${listening.url}/__admin (${config.adminKey ? \"x-mockingbird-admin-key required\" : \"open \u2014 pass --admin-key to lock\"})`,\n )\n console.log(`${target.name} admin ui: ${listening.url}/__admin/ui`)\n for (const line of target.banner?.(runtime) ?? []) console.log(`${target.name} ${line}`)\n return listening\n}\n\nconst untilSignal = async (servers: Listening[]): Promise<number> =>\n new Promise((resolve) => {\n const stop = async () => {\n await Promise.allSettled(servers.map((s) => s.close()))\n resolve(0)\n }\n process.once(\"SIGINT\", stop)\n process.once(\"SIGTERM\", stop)\n })\n\n/** The standard `serve` command for a service, including multi-service `--config`. */\nexport const serveCommand = (target: ServeTarget): CliCommand => ({\n summary: `Serve the ${target.name} mock over HTTP`,\n options: { ...COMMON_SERVE_OPTIONS, ...target.options },\n async run(values) {\n const log = (\n values[\"log-requests\"] === true ? \"json\" : (asString(values.log) ?? \"pretty\")\n ) as LogFormat\n if (![\"pretty\", \"json\", \"off\"].includes(log)) {\n console.error(`--log must be pretty, json or off (got ${log})`)\n return 2\n }\n const configPath = asString(values.config)\n if (configPath !== undefined) {\n const config = JSON.parse(await readFile(configPath, \"utf8\")) as MockingbirdConfig\n const servers: Listening[] = []\n try {\n for (const [name, entry] of Object.entries(config.services ?? {})) {\n const each = await loadTarget(name, target)\n servers.push(\n await start(each, entry.options ?? {}, {\n port: entry.port ?? each.defaultPort,\n host: entry.host ?? \"127.0.0.1\",\n ...(entry.adminKey !== undefined ? { adminKey: entry.adminKey } : {}),\n ...(entry.seed !== undefined ? { seed: entry.seed } : {}),\n log: config.log ?? log,\n }),\n )\n }\n } catch (error) {\n await Promise.allSettled(servers.map((s) => s.close()))\n console.error(error instanceof Error ? error.message : String(error))\n return 1\n }\n return untilSignal(servers)\n }\n const port = asString(values.port)\n const adminKey = asString(values[\"admin-key\"]) ?? process.env.MOCKINGBIRD_ADMIN_KEY\n const seed = asString(values.seed)\n let listening: Listening\n try {\n listening = await start(target, values, {\n port: port === undefined ? target.defaultPort : Number.parseInt(port, 10),\n host: asString(values.host) ?? \"127.0.0.1\",\n ...(adminKey !== undefined ? { adminKey } : {}),\n ...(seed !== undefined ? { seed } : {}),\n log,\n })\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error))\n return 1\n }\n return untilSignal([listening])\n },\n})\n", "import { createServer } from \"node:http\"\nimport type { FetchAPI } from \"@crvouga/mockingbird-core\"\n\n/** Options for {@link serve}. */\nexport type NodeServeOptions = {\n port?: number\n host?: string\n}\n\n/**\n * Serve any Mockingbird {@link FetchAPI} over `node:http`.\n * Port defaults to `0`, so the OS assigns an ephemeral port (read from `server.address()`).\n */\nexport const serve = async (api: FetchAPI, options: NodeServeOptions = {}) => {\n const server = createServer(async (req, res) => {\n const chunks: Buffer[] = []\n for await (const chunk of req) {\n chunks.push(Buffer.from(chunk))\n }\n const body = Buffer.concat(chunks)\n const address = server.address()\n const port = typeof address === \"object\" && address !== null ? address.port : undefined\n const base = `http://${req.headers.host ?? `localhost:${port ?? 80}`}`\n const raw = req.url ?? \"/\"\n const url = new URL(raw.replace(/^\\/+/, \"/\"), base)\n const method = req.method ?? \"GET\"\n const init: RequestInit = { method, headers: req.headers as Record<string, string> }\n if (method !== \"GET\" && method !== \"HEAD\" && body.length > 0) {\n init.body = body\n }\n const aborted = new AbortController()\n res.once(\"close\", () => {\n if (!res.writableFinished) aborted.abort()\n })\n init.signal = aborted.signal\n const request = new Request(url, init)\n let response: Response\n try {\n response = await api.fetch(request)\n } catch (error) {\n // A `drop` fault: destroy the socket so the client sees the connection die.\n if ((error as { code?: string }).code === \"MOCKINGBIRD_DROP\") {\n req.socket.destroy()\n return\n }\n res.writeHead(500, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: {\n type: \"mockingbird_internal\",\n message: error instanceof Error ? error.message : String(error),\n },\n }),\n )\n return\n }\n // Headers#entries() joins repeated headers; Set-Cookie must stay one header per cookie.\n const headers: Record<string, string | string[]> = Object.fromEntries(response.headers)\n const cookies = response.headers.getSetCookie()\n if (cookies.length > 0) headers[\"set-cookie\"] = cookies\n if (!response.body) {\n res.writeHead(response.status, headers)\n res.end()\n return\n }\n // Stream the body chunk by chunk: event streams and long-polls must not be buffered.\n res.writeHead(response.status, headers)\n res.flushHeaders()\n const reader = response.body.getReader()\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n if (!res.write(value)) await new Promise<void>((resolve) => res.once(\"drain\", resolve))\n }\n res.end()\n } catch {\n res.destroy()\n } finally {\n reader.releaseLock()\n }\n })\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(options.port ?? 0, options.host, resolve)\n })\n return server\n}\n", "import type { Server } from \"node:http\"\nimport type { FetchAPI } from \"@crvouga/mockingbird-core\"\nimport { serve } from \"./serve.js\"\n\nexport type ListenOptions = {\n /** Default `0`: the OS picks a free port. */\n port?: number\n /** Default `127.0.0.1`: a mock should not be reachable off the machine by accident. */\n host?: string\n}\n\n/** A running server, with the address it actually bound. */\nexport type Listening = {\n url: string\n port: number\n host: string\n server: Server\n close(): Promise<void>\n}\n\nexport const listen = async (api: FetchAPI, options: ListenOptions = {}): Promise<Listening> => {\n const host = options.host ?? \"127.0.0.1\"\n const server = await serve(api, { port: options.port ?? 0, host })\n const address = server.address()\n const port = typeof address === \"object\" && address !== null ? address.port : (options.port ?? 0)\n const shown = host.includes(\":\") ? `[${host}]` : host\n return {\n url: `http://${shown}:${port}`,\n port,\n host,\n server,\n close: () =>\n new Promise<void>((resolve, reject) => {\n // Stop accepting first, then drop keep-alive sockets so close() can finish.\n server.close((error) => {\n if (error && (error as { code?: string }).code !== \"ERR_SERVER_NOT_RUNNING\") reject(error)\n else resolve()\n })\n server.closeAllConnections?.()\n }),\n }\n}\n"],
5
+ "mappings": ";;;;;;AACA,SAAS,oBAAoB;;;ACD7B,SAAS,gBAAgB;AACzB,SAA+B,iBAAiB;;;ACDhD,SAAS,oBAAoB;AAatB,IAAM,QAAQ,OAAO,KAAe,UAA4B,CAAA,MAAM;AAC3E,QAAM,SAAS,aAAa,OAAO,KAAK,QAAO;AAC7C,UAAM,SAAmB,CAAA;AACzB,qBAAiB,SAAS,KAAK;AAC7B,aAAO,KAAK,OAAO,KAAK,KAAK,CAAC;IAChC;AACA,UAAM,OAAO,OAAO,OAAO,MAAM;AACjC,UAAM,UAAU,OAAO,QAAO;AAC9B,UAAM,OAAO,OAAO,YAAY,YAAY,YAAY,OAAO,QAAQ,OAAO;AAC9E,UAAM,OAAO,UAAU,IAAI,QAAQ,QAAQ,aAAa,QAAQ,EAAE,EAAE;AACpE,UAAM,MAAM,IAAI,OAAO;AACvB,UAAM,MAAM,IAAI,IAAI,IAAI,QAAQ,QAAQ,GAAG,GAAG,IAAI;AAClD,UAAM,SAAS,IAAI,UAAU;AAC7B,UAAM,OAAoB,EAAE,QAAQ,SAAS,IAAI,QAAiC;AAClF,QAAI,WAAW,SAAS,WAAW,UAAU,KAAK,SAAS,GAAG;AAC5D,WAAK,OAAO;IACd;AACA,UAAM,UAAU,IAAI,gBAAe;AACnC,QAAI,KAAK,SAAS,MAAK;AACrB,UAAI,CAAC,IAAI;AAAkB,gBAAQ,MAAK;IAC1C,CAAC;AACD,SAAK,SAAS,QAAQ;AACtB,UAAM,UAAU,IAAI,QAAQ,KAAK,IAAI;AACrC,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,IAAI,MAAM,OAAO;IACpC,SAAS,OAAO;AAEd,UAAK,MAA4B,SAAS,oBAAoB;AAC5D,YAAI,OAAO,QAAO;AAClB;MACF;AACA,UAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAkB,CAAE;AACzD,UAAI,IACF,KAAK,UAAU;QACb,OAAO;UACL,MAAM;UACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;;OAEjE,CAAC;AAEJ;IACF;AAEA,UAAM,UAA6C,OAAO,YAAY,SAAS,OAAO;AACtF,UAAM,UAAU,SAAS,QAAQ,aAAY;AAC7C,QAAI,QAAQ,SAAS;AAAG,cAAQ,YAAY,IAAI;AAChD,QAAI,CAAC,SAAS,MAAM;AAClB,UAAI,UAAU,SAAS,QAAQ,OAAO;AACtC,UAAI,IAAG;AACP;IACF;AAEA,QAAI,UAAU,SAAS,QAAQ,OAAO;AACtC,QAAI,aAAY;AAChB,UAAM,SAAS,SAAS,KAAK,UAAS;AACtC,QAAI;AACF,iBAAS;AACP,cAAM,EAAE,MAAM,MAAK,IAAK,MAAM,OAAO,KAAI;AACzC,YAAI;AAAM;AACV,YAAI,CAAC,IAAI,MAAM,KAAK;AAAG,gBAAM,IAAI,QAAc,CAAC,YAAY,IAAI,KAAK,SAAS,OAAO,CAAC;MACxF;AACA,UAAI,IAAG;IACT,QAAQ;AACN,UAAI,QAAO;IACb;AACE,aAAO,YAAW;IACpB;EACF,CAAC;AACD,QAAM,IAAI,QAAc,CAAC,SAAS,WAAU;AAC1C,WAAO,KAAK,SAAS,MAAM;AAC3B,WAAO,OAAO,QAAQ,QAAQ,GAAG,QAAQ,MAAM,OAAO;EACxD,CAAC;AACD,SAAO;AACT;;;ACnEO,IAAM,SAAS,OAAO,KAAe,UAAyB,CAAA,MAA0B;AAC7F,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,SAAS,MAAM,MAAM,KAAK,EAAE,MAAM,QAAQ,QAAQ,GAAG,KAAI,CAAE;AACjE,QAAM,UAAU,OAAO,QAAO;AAC9B,QAAM,OAAO,OAAO,YAAY,YAAY,YAAY,OAAO,QAAQ,OAAQ,QAAQ,QAAQ;AAC/F,QAAM,QAAQ,KAAK,SAAS,GAAG,IAAI,IAAI,IAAI,MAAM;AACjD,SAAO;IACL,KAAK,UAAU,KAAK,IAAI,IAAI;IAC5B;IACA;IACA;IACA,OAAO,MACL,IAAI,QAAc,CAAC,SAAS,WAAU;AAEpC,aAAO,MAAM,CAAC,UAAS;AACrB,YAAI,SAAU,MAA4B,SAAS;AAA0B,iBAAO,KAAK;;AACpF,kBAAO;MACd,CAAC;AACD,aAAO,sBAAqB;IAC9B,CAAC;;AAEP;;;AFZA,IAAM,aAAa,CAAC,YAClB,OAAO,QAAQ,OAAO,EAAE,IAAI,CAAC,CAAC,MAAM,MAAM,MAAK;AAC7C,QAAM,OAAO,KAAK,IAAI,GAAG,OAAO,SAAS,WAAW,IAAI,OAAO,SAAS,SAAS,KAAK,EAAE;AACxF,QAAM,WAAW,OAAO,YAAY,SAAY,cAAc,OAAO,OAAO,OAAO,CAAC,MAAM;AAC1F,SAAO,KAAK,KAAK,OAAO,EAAE,CAAC,IAAI,OAAO,WAAW,GAAG,QAAQ;AAC9D,CAAC;AAEH,IAAM,OAAO,CAAC,SACZ;EACE,GAAG,KAAK,GAAG,WAAM,KAAK,WAAW;EACjC;EACA;EACA,KAAK,KAAK,GAAG;EACb;EACA;EACA,GAAG,OAAO,QAAQ,KAAK,QAAQ,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,KAAK,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE;EACvF;EACA,SAAS,KAAK,GAAG;EACjB,KAAK,IAAI;AAEb,IAAM,cAAc,CAAC,MAAe,MAAc,YAChD;EACE,GAAG,KAAK,GAAG,IAAI,IAAI,WAAM,QAAQ,OAAO;EACxC;EACA;EACA,KAAK,QAAQ,SAAS,GAAG,KAAK,GAAG,IAAI,IAAI,YAAY;EACrD,GAAI,QAAQ,UAAU,CAAC,IAAI,YAAY,GAAG,WAAW,QAAQ,OAAO,CAAC,IAAI,CAAA;EACzE,KAAK,IAAI;AAGN,IAAM,SAAS,OAAO,MAAe,SAAmC;AAE7E,QAAM,OAAO,KAAK,UAAU,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK;AAC1D,QAAM,QAAQ,SAAS,UAAa,KAAK,SAAS,IAAI,IAAI,IAAI;AAC9D,QAAM,OAAO,UAAU,IAAI,OAAO,KAAK,CAAC;AACxC,QAAM,OAAO,KAAK,MAAM,KAAK;AAC7B,MAAI,SAAS,UAAa,SAAS,YAAY,SAAS,QAAQ,SAAS,QAAQ;AAC/E,YAAQ,IAAI,KAAK,IAAI,CAAC;AACtB,WAAO;EACT;AACA,QAAM,UAAU,KAAK,SAAS,IAAI;AAClC,MAAI,CAAC,SAAS;AACZ,YAAQ,MAAM,GAAG,KAAK,GAAG,qBAAqB,KAAK,UAAU,IAAI,CAAC;;EAAO,KAAK,IAAI,CAAC,EAAE;AACrF,WAAO;EACT;AACA,MAAI,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,IAAI,GAAG;AAClD,YAAQ,IAAI,YAAY,MAAM,MAAM,OAAO,CAAC;AAC5C,WAAO;EACT;AACA,MAAI;AACJ,MAAI;AACF,aAAS,UAAU;MACjB,MAAM;MACN,kBAAkB;MAClB,QAAQ;MACR,SAAS,OAAO,YACd,OAAO,QAAQ,QAAQ,WAAW,CAAA,CAAE,EAAE,IAAI,CAAC,CAAC,KAAK,MAAM,MAAM;QAC3D;QACA;UACE,MAAM,OAAO;UACb,GAAI,OAAO,YAAY,SAAY,EAAE,SAAS,OAAO,QAAO,IAAK,CAAA;;OAEpE,CAAC;KAEL;EACH,SAAS,OAAO;AACd,YAAQ,MACN,GAAG,KAAK,GAAG,IAAI,IAAI,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;;EAAO,YAAY,MAAM,MAAM,OAAO,CAAC,EAAE;AAEzH,WAAO;EACT;AACA,SAAO,QAAQ,IAAI,OAAO,QAAQ,OAAO,WAAW;AACtD;AAgCA,IAAM,uBAAkD;EACtD,MAAM,EAAE,MAAM,UAAU,OAAO,UAAU,aAAa,oBAAmB;EACzE,MAAM,EAAE,MAAM,UAAU,OAAO,UAAU,aAAa,qBAAqB,SAAS,YAAW;EAC/F,aAAa;IACX,MAAM;IACN,OAAO;IACP,aAAa;;EAEf,MAAM,EAAE,MAAM,UAAU,OAAO,UAAU,aAAa,+BAA8B;EACpF,KAAK;IACH,MAAM;IACN,OAAO;IACP,aAAa;IACb,SAAS;;EAEX,gBAAgB;IACd,MAAM;IACN,aACE;;EAEJ,QAAQ;IACN,MAAM;IACN,OAAO;IACP,aAAa;;;AAIjB,IAAM,YAAY,CAAC,WAAqB;AACtC,MAAI,WAAW;AAAO,WAAO;AAC7B,MAAI,WAAW;AAAQ,WAAO,CAAC,UAAsB,QAAQ,IAAI,KAAK,UAAU,KAAK,CAAC;AACtF,SAAO,CAAC,UAAqB;AAC3B,UAAM,KAAK,MAAM,gBAAgB,MAAM,YAAY,cAAc;AACjE,UAAM,KAAK,MAAM,cAAc,YAAY,KAAK,KAAK,MAAM,SAAS;AACpE,UAAM,QAAQ,MAAM,UAAU,UAAU,MAAM,OAAO,KAAK;AAC1D,UAAM,UAAU,MAAM,UAAU,aAAa;AAE7C,UAAM,WAAW,MAAM,UACnB,aAAa,MAAM,QAAQ,cAAc,OAAO,MAAM,GAAG,MAAM,QAAQ,SAAS,GAAG,OAAO,MAAM,QAAQ,eAAe,GAAG,GACxH,MAAM,QAAQ,mBAAmB,OAAO,MAAM,QAAQ,gBAAgB,KAAK,EAC7E,KACA;AACJ,UAAM,SAAS,MAAM,QAAQ,SACzB,WAAW,MAAM,OACd,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,UAAU,GAAG,MAAM,QAAQ,GAAG,KAAK,MAAM,OAAO,EAAE,EACvD,KAAK,IAAI,CAAC,GAAG,MAAM,OAAO,SAAS,IAAI,MAAM,MAAM,OAAO,SAAS,CAAC,MAAM,EAAE,KAC/E;AACJ,YAAQ,IACN,GAAG,MAAM,OAAO,IAAI,MAAM,MAAM,IAAI,MAAM,IAAI,IAAI,MAAM,MAAM,IAAI,EAAE,IAAI,MAAM,UAAU,KAAK,EAAE,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,EAAE;EAE3I;AACF;AAEA,IAAM,WAAW,CAAC,UAChB,OAAO,UAAU,WAAW,QAAQ;AAkBtC,IAAM,aAAa,OAAO,MAAc,QAA0C;AAChF,MAAI,SAAS,IAAI;AAAM,WAAO;AAC9B,QAAM,YAAY,gCAAgC,IAAI;AACtD,MAAI;AACF,UAAM,MAAO,MAAM,OAAO;AAC1B,QAAI,CAAC,IAAI;AAAa,YAAM,IAAI,MAAM,GAAG,SAAS,yBAAyB;AAC3E,WAAO,IAAI;EACb,SAAS,OAAO;AACd,UAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACpE,UAAM,IAAI,MACR,wBAAwB,IAAI,MAAM,MAAM,0CAA0C,IAAI,GAAG;EAE7F;AACF;AAEA,IAAM,QAAQ,OACZ,QACA,QACA,WACsB;AACtB,QAAM,UAAU,MAAM,OAAO,OAAO,QAAQ;IAC1C,UAAU,OAAO;IACjB,MAAM,OAAO;IACb,OAAO,UAAU,OAAO,GAAG;GAC5B;AACD,QAAM,YAAY,MAAM,OAAO,SAAS,EAAE,MAAM,OAAO,MAAM,MAAM,OAAO,KAAI,CAAE;AAChF,SAAO,YAAY,SAAS;AAC5B,UAAQ,IAAI,GAAG,OAAO,IAAI,sBAAsB,UAAU,GAAG,EAAE;AAC/D,UAAQ,IAAI,GAAG,OAAO,IAAI,gBAAgB,UAAU,GAAG,SAAS;AAChE,UAAQ,IACN,GAAG,OAAO,IAAI,WAAW,UAAU,GAAG,aAAa,OAAO,WAAW,qCAAqC,sCAAiC,GAAG;AAEhJ,UAAQ,IAAI,GAAG,OAAO,IAAI,cAAc,UAAU,GAAG,aAAa;AAClE,aAAW,QAAQ,OAAO,SAAS,OAAO,KAAK,CAAA;AAAI,YAAQ,IAAI,GAAG,OAAO,IAAI,IAAI,IAAI,EAAE;AACvF,SAAO;AACT;AAEA,IAAM,cAAc,OAAO,YACzB,IAAI,QAAQ,CAAC,YAAW;AACtB,QAAM,OAAO,YAAW;AACtB,UAAM,QAAQ,WAAW,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAK,CAAE,CAAC;AACtD,YAAQ,CAAC;EACX;AACA,UAAQ,KAAK,UAAU,IAAI;AAC3B,UAAQ,KAAK,WAAW,IAAI;AAC9B,CAAC;AAGI,IAAM,eAAe,CAAC,YAAqC;EAChE,SAAS,aAAa,OAAO,IAAI;EACjC,SAAS,EAAE,GAAG,sBAAsB,GAAG,OAAO,QAAO;EACrD,MAAM,IAAI,QAAM;AACd,UAAM,MACJ,OAAO,cAAc,MAAM,OAAO,SAAU,SAAS,OAAO,GAAG,KAAK;AAEtE,QAAI,CAAC,CAAC,UAAU,QAAQ,KAAK,EAAE,SAAS,GAAG,GAAG;AAC5C,cAAQ,MAAM,0CAA0C,GAAG,GAAG;AAC9D,aAAO;IACT;AACA,UAAM,aAAa,SAAS,OAAO,MAAM;AACzC,QAAI,eAAe,QAAW;AAC5B,YAAM,SAAS,KAAK,MAAM,MAAM,SAAS,YAAY,MAAM,CAAC;AAC5D,YAAM,UAAuB,CAAA;AAC7B,UAAI;AACF,mBAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,OAAO,YAAY,CAAA,CAAE,GAAG;AACjE,gBAAM,OAAO,MAAM,WAAW,MAAM,MAAM;AAC1C,kBAAQ,KACN,MAAM,MAAM,MAAM,MAAM,WAAW,CAAA,GAAI;YACrC,MAAM,MAAM,QAAQ,KAAK;YACzB,MAAM,MAAM,QAAQ;YACpB,GAAI,MAAM,aAAa,SAAY,EAAE,UAAU,MAAM,SAAQ,IAAK,CAAA;YAClE,GAAI,MAAM,SAAS,SAAY,EAAE,MAAM,MAAM,KAAI,IAAK,CAAA;YACtD,KAAK,OAAO,OAAO;WACpB,CAAC;QAEN;MACF,SAAS,OAAO;AACd,cAAM,QAAQ,WAAW,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAK,CAAE,CAAC;AACtD,gBAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AACpE,eAAO;MACT;AACA,aAAO,YAAY,OAAO;IAC5B;AACA,UAAM,OAAO,SAAS,OAAO,IAAI;AACjC,UAAM,WAAW,SAAS,OAAO,WAAW,CAAC,KAAK,QAAQ,IAAI;AAC9D,UAAM,OAAO,SAAS,OAAO,IAAI;AACjC,QAAI;AACJ,QAAI;AACF,kBAAY,MAAM,MAAM,QAAQ,QAAQ;QACtC,MAAM,SAAS,SAAY,OAAO,cAAc,OAAO,SAAS,MAAM,EAAE;QACxE,MAAM,SAAS,OAAO,IAAI,KAAK;QAC/B,GAAI,aAAa,SAAY,EAAE,SAAQ,IAAK,CAAA;QAC5C,GAAI,SAAS,SAAY,EAAE,KAAI,IAAK,CAAA;QACpC;OACD;IACH,SAAS,OAAO;AACd,cAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AACpE,aAAO;IACT;AACA,WAAO,YAAY,CAAC,SAAS,CAAC;EAChC;;;;AD1SK,IAAM,eAAe;AAYrB,IAAMA,gBAAe,OAAO,UAA+B,CAAC,MAA6B;AAC9F,QAAM,EAAE,MAAM,MAAM,GAAG,KAAK,IAAI;AAChC,QAAM,UAAU,cAAc,IAAI;AAClC,QAAM,YAAY,MAAM,OAAO,SAAS;AAAA,IACtC,MAAM,QAAQ;AAAA,IACd,GAAI,SAAS,SAAY,EAAE,KAAK,IAAI,CAAC;AAAA,EACvC,CAAC;AACD,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA,OAAO,YAAY;AACjB,cAAQ,KAAK;AACb,YAAM,UAAU,MAAM;AAAA,IACxB;AAAA,EACF;AACF;AAEA,IAAM,OAAO,CAAC,UACZ,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ;AAGtD,IAAM,eAAe,CAAC,UAAkB;AACtC,QAAM,MACJ,MAAM,KAAK,EAAE,WAAW,GAAG,KAAK,MAAM,KAAK,EAAE,WAAW,GAAG,IACvD,QACA,aAAa,OAAO,MAAM;AAChC,QAAM,SAAS,iBAAiB,KAAK,MAAM,GAAG,CAAC;AAC/C,MAAI,OAAO,WAAW,SAAU,OAAM,IAAI,MAAM,eAAe,MAAM,EAAE;AACvE,SAAO;AACT;AAGO,IAAM,cAA2B;AAAA,EACtC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,SAAS;AAAA,IACP,UAAU;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aACE;AAAA,IACJ;AAAA,IACA,eAAe;AAAA,MACb,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IACf;AAAA,IACA,kBAAkB;AAAA,MAChB,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IACf;AAAA,IACA,cAAc;AAAA,MACZ,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,QAAQ,CAAC,QAAQ,WAAW;AAC1B,UAAM,MAAM,KAAK,OAAO,aAAa,CAAC;AACtC,UAAM,SAAS,KAAK,OAAO,gBAAgB,CAAC;AAC5C,UAAM,WAAW,KAAK,OAAO,QAAQ;AACrC,UAAM,YAAY,KAAK,OAAO,YAAY,CAAC;AAC3C,WAAO,cAAc;AAAA,MACnB,GAAI,OAAO,aAAa,SAAY,EAAE,UAAU,OAAO,SAAS,IAAI,CAAC;AAAA,MACrE,GAAI,OAAO,SAAS,SAAY,EAAE,MAAM,OAAO,KAAK,IAAI,CAAC;AAAA,MACzD,GAAI,OAAO,QAAQ,EAAE,OAAO,OAAO,MAAM,IAAI,CAAC;AAAA,MAC9C,GAAI,WAAW,EAAE,UAAU,aAAa,QAAQ,EAAE,IAAI,CAAC;AAAA,MACvD,GAAI,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,KAAK,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC,EAAG,CAAC,EAAE,EAAE,IAAI,CAAC;AAAA,MACnF,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,MACjC,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EACA,QAAQ,MAAM;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
6
+ "names": ["createServer"]
7
+ }
@@ -2862,7 +2862,7 @@ var renderAdminDocument = (service) => {
2862
2862
  main { padding: 20px; max-width: 1100px; width: 100%; min-width: 0; }
2863
2863
  .view h2 { margin: 0 0 4px; font-size: 22px; letter-spacing: -0.02em; }
2864
2864
  .lede { margin: 0 0 16px; color: var(--muted); }
2865
- .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; }
2865
+ .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr)); gap: 12px; }
2866
2866
  .card {
2867
2867
  background: var(--bg-elev); border: 1px solid var(--line); border-radius: var(--radius);
2868
2868
  padding: 14px 16px; box-shadow: var(--shadow);
@@ -2902,7 +2902,7 @@ var renderAdminDocument = (service) => {
2902
2902
  .empty { color: var(--muted); padding: 24px 8px; }
2903
2903
  dialog {
2904
2904
  border: 1px solid var(--line); border-radius: var(--radius); padding: 0; background: var(--bg-elev);
2905
- color: var(--ink); width: min(640px, calc(100vw - 24px)); box-shadow: none;
2905
+ color: var(--ink); width: min(640px, calc(100% - 24px)); max-width: calc(100vw - 24px); box-shadow: none;
2906
2906
  }
2907
2907
  dialog::backdrop { background: rgb(20 19 17 / 0.45); }
2908
2908
  dialog form, .dialog-body { padding: 16px; display: flex; flex-direction: column; gap: 10px; }
@@ -3726,7 +3726,7 @@ var stateAdminRoutes = (routes) => {
3726
3726
  };
3727
3727
 
3728
3728
  // ../core/dist/version.js
3729
- var PACKAGE_VERSION = true ? "1.10.0" : UNRELEASED_VERSION;
3729
+ var PACKAGE_VERSION = true ? "1.11.0" : UNRELEASED_VERSION;
3730
3730
 
3731
3731
  // ../core/dist/signing.js
3732
3732
  var encoder = new TextEncoder();
@@ -10462,27 +10462,28 @@ ${CSS_RESET}
10462
10462
  --field:0 0 0 1px #e0e0e0,0 2px 4px 0 rgba(0,0,0,.07),0 1px 1.5px 0 rgba(0,0,0,.05);
10463
10463
  --font:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif}
10464
10464
  html,body{margin:0;background:#fff;color:var(--text);font-family:var(--font);font-size:14px;
10465
- line-height:1.4;-webkit-font-smoothing:antialiased}
10466
- .app{min-height:100vh;display:flex;flex-direction:column}
10467
- .summary{background:#fff;padding:24px 16px 8px}
10468
- .pane{padding:8px 16px 32px}
10469
- .inner{max-width:420px;margin:0 auto}
10470
- @media (min-width:992px){
10465
+ line-height:1.4;-webkit-font-smoothing:antialiased;container-type:inline-size}
10466
+ .app{min-height:100vh;min-width:0;max-width:100%;display:flex;flex-direction:column}
10467
+ .summary{background:#fff;padding:24px 16px 8px;min-width:0}
10468
+ .pane{padding:8px 16px 32px;min-width:0}
10469
+ .inner{max-width:min(420px,100%);margin:0 auto;min-width:0}
10470
+ @container (min-width:992px){
10471
10471
  .app{flex-direction:row}
10472
- .summary{flex:1;display:flex;justify-content:flex-end;padding:64px 64px 48px 32px}
10473
- .pane{flex:1;display:flex;justify-content:flex-start;padding:64px 32px 48px 64px;
10472
+ .summary{flex:1;display:flex;justify-content:flex-end;padding:48px 32px 40px 16px}
10473
+ .pane{flex:1;display:flex;justify-content:flex-start;padding:48px 16px 40px 32px;
10474
10474
  box-shadow:15px 0 30px 0 rgba(0,0,0,.18);position:relative}
10475
- .summary .inner,.pane .inner{margin:0;width:380px;max-width:380px}
10475
+ .summary .inner,.pane .inner{margin:0;width:min(380px,100%);max-width:380px}
10476
10476
  .summary .inner{display:flex;flex-direction:column;min-height:calc(100vh - 112px)}
10477
+ .totals{margin-left:58px}
10477
10478
  }
10478
- .header{display:flex;align-items:center;gap:8px;min-height:28px;margin-bottom:32px}
10479
+ .header{display:flex;align-items:center;flex-wrap:wrap;gap:8px;min-height:28px;margin-bottom:32px;min-width:0}
10479
10480
  .back{display:inline-flex;align-items:center;justify-content:center;gap:8px;border:0;
10480
10481
  background:none;padding:4px 6px 4px 2px;margin-left:-2px;border-radius:6px;cursor:pointer;
10481
10482
  color:var(--text);transition:background .15s}
10482
10483
  .back:hover{background:rgba(0,0,0,.05)}
10483
10484
  .back svg{width:12px;height:12px;fill:var(--muted);transition:transform .15s}
10484
10485
  .back:hover svg{transform:translateX(-2px)}
10485
- .merchant{display:inline-flex;align-items:center;gap:10px;font-weight:500;font-size:14px}
10486
+ .merchant{display:inline-flex;align-items:center;gap:10px;min-width:0;font-weight:500;font-size:14px;overflow-wrap:anywhere}
10486
10487
  .avatar{width:28px;height:28px;border-radius:50%;background:#f0f0f0;box-shadow:inset 0 0 0 1px rgba(0,0,0,.06);
10487
10488
  display:inline-flex;align-items:center;justify-content:center;font-size:12px;font-weight:600;color:var(--muted)}
10488
10489
  .badge{display:inline-block;margin-left:4px;padding:1px 6px;border-radius:4px;background:var(--test-bg);
@@ -10493,7 +10494,7 @@ line-height:1.4;-webkit-font-smoothing:antialiased}
10493
10494
  .amount small{font-size:14px;font-weight:500;color:var(--muted);letter-spacing:0;line-height:1.2}
10494
10495
  .amount-note{color:var(--muted);margin:6px 0 0}
10495
10496
  .lines{list-style:none;margin:32px 0 0;padding:0}
10496
- .line{display:flex;gap:16px;align-items:flex-start;padding:0 0 20px}
10497
+ .line{display:flex;gap:12px;align-items:flex-start;padding:0 0 20px;min-width:0}
10497
10498
  .thumb{flex:none;width:42px;height:42px;border-radius:6px;background:#f6f8fa;
10498
10499
  box-shadow:0 2px 5px rgba(50,50,93,.1),0 1px 1px rgba(0,0,0,.07);overflow:hidden;
10499
10500
  display:flex;align-items:center;justify-content:center}
@@ -10504,17 +10505,17 @@ line-height:1.4;-webkit-font-smoothing:antialiased}
10504
10505
  .line-meta{color:var(--muted);font-size:12px;margin-top:2px}
10505
10506
  .line-amount{font-weight:500;font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
10506
10507
  .line-amount .line-meta{text-align:right}
10507
- .totals{margin:4px 0 0 58px;border-top:1px solid var(--line)}
10508
- .totals div{display:flex;justify-content:space-between;padding:14px 0 0;font-variant-numeric:tabular-nums}
10508
+ .totals{margin:4px 0 0;border-top:1px solid var(--line);min-width:0}
10509
+ .totals div{display:flex;justify-content:space-between;gap:8px 12px;flex-wrap:wrap;padding:14px 0 0;font-variant-numeric:tabular-nums}
10509
10510
  .totals .sub{font-weight:500}
10510
10511
  .totals .discount span:first-child{display:inline-flex;align-items:center;gap:6px}
10511
10512
  .totals .discount span:last-child{color:var(--muted)}
10512
10513
  .chip{display:inline-block;padding:2px 8px;border-radius:4px;background:#f0f0f0;font-size:12px;font-weight:500}
10513
10514
  .totals .due{margin-top:14px;padding-top:14px;border-top:1px solid var(--line);font-weight:600}
10514
- .summary-foot{margin-top:auto;padding-top:48px;display:none;align-items:center;gap:14px;color:var(--faint);font-size:12px}
10515
- @media (min-width:992px){.summary-foot{display:flex}}
10516
- .pane-foot{display:flex;justify-content:center;align-items:center;gap:14px;color:var(--faint);font-size:12px;margin-top:32px}
10517
- @media (min-width:992px){.pane-foot{display:none}}
10515
+ .summary-foot{margin-top:auto;padding-top:48px;display:none;align-items:center;flex-wrap:wrap;gap:8px 14px;color:var(--faint);font-size:12px}
10516
+ @container (min-width:992px){.summary-foot{display:flex}}
10517
+ .pane-foot{display:flex;justify-content:center;align-items:center;flex-wrap:wrap;gap:8px 14px;color:var(--faint);font-size:12px;margin-top:32px}
10518
+ @container (min-width:992px){.pane-foot{display:none}}
10518
10519
  .powered{display:inline-flex;align-items:center;gap:4px;padding-right:14px;border-right:1px solid var(--line)}
10519
10520
  .powered b{font-weight:700;font-size:14px;letter-spacing:-.03em;color:rgba(26,26,26,.5)}
10520
10521
  .foot-link{color:inherit;text-decoration:none}
@@ -10524,13 +10525,13 @@ section+section{margin-top:28px}
10524
10525
  .label{display:block;color:var(--muted);font-size:13px;font-weight:500;margin:0 0 6px}
10525
10526
  .field-block+.field-block{margin-top:16px}
10526
10527
  .group{border-radius:6px;box-shadow:var(--field);background:#fff;position:relative}
10527
- .group input,.group select{display:block;width:100%;border:0;background:transparent;outline:none;
10528
+ .group input,.group select{display:block;width:100%;min-width:0;max-width:100%;border:0;background:transparent;outline:none;
10528
10529
  padding:10px 12px;font-size:16px;line-height:1.5;height:44px;border-radius:0}
10529
10530
  .group input::placeholder{color:rgba(26,26,26,.35)}
10530
10531
  .row{position:relative}
10531
10532
  .row+.row{border-top:1px solid #e0e0e0}
10532
- .split{display:flex}
10533
- .split>.row{flex:1}
10533
+ .split{display:flex;min-width:0}
10534
+ .split>.row{flex:1;min-width:0}
10534
10535
  .split>.row+.row{border-top:0;border-left:1px solid #e0e0e0}
10535
10536
  .row:not(.split):focus-within{z-index:1;box-shadow:0 0 0 1px rgba(50,151,211,.7),0 0 0 4px var(--ring);border-radius:6px}
10536
10537
  .group>.row:first-child:focus-within,.group>.row:first-child{border-radius:6px 6px 0 0}
@@ -10540,11 +10541,11 @@ section+section{margin-top:28px}
10540
10541
  .icons svg{width:24px;height:16px;display:block;transition:opacity .15s,transform .15s}
10541
10542
  .icons[data-brand] svg{display:none}
10542
10543
  .icons[data-brand] svg.active{display:block;transform:scale(1.1)}
10543
- .group .card-input{padding-right:120px}
10544
+ .group .card-input{padding-right:min(120px,42%)}
10544
10545
  .group .cvc-input{padding-right:48px}
10545
10546
  .row.invalid{box-shadow:0 0 0 1px var(--danger);z-index:1}
10546
10547
  .row.invalid input{color:var(--danger)}
10547
- .readonly{padding:11px 12px;border-radius:6px;box-shadow:var(--field);background:#fafafa;color:var(--muted);font-size:16px}
10548
+ .readonly{padding:11px 12px;border-radius:6px;box-shadow:var(--field);background:#fafafa;color:var(--muted);font-size:16px;overflow-wrap:anywhere}
10548
10549
  select{appearance:none;-webkit-appearance:none;cursor:pointer;
10549
10550
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill='%23697386' d='M6 8.5 1.8 4.3l1-1L6 6.5l3.2-3.2 1 1z'/%3E%3C/svg%3E")!important;
10550
10551
  background-repeat:no-repeat!important;background-position:right 12px center!important;background-size:12px!important}
@@ -10567,7 +10568,7 @@ select{appearance:none;-webkit-appearance:none;cursor:pointer;
10567
10568
  @keyframes spin{to{transform:rotate(360deg)}}
10568
10569
  .fine{color:var(--muted);font-size:12px;text-align:center;margin:12px 0 0}
10569
10570
  .testcards{margin:0 0 28px;border-radius:8px;border:1px solid #f5d37a;background:#fffbf0;overflow:hidden}
10570
- .testcards summary{list-style:none;display:flex;align-items:center;gap:8px;padding:10px 12px;cursor:pointer;user-select:none}
10571
+ .testcards summary{list-style:none;display:flex;align-items:center;flex-wrap:wrap;gap:8px;padding:10px 12px;cursor:pointer;user-select:none}
10571
10572
  .testcards summary::-webkit-details-marker{display:none}
10572
10573
  .testcards summary .title{font-weight:600;color:var(--test-fg)}
10573
10574
  .testcards summary .hint{color:#a8680a;font-size:12px;margin-left:auto}
@@ -10577,15 +10578,15 @@ select{appearance:none;-webkit-appearance:none;cursor:pointer;
10577
10578
  .tc-group{margin-top:10px}
10578
10579
  .tc-group-label{font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:#a8680a;margin:0 0 6px}
10579
10580
  .tc-grid{display:flex;flex-wrap:wrap;gap:6px}
10580
- .tc{display:inline-flex;align-items:center;gap:6px;padding:5px 9px 5px 7px;border-radius:6px;border:0;background:#fff;
10581
+ .tc{display:inline-flex;align-items:center;gap:6px;max-width:100%;padding:5px 9px 5px 7px;border-radius:6px;border:0;background:#fff;
10581
10582
  text-align:left;cursor:pointer;box-shadow:0 0 0 1px rgba(0,0,0,.08),0 1px 2px rgba(0,0,0,.05);
10582
10583
  transition:box-shadow .15s,transform .1s}
10583
10584
  .tc:hover{box-shadow:0 0 0 1px rgba(0,0,0,.14),0 3px 6px rgba(0,0,0,.08)}
10584
10585
  .tc:active{transform:translateY(1px)}
10585
10586
  .tc:focus-visible{outline:none;box-shadow:0 0 0 2px var(--accent)}
10586
10587
  .tc svg{flex:none;width:24px;height:16px}
10587
- .tc .tc-text{display:inline-flex;align-items:baseline;gap:6px}
10588
- .tc .tc-label{font-size:12px;font-weight:500;white-space:nowrap}
10588
+ .tc .tc-text{display:inline-flex;align-items:baseline;flex-wrap:wrap;gap:6px;min-width:0}
10589
+ .tc .tc-label{font-size:12px;font-weight:500}
10589
10590
  .tc .tc-num{font-size:11px;color:var(--faint);font-variant-numeric:tabular-nums}
10590
10591
  .tc[data-group=succeeds]{border-left:3px solid #1ea672}
10591
10592
  .tc[data-group=declines]{border-left:3px solid var(--danger)}
@@ -10602,8 +10603,8 @@ select{appearance:none;-webkit-appearance:none;cursor:pointer;
10602
10603
  .done p{color:var(--muted);margin:0}
10603
10604
  .totals .after{color:var(--muted)}
10604
10605
  .promo{padding:14px 0 0}
10605
- .promo-row{display:flex;gap:8px;align-items:center}
10606
- .promo-row .group{flex:1}
10606
+ .promo-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
10607
+ .promo-row .group{flex:1;min-width:0}
10607
10608
  .promo-row .group input{height:36px;font-size:14px;padding:6px 10px}
10608
10609
  .apply,.link{border:0;background:none;color:var(--accent);font-weight:600;cursor:pointer;padding:6px 4px}
10609
10610
  .apply:hover,.link:hover{color:var(--accent-hover)}
@@ -11862,19 +11863,20 @@ ${CSS_RESET}
11862
11863
  :root{--text:#1a1f36;--muted:#697386;--faint:#a3acb9;--line:#e3e8ee;--accent:#635bff;--accent-hover:#5851e5;
11863
11864
  --danger:#df1b41;--ok:#1ea672;--warn:#c44c00;--test-bg:#ffde92;--test-fg:#983705;
11864
11865
  --font:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif}
11865
- html,body{margin:0;color:var(--text);font-family:var(--font);font-size:14px;line-height:1.45;-webkit-font-smoothing:antialiased}
11866
- .app{min-height:100vh;display:flex;flex-direction:column}
11867
- .side{background:#f6f9fc;padding:24px 20px}
11868
- .main{padding:24px 20px 48px;flex:1}
11869
- @media (min-width:900px){.app{flex-direction:row}.side{width:40%;display:flex;justify-content:flex-end;padding:64px 48px}
11870
- .side .inner{width:320px}.main{padding:64px 48px}.main .inner{max-width:560px}}
11866
+ html,body{margin:0;color:var(--text);font-family:var(--font);font-size:14px;line-height:1.45;-webkit-font-smoothing:antialiased;container-type:inline-size}
11867
+ .app{min-height:100vh;min-width:0;max-width:100%;display:flex;flex-direction:column}
11868
+ .side{background:#f6f9fc;padding:24px 20px;min-width:0}
11869
+ .main{padding:24px 20px 48px;flex:1;min-width:0}
11870
+ .inner{min-width:0;max-width:100%}
11871
+ @container (min-width:900px){.app{flex-direction:row}.side{width:40%;display:flex;justify-content:flex-end;padding:48px 32px}
11872
+ .side .inner{width:100%;max-width:320px}.main{padding:48px 32px}.main .inner{max-width:min(560px,100%)}}
11871
11873
  .merchant{display:flex;align-items:center;gap:10px;font-weight:600;font-size:15px}
11872
11874
  .avatar{width:28px;height:28px;border-radius:50%;background:#e3e8ee;display:inline-flex;align-items:center;justify-content:center;font-size:12px;font-weight:600;color:var(--muted)}
11873
11875
  .badge{display:inline-block;padding:1px 6px;border-radius:4px;background:var(--test-bg);color:var(--test-fg);font-size:11px;font-weight:600;letter-spacing:.03em;text-transform:uppercase}
11874
11876
  .back{display:inline-flex;align-items:center;gap:6px;margin-top:24px;color:var(--muted);text-decoration:none;font-weight:500}
11875
11877
  .back:hover{color:var(--text)}
11876
11878
  .tagline{color:var(--muted);margin:16px 0 0}
11877
- .legal{margin-top:32px;color:var(--faint);font-size:12px;display:flex;gap:12px}
11879
+ .legal{margin-top:32px;color:var(--faint);font-size:12px;display:flex;flex-wrap:wrap;gap:12px}
11878
11880
  .legal a{color:inherit}
11879
11881
  h1{font-size:20px;font-weight:600;margin:0 0 20px}
11880
11882
  h2{font-size:13px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);margin:0 0 12px}
@@ -11894,16 +11896,16 @@ font-weight:600;text-decoration:none;background:#fff;color:var(--text);box-shado
11894
11896
  .btn.primary{background:var(--accent);color:#fff;box-shadow:none}.btn.primary:hover{background:var(--accent-hover)}
11895
11897
  .btn.danger{background:var(--danger);color:#fff;box-shadow:none}
11896
11898
  .link{border:0;background:none;padding:0;color:var(--accent);font-weight:600;cursor:pointer;text-decoration:none}
11897
- .row{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:10px 0}
11899
+ .row{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px 12px;padding:10px 0;min-width:0}
11898
11900
  .row+.row{border-top:1px solid var(--line)}
11899
11901
  .notice{padding:10px 12px;border-radius:6px;background:#eef8f2;color:#05690d;margin:0 0 20px}
11900
11902
  .error{padding:10px 12px;border-radius:6px;background:#ffe7f2;color:#b3093c;margin:0 0 20px}
11901
11903
  label.field{display:block;margin:0 0 14px}
11902
11904
  label.field span{display:block;color:var(--muted);font-weight:500;margin-bottom:6px}
11903
- input[type=text],input[type=email],input[type=number],textarea,select{width:100%;padding:8px 10px;border-radius:6px;border:0;
11905
+ input[type=text],input[type=email],input[type=number],textarea,select{width:100%;min-width:0;max-width:100%;padding:8px 10px;border-radius:6px;border:0;
11904
11906
  box-shadow:0 0 0 1px rgba(60,66,87,.16),0 2px 5px rgba(60,66,87,.08);background:#fff}
11905
11907
  textarea{min-height:72px;resize:vertical}
11906
- .split{display:flex;gap:10px}.split>*{flex:1}
11908
+ .split{display:flex;flex-wrap:wrap;gap:10px;min-width:0}.split>*{flex:1;min-width:min(100%,8rem)}
11907
11909
  .option{display:flex;gap:10px;align-items:flex-start;padding:12px;border-radius:8px;box-shadow:0 0 0 1px var(--line);margin:0 0 8px;cursor:pointer}
11908
11910
  .option:has(input:checked){box-shadow:0 0 0 2px var(--accent)}
11909
11911
  .option input{margin-top:3px}
@@ -19871,4 +19873,4 @@ export {
19871
19873
  createRuntime2 as createRuntime,
19872
19874
  StripeAPI
19873
19875
  };
19874
- //# sourceMappingURL=chunk-YUKBBY4J.js.map
19876
+ //# sourceMappingURL=chunk-RPSJESGN.js.map