mcp-scraper 0.57.3 → 0.60.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 (38) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +2 -2
  3. package/dist/bin/api-server.cjs +549 -107
  4. package/dist/bin/api-server.cjs.map +1 -1
  5. package/dist/bin/api-server.js +2 -2
  6. package/dist/bin/mcp-scraper-cli.cjs +1 -1
  7. package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
  8. package/dist/bin/mcp-scraper-cli.js +1 -1
  9. package/dist/bin/mcp-scraper-install.cjs +2 -2
  10. package/dist/bin/mcp-scraper-install.cjs.map +1 -1
  11. package/dist/bin/mcp-scraper-install.js +2 -2
  12. package/dist/bin/mcp-stdio-server.cjs +36 -8
  13. package/dist/bin/mcp-stdio-server.cjs.map +1 -1
  14. package/dist/bin/mcp-stdio-server.js +4 -4
  15. package/dist/{chunk-R6CO77BN.js → chunk-2U2ZDDSI.js} +3 -3
  16. package/dist/{chunk-R6CO77BN.js.map → chunk-2U2ZDDSI.js.map} +1 -1
  17. package/dist/{chunk-QSUSTYB3.js → chunk-AIA3MFT2.js} +38 -9
  18. package/dist/chunk-AIA3MFT2.js.map +1 -0
  19. package/dist/chunk-AQA2ZL4X.js +7 -0
  20. package/dist/chunk-AQA2ZL4X.js.map +1 -0
  21. package/dist/{chunk-HU4R6BP2.js → chunk-IMBMDZUO.js} +2 -2
  22. package/dist/{chunk-HU4R6BP2.js.map → chunk-IMBMDZUO.js.map} +1 -1
  23. package/dist/{chunk-5XYBKE3X.js → chunk-KMGRM4FL.js} +2 -2
  24. package/dist/editorial-reading-room/assets/app.js +17 -3
  25. package/dist/{extract-bundle-H7JEELY7.js → extract-bundle-XRRN6NAZ.js} +3 -3
  26. package/dist/{server-EP2SK2ID.js → server-IRKNU6LO.js} +505 -105
  27. package/dist/server-IRKNU6LO.js.map +1 -0
  28. package/dist/{site-extract-repository-CFMSWAVL.js → site-extract-repository-XAA2FVDN.js} +3 -3
  29. package/dist/{worker-S2WXELUC.js → worker-QFSOMF2N.js} +2 -2
  30. package/package.json +1 -1
  31. package/dist/chunk-LHH3GX3W.js +0 -7
  32. package/dist/chunk-LHH3GX3W.js.map +0 -1
  33. package/dist/chunk-QSUSTYB3.js.map +0 -1
  34. package/dist/server-EP2SK2ID.js.map +0 -1
  35. /package/dist/{chunk-5XYBKE3X.js.map → chunk-KMGRM4FL.js.map} +0 -0
  36. /package/dist/{extract-bundle-H7JEELY7.js.map → extract-bundle-XRRN6NAZ.js.map} +0 -0
  37. /package/dist/{site-extract-repository-CFMSWAVL.js.map → site-extract-repository-XAA2FVDN.js.map} +0 -0
  38. /package/dist/{worker-S2WXELUC.js.map → worker-QFSOMF2N.js.map} +0 -0
@@ -115,6 +115,7 @@ import {
115
115
  CommonsClaimPublicationInputSchema,
116
116
  CommonsPreparePublicationInputSchema,
117
117
  CommonsPublishEditorialInputSchema,
118
+ CommonsUpdateEditorialArticleInputSchema,
118
119
  CommonsValidatePublicationInputSchema,
119
120
  CreateArtifactTemplateInputSchema,
120
121
  CreateEditorialReadingRoomInputSchema,
@@ -169,7 +170,7 @@ import {
169
170
  resolveDeploymentProfile,
170
171
  resolveLocalSourcebookSchemaType,
171
172
  transcribeMediaUrl
172
- } from "./chunk-QSUSTYB3.js";
173
+ } from "./chunk-AIA3MFT2.js";
173
174
  import {
174
175
  auditImageUrls,
175
176
  auditImages,
@@ -225,7 +226,7 @@ import {
225
226
  } from "./chunk-FG6LJGJ7.js";
226
227
  import {
227
228
  PACKAGE_VERSION
228
- } from "./chunk-LHH3GX3W.js";
229
+ } from "./chunk-AQA2ZL4X.js";
229
230
  import {
230
231
  abandonExtractSettlement,
231
232
  countSuccessfulPages,
@@ -248,7 +249,7 @@ import {
248
249
  setExtractJobTotal,
249
250
  settleExtractJob,
250
251
  terminalExtractJobStatus
251
- } from "./chunk-5XYBKE3X.js";
252
+ } from "./chunk-KMGRM4FL.js";
252
253
  import {
253
254
  BROWSER_OPEN_MIN_BALANCE_MC,
254
255
  CONCURRENCY_PACK_INVOICE_DESCRIPTION,
@@ -301,7 +302,7 @@ import {
301
302
  tierChangeLeavesPrivateOffer,
302
303
  tierCreditsPerInterval,
303
304
  vendorCostUsdToMc
304
- } from "./chunk-R6CO77BN.js";
305
+ } from "./chunk-2U2ZDDSI.js";
305
306
  import {
306
307
  CaptchaError,
307
308
  MapsSearchIncompletePageError,
@@ -9393,7 +9394,7 @@ var siteExtractFn = inngest.createFunction(
9393
9394
  });
9394
9395
  }) : null;
9395
9396
  const finalized = await step.run("finalize", async () => {
9396
- const { assembleExtractArtifacts } = await import("./extract-bundle-H7JEELY7.js");
9397
+ const { assembleExtractArtifacts } = await import("./extract-bundle-XRRN6NAZ.js");
9397
9398
  const current = await getExtractJob(jobId2);
9398
9399
  if (!current) throw new Error("extract job disappeared before finalization");
9399
9400
  const stored = await assembleExtractArtifacts(current, { branding, imageAudit });
@@ -32751,9 +32752,7 @@ function socialMeta(input) {
32751
32752
  ];
32752
32753
  return tags.join("\n ");
32753
32754
  }
32754
- function renderEditorialReadingRoom(input, now = /* @__PURE__ */ new Date()) {
32755
- const sourceBytes = input.articles.reduce((total, article) => total + Buffer.byteLength(article.markdown), 0);
32756
- if (sourceBytes > 2e6) throw new Error("Editorial reading-room Markdown must be 2,000,000 bytes or fewer in total.");
32755
+ function buildEditorialArticles(input) {
32757
32756
  const seenSlugs = /* @__PURE__ */ new Set();
32758
32757
  const seenOrders = /* @__PURE__ */ new Set();
32759
32758
  const parser = markdownRenderer();
@@ -32780,7 +32779,19 @@ function renderEditorialReadingRoom(input, now = /* @__PURE__ */ new Date()) {
32780
32779
  html: rendered
32781
32780
  };
32782
32781
  });
32782
+ return { articles, warnings, totalWordCount };
32783
+ }
32784
+ function renderEditorialArticleModels(input) {
32785
+ return buildEditorialArticles(input).articles;
32786
+ }
32787
+ function renderEditorialReadingRoom(input, now = /* @__PURE__ */ new Date()) {
32788
+ const sourceBytes = input.articles.reduce((total, article) => total + Buffer.byteLength(article.markdown), 0);
32789
+ if (sourceBytes > 2e6) throw new Error("Editorial reading-room Markdown must be 2,000,000 bytes or fewer in total.");
32783
32790
  const generatedAt = now.toISOString();
32791
+ const built = buildEditorialArticles(input);
32792
+ const articles = built.articles;
32793
+ const warnings = built.warnings;
32794
+ const totalWordCount = built.totalWordCount;
32784
32795
  const data = { ...input, generatedAt, articles };
32785
32796
  const template = readAsset("index.html");
32786
32797
  const html = template.replace("<title>Editorial Reading Room</title>", `<title>${escapeHtml5(input.site.title)}</title>`).replace('content="A mobile-first editorial reading room."', `content="${escapeHtml5(input.deck || input.site.heroTitle)}"`).replace("<!--__READING_ROOM_SOCIAL_META__-->", socialMeta(input)).replace("/*__READING_ROOM_STYLES__*/", readAsset("styles.css")).replace("/*__READING_ROOM_DATA__*/", escapedJsonForHtml(data)).replace("/*__READING_ROOM_SCRIPT__*/", readAsset("app.js"));
@@ -33229,6 +33240,134 @@ async function hostEntityImages(input) {
33229
33240
  return rewrite;
33230
33241
  }
33231
33242
 
33243
+ // src/api/commons-embeddings.ts
33244
+ import { neon } from "@neondatabase/serverless";
33245
+ var COMMONS_EMBED_PROVIDER = "jina";
33246
+ var _vectorSql = null;
33247
+ var vectorSchemaReady = false;
33248
+ function commonsEmbedModel() {
33249
+ return (process.env.JINA_EMBED_MODEL ?? "jina-embeddings-v5-omni-small").trim();
33250
+ }
33251
+ function commonsEmbedDim() {
33252
+ return Number((process.env.JINA_EMBED_DIM ?? "1024").trim());
33253
+ }
33254
+ function commonsSemanticSearchConfigured() {
33255
+ return Boolean(process.env.JINA_API_KEY?.trim() && process.env.MEMORY_DATABASE_URL?.trim());
33256
+ }
33257
+ function vectorSql() {
33258
+ if (_vectorSql) return _vectorSql;
33259
+ const url = process.env.MEMORY_DATABASE_URL?.trim();
33260
+ if (!url) throw new Error("MEMORY_DATABASE_URL is not set; Commons semantic search needs the shared Postgres.");
33261
+ _vectorSql = neon(url);
33262
+ return _vectorSql;
33263
+ }
33264
+ async function ensureCommonsVectorSchema() {
33265
+ if (vectorSchemaReady) return;
33266
+ const dimension = commonsEmbedDim();
33267
+ await vectorSql().query("CREATE EXTENSION IF NOT EXISTS vector");
33268
+ await vectorSql().query(`
33269
+ CREATE TABLE IF NOT EXISTS commons_index_vectors (
33270
+ document_id TEXT PRIMARY KEY,
33271
+ entity_id TEXT NOT NULL,
33272
+ document_type TEXT NOT NULL,
33273
+ title TEXT NOT NULL,
33274
+ embedding vector(${dimension}) NOT NULL,
33275
+ model TEXT NOT NULL,
33276
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
33277
+ )
33278
+ `);
33279
+ await vectorSql().query("CREATE INDEX IF NOT EXISTS commons_index_vectors_entity ON commons_index_vectors(entity_id)");
33280
+ vectorSchemaReady = true;
33281
+ }
33282
+ async function embedCommonsTexts(texts) {
33283
+ const apiKey = process.env.JINA_API_KEY?.trim();
33284
+ if (!apiKey) throw new Error("JINA_API_KEY is not set; Commons semantic search cannot embed.");
33285
+ if (!texts.length) return [];
33286
+ const response = await fetch("https://api.jina.ai/v1/embeddings", {
33287
+ method: "POST",
33288
+ headers: { authorization: `Bearer ${apiKey}`, "content-type": "application/json" },
33289
+ body: JSON.stringify({
33290
+ model: commonsEmbedModel(),
33291
+ dimensions: commonsEmbedDim(),
33292
+ input: texts.map((text2) => ({ text: text2.slice(0, 8e3) }))
33293
+ }),
33294
+ signal: AbortSignal.timeout(6e4)
33295
+ });
33296
+ if (!response.ok) {
33297
+ throw new Error(`Jina embedding request failed with HTTP ${response.status}: ${(await response.text()).slice(0, 200)}`);
33298
+ }
33299
+ const payload = await response.json();
33300
+ const vectors = (payload.data ?? []).map((item) => item.embedding);
33301
+ if (vectors.length !== texts.length) {
33302
+ throw new Error(`Jina returned ${vectors.length} embeddings for ${texts.length} inputs.`);
33303
+ }
33304
+ return vectors;
33305
+ }
33306
+ async function embedQueuedCommonsDocuments(limit = 50) {
33307
+ if (!commonsSemanticSearchConfigured()) return { claimed: 0, embedded: 0, failed: 0, remaining: 0 };
33308
+ await ensureCommonsVectorSchema();
33309
+ const bounded = Math.max(1, Math.min(200, Math.floor(limit)));
33310
+ const queued = await getDb().execute({
33311
+ sql: `SELECT id, entity_id, document_type, title, text FROM commons_index_documents
33312
+ WHERE embedding_status IN ('queued', 'failed') ORDER BY updated_at ASC LIMIT ?`,
33313
+ args: [bounded]
33314
+ });
33315
+ const rows = queued.rows;
33316
+ if (!rows.length) return { claimed: 0, embedded: 0, failed: 0, remaining: await queuedCommonsDocumentCount() };
33317
+ let embedded = 0;
33318
+ let failed = 0;
33319
+ const model = commonsEmbedModel();
33320
+ try {
33321
+ const vectors = await embedCommonsTexts(rows.map((row) => `${row.title}
33322
+
33323
+ ${row.text}`));
33324
+ for (const [index, row] of rows.entries()) {
33325
+ const literal = `[${vectors[index].join(",")}]`;
33326
+ await vectorSql().query(
33327
+ `INSERT INTO commons_index_vectors (document_id, entity_id, document_type, title, embedding, model, updated_at)
33328
+ VALUES ($1, $2, $3, $4, $5::vector, $6, now())
33329
+ ON CONFLICT (document_id) DO UPDATE SET entity_id = EXCLUDED.entity_id, document_type = EXCLUDED.document_type,
33330
+ title = EXCLUDED.title, embedding = EXCLUDED.embedding, model = EXCLUDED.model, updated_at = now()`,
33331
+ [row.id, row.entity_id, row.document_type, row.title, literal, model]
33332
+ );
33333
+ await getDb().execute({
33334
+ sql: `UPDATE commons_index_documents SET embedding_status = 'indexed', embedding_provider = ?, embedding_model = ?,
33335
+ vector_ref = ?, indexed_at = ?, error = NULL WHERE id = ?`,
33336
+ args: [COMMONS_EMBED_PROVIDER, model, row.id, (/* @__PURE__ */ new Date()).toISOString(), row.id]
33337
+ });
33338
+ embedded += 1;
33339
+ }
33340
+ } catch (error) {
33341
+ failed = rows.length - embedded;
33342
+ const message = (error instanceof Error ? error.message : String(error)).slice(0, 500);
33343
+ for (const row of rows.slice(embedded)) {
33344
+ await getDb().execute({
33345
+ sql: `UPDATE commons_index_documents SET embedding_status = 'failed', error = ? WHERE id = ?`,
33346
+ args: [message, row.id]
33347
+ }).catch(() => void 0);
33348
+ }
33349
+ }
33350
+ return { claimed: rows.length, embedded, failed, remaining: await queuedCommonsDocumentCount() };
33351
+ }
33352
+ async function queuedCommonsDocumentCount() {
33353
+ const result = await getDb().execute(`SELECT COUNT(*) AS n FROM commons_index_documents WHERE embedding_status IN ('queued', 'failed')`);
33354
+ return Number(result.rows[0]?.n ?? 0);
33355
+ }
33356
+ async function semanticCommonsEntityScores(query, limit = 40) {
33357
+ const scores = /* @__PURE__ */ new Map();
33358
+ if (!commonsSemanticSearchConfigured() || !query.trim()) return scores;
33359
+ await ensureCommonsVectorSchema();
33360
+ const [vector] = await embedCommonsTexts([query]);
33361
+ if (!vector) return scores;
33362
+ const rows = await vectorSql().query(
33363
+ `SELECT entity_id, MAX(1 - (embedding <=> $1::vector)) AS score
33364
+ FROM commons_index_vectors GROUP BY entity_id ORDER BY score DESC LIMIT $2`,
33365
+ [`[${vector.join(",")}]`, Math.max(1, Math.min(100, limit))]
33366
+ );
33367
+ for (const row of rows) scores.set(String(row.entity_id), Number(row.score));
33368
+ return scores;
33369
+ }
33370
+
33232
33371
  // src/api/schema-presence.ts
33233
33372
  var cache = null;
33234
33373
  async function loadSchemaObjects() {
@@ -33883,17 +34022,35 @@ async function searchCommonsEntities(filters = {}, userId) {
33883
34022
  args.push(mergedFilters.updatedAfter);
33884
34023
  }
33885
34024
  const terms = tokenize(mergedFilters.query);
33886
- for (const term of terms) {
33887
- clauses.push(`(
33888
- search_text LIKE ?
33889
- OR EXISTS (
33890
- SELECT 1 FROM commons_claims
33891
- WHERE commons_claims.subject_entity_id = commons_entities.id
33892
- AND (commons_claims.predicate LIKE ? OR commons_claims.predicate_label LIKE ? OR commons_claims.title LIKE ? OR commons_claims.object_url LIKE ?)
33893
- )
33894
- )`);
33895
- const pattern = `%${escapeLike(term)}%`;
33896
- args.push(pattern, pattern, pattern, pattern, pattern);
34025
+ const searchMode = mergedFilters.mode === "lexical" || mergedFilters.mode === "semantic" ? mergedFilters.mode : "hybrid";
34026
+ const semanticScores = !terms.length || searchMode === "lexical" || !commonsSemanticSearchConfigured() ? /* @__PURE__ */ new Map() : await semanticCommonsEntityScores(String(mergedFilters.query ?? ""), SEARCH_CANDIDATE_LIMIT).catch(() => /* @__PURE__ */ new Map());
34027
+ const semanticIds = [...semanticScores.entries()].filter(([, score]) => score >= 0.6).sort((left, right) => right[1] - left[1]).slice(0, 60).map(([id]) => id);
34028
+ if (terms.length) {
34029
+ const termClauses = [];
34030
+ for (const term of terms) {
34031
+ termClauses.push(`(
34032
+ search_text LIKE ?
34033
+ OR EXISTS (
34034
+ SELECT 1 FROM commons_claims
34035
+ WHERE commons_claims.subject_entity_id = commons_entities.id
34036
+ AND (commons_claims.predicate LIKE ? OR commons_claims.predicate_label LIKE ? OR commons_claims.title LIKE ? OR commons_claims.object_url LIKE ?)
34037
+ )
34038
+ )`);
34039
+ const pattern = `%${escapeLike(term)}%`;
34040
+ args.push(pattern, pattern, pattern, pattern, pattern);
34041
+ }
34042
+ const lexicalClause = `(${termClauses.join(" AND ")})`;
34043
+ if (searchMode === "semantic") {
34044
+ if (!semanticIds.length) return { results: [], filters: mergedFilters, limit, offset };
34045
+ args.length -= terms.length * 5;
34046
+ clauses.push(`id IN (${semanticIds.map(() => "?").join(", ")})`);
34047
+ args.push(...semanticIds);
34048
+ } else if (semanticIds.length) {
34049
+ clauses.push(`(${lexicalClause} OR id IN (${semanticIds.map(() => "?").join(", ")}))`);
34050
+ args.push(...semanticIds);
34051
+ } else {
34052
+ clauses.push(lexicalClause);
34053
+ }
33897
34054
  }
33898
34055
  if (!terms.length) {
33899
34056
  args.push(limit, offset);
@@ -33930,6 +34087,7 @@ async function searchCommonsEntities(filters = {}, userId) {
33930
34087
  `,
33931
34088
  args
33932
34089
  });
34090
+ const mode = searchMode;
33933
34091
  const ranked = candidates.rows.map((row) => {
33934
34092
  const record = row;
33935
34093
  const score = relevanceScore(terms, {
@@ -33940,8 +34098,10 @@ async function searchCommonsEntities(filters = {}, userId) {
33940
34098
  searchText: String(record.search_text ?? ""),
33941
34099
  claimText: String(record.claim_text ?? "")
33942
34100
  });
33943
- return { id: String(record.id), updatedAt: String(record.updated_at ?? ""), title: String(record.title ?? ""), score };
33944
- }).filter((candidate) => candidate.score > 0).sort((left, right) => right.score - left.score || right.updatedAt.localeCompare(left.updatedAt) || left.title.localeCompare(right.title));
34101
+ const semantic = semanticScores.get(String(record.id)) ?? 0;
34102
+ const fused = mode === "semantic" ? semantic * 100 : score + semantic * 60;
34103
+ return { id: String(record.id), updatedAt: String(record.updated_at ?? ""), title: String(record.title ?? ""), score: fused, lexical: score, semantic };
34104
+ }).filter((candidate) => mode === "semantic" ? candidate.semantic > 0 : candidate.lexical > 0 || candidate.semantic >= 0.62).sort((left, right) => right.score - left.score || right.updatedAt.localeCompare(left.updatedAt) || left.title.localeCompare(right.title));
33945
34105
  const pageIds = ranked.slice(offset, offset + limit).map((candidate) => candidate.id);
33946
34106
  if (!pageIds.length) return { results: [], filters: mergedFilters, limit, offset };
33947
34107
  const page = await getDb().execute({
@@ -35428,6 +35588,7 @@ function normalizeRelatedEntities(related) {
35428
35588
  }
35429
35589
  function sanitizeSearchFilters(filters) {
35430
35590
  return {
35591
+ mode: filters.mode === "lexical" || filters.mode === "semantic" ? filters.mode : "hybrid",
35431
35592
  query: optionalText2(filters.query, 300) ?? void 0,
35432
35593
  entityType: filters.entityType ? normalizeEntityType(filters.entityType) : void 0,
35433
35594
  tag: optionalText2(filters.tag, 80) ?? void 0,
@@ -35701,6 +35862,97 @@ var CommonsRepositoryError = class extends Error {
35701
35862
 
35702
35863
  // src/api/commons-publication-repository.ts
35703
35864
  import { createHash as createHash16, randomUUID as randomUUID18 } from "crypto";
35865
+
35866
+ // src/editorial-reading-room/article-page.ts
35867
+ function escapeHtml6(value) {
35868
+ return String(value ?? "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
35869
+ }
35870
+ function articlePath(origin, slug4) {
35871
+ return `${origin.replace(/\/+$/, "")}/${encodeURIComponent(slug4)}`;
35872
+ }
35873
+ function renderEditorialArticlePage(input) {
35874
+ const articles = renderEditorialArticleModels(input.edition);
35875
+ const index = articles.findIndex((article2) => article2.slug === input.articleSlug);
35876
+ if (index === -1) return null;
35877
+ const article = articles[index];
35878
+ const previous = index > 0 ? articles[index - 1] : null;
35879
+ const next = index < articles.length - 1 ? articles[index + 1] : null;
35880
+ const canonicalUrl = articlePath(input.origin, article.slug);
35881
+ const site = input.edition.site;
35882
+ const description = article.summary || input.edition.deck || site.title;
35883
+ const jsonLd = JSON.stringify({
35884
+ "@context": "https://schema.org",
35885
+ "@type": "Article",
35886
+ "@id": `${canonicalUrl}#article`,
35887
+ headline: article.title,
35888
+ description,
35889
+ articleSection: article.category,
35890
+ wordCount: article.wordCount,
35891
+ url: canonicalUrl,
35892
+ isPartOf: { "@type": "CollectionPage", "@id": `${input.editionUrl}#collection`, name: site.title, url: input.editionUrl },
35893
+ publisher: { "@type": "Organization", name: input.publicationTitle, url: input.origin }
35894
+ }).replace(/</g, "\\u003c");
35895
+ const jumps = article.toc.length ? `<nav class="article-jumps" aria-label="On this page">${article.toc.map((item) => `<a href="#${escapeHtml6(item.id)}">${escapeHtml6(item.title)}</a>`).join("")}</nav>` : "";
35896
+ const neighbour = (item, label) => item ? `<a class="neighbour" href="${escapeHtml6(articlePath(input.origin, item.slug))}"><span>${label}</span><strong>${escapeHtml6(item.title)}</strong></a>` : "";
35897
+ const html = `<!doctype html>
35898
+ <html lang="en">
35899
+ <head>
35900
+ <meta charset="utf-8">
35901
+ <meta name="viewport" content="width=device-width, initial-scale=1">
35902
+ <title>${escapeHtml6(article.title)} \u2014 ${escapeHtml6(input.publicationTitle)}</title>
35903
+ <meta name="description" content="${escapeHtml6(description)}">
35904
+ <link rel="canonical" href="${escapeHtml6(canonicalUrl)}">
35905
+ <meta property="og:type" content="article">
35906
+ <meta property="og:title" content="${escapeHtml6(article.title)}">
35907
+ <meta property="og:description" content="${escapeHtml6(description)}">
35908
+ <meta property="og:url" content="${escapeHtml6(canonicalUrl)}">
35909
+ <meta property="og:site_name" content="${escapeHtml6(input.publicationTitle)}">
35910
+ <meta name="twitter:card" content="summary_large_image">
35911
+ <meta name="twitter:title" content="${escapeHtml6(article.title)}">
35912
+ <meta name="twitter:description" content="${escapeHtml6(description)}">
35913
+ <script type="application/ld+json">${jsonLd}</script>
35914
+ <style>
35915
+ :root{color-scheme:light dark;--ink:#12171f;--muted:#5b6672;--rule:#dfe4ea;--bg:#fbfbfa;--accent:#8a6a2f}
35916
+ *{box-sizing:border-box}
35917
+ body{margin:0;background:var(--bg);color:var(--ink);font:17px/1.65 Georgia,"Times New Roman",serif}
35918
+ a{color:inherit}
35919
+ header.masthead{border-bottom:1px solid var(--rule);padding:18px 20px}
35920
+ header.masthead a{font:600 13px/1 ui-sans-serif,system-ui,sans-serif;letter-spacing:.08em;text-transform:uppercase;text-decoration:none;color:var(--muted)}
35921
+ main{max-width:44rem;margin:0 auto;padding:34px 20px 64px}
35922
+ .kicker{font:600 12px/1 ui-sans-serif,system-ui,sans-serif;letter-spacing:.1em;text-transform:uppercase;color:var(--accent)}
35923
+ h1{font-size:2.1rem;line-height:1.18;margin:12px 0 10px}
35924
+ .summary{color:var(--muted);font-size:1.06rem;margin:0 0 18px}
35925
+ .meta{font:12px/1 ui-sans-serif,system-ui,sans-serif;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:11px 0;margin-bottom:26px}
35926
+ .article-jumps{display:flex;flex-wrap:wrap;gap:10px;margin:0 0 26px}
35927
+ .article-jumps a{font:13px/1 ui-sans-serif,system-ui,sans-serif;color:var(--muted);text-decoration:none;border:1px solid var(--rule);border-radius:999px;padding:6px 11px}
35928
+ article h2{font-size:1.4rem;margin:32px 0 10px}
35929
+ article h3{font-size:1.15rem;margin:24px 0 8px}
35930
+ article p{margin:0 0 17px}
35931
+ .neighbours{display:grid;gap:12px;margin-top:44px;padding-top:22px;border-top:1px solid var(--rule)}
35932
+ .neighbour{display:block;text-decoration:none;border:1px solid var(--rule);border-radius:10px;padding:13px 15px;background:#fff}
35933
+ .neighbour span{display:block;font:11px/1 ui-sans-serif,system-ui,sans-serif;letter-spacing:.09em;text-transform:uppercase;color:var(--muted);margin-bottom:5px}
35934
+ footer{border-top:1px solid var(--rule);padding:20px;text-align:center;color:var(--muted);font:13px/1.5 ui-sans-serif,system-ui,sans-serif}
35935
+ @media (prefers-color-scheme:dark){:root{--ink:#eef1f5;--muted:#9aa4b1;--rule:#2b323b;--bg:#12151a}.neighbour{background:#171b21}}
35936
+ </style>
35937
+ </head>
35938
+ <body>
35939
+ <header class="masthead"><a href="${escapeHtml6(input.origin)}">${escapeHtml6(input.publicationTitle)}</a></header>
35940
+ <main>
35941
+ <p class="kicker">${escapeHtml6(article.kicker || article.category)}</p>
35942
+ <h1>${escapeHtml6(article.title)}</h1>
35943
+ <p class="summary">${escapeHtml6(article.summary)}</p>
35944
+ <p class="meta">${escapeHtml6(article.category)} \xB7 ${article.wordCount} words \xB7 ${article.readingMinutes} min \xB7 <a href="${escapeHtml6(input.editionUrl)}">${escapeHtml6(site.title)}</a></p>
35945
+ ${jumps}
35946
+ <article>${article.html}</article>
35947
+ <div class="neighbours">${neighbour(previous, "Previous")}${neighbour(next, "Next")}</div>
35948
+ </main>
35949
+ <footer>${escapeHtml6(input.publicationTitle)} \xB7 <a href="${escapeHtml6(input.editionUrl)}">All articles in ${escapeHtml6(site.title)}</a></footer>
35950
+ </body>
35951
+ </html>`;
35952
+ return { html, article, canonicalUrl };
35953
+ }
35954
+
35955
+ // src/api/commons-publication-repository.ts
35704
35956
  var PUBLICATION_ROOT_DOMAIN = process.env.COMMONS_PUBLICATION_ROOT_DOMAIN || "transparent-commons.cc";
35705
35957
  var RESERVED_SUBDOMAINS = /* @__PURE__ */ new Set([
35706
35958
  "admin",
@@ -35917,6 +36169,92 @@ async function publishCommonsEditorial(input, user) {
35917
36169
  if (!edition) throw new CommonsPublicationError("publication_publish_failed", "The published edition was not persisted.");
35918
36170
  return publicationResult({ ...publication, latestEditionId: editionId, updatedAt: now }, edition, false);
35919
36171
  }
36172
+ async function updateCommonsEditorialArticle(input, user) {
36173
+ await ensureCommonsSchema();
36174
+ const subdomain = normalizePublicationSubdomain(input.publicationSubdomain);
36175
+ const publication = await getCommonsPublicationBySubdomain(subdomain);
36176
+ if (!publication) throw new CommonsPublicationError("publication_not_found", "Claim this publication name before editing an edition.", 404);
36177
+ if (publication.ownerUserId !== Number(user.id)) {
36178
+ throw new CommonsPublicationError("publication_not_owned", "Only the account that claimed this publication can edit it.", 404);
36179
+ }
36180
+ const idempotencyKey3 = requiredIdempotencyKey(input.idempotencyKey);
36181
+ const replay = await getEditionByIdempotency(Number(user.id), idempotencyKey3);
36182
+ if (replay) return publicationResult(publication, replay, true);
36183
+ const latestOverall = publication.latestEditionId ? await getPublicationEditionById(publication.latestEditionId) : null;
36184
+ const editionSlug = normalizeEditionSlug(input.editionSlug || latestOverall?.editionSlug || "");
36185
+ if (!editionSlug) throw new CommonsPublicationError("publication_edition_required", "This publication has no edition yet; publish one before editing an article.", 409);
36186
+ const latest = await getLatestEdition(publication.id, editionSlug);
36187
+ if (!latest) throw new CommonsPublicationError("publication_edition_not_found", `Edition ${editionSlug} does not exist.`, 404);
36188
+ if (input.baseRevision !== latest.revision) {
36189
+ throw new CommonsPublicationError("publication_revision_conflict", `Edition ${editionSlug} is revision ${latest.revision}; read it again before editing.`, 409);
36190
+ }
36191
+ const articles = latest.articles;
36192
+ const index = articles.findIndex((article) => article.slug === input.articleSlug);
36193
+ if (index === -1) {
36194
+ throw new CommonsPublicationError("publication_article_not_found", `Edition ${editionSlug} has no article with slug ${input.articleSlug}. Known slugs: ${articles.map((article) => article.slug).join(", ")}.`, 404);
36195
+ }
36196
+ const current = articles[index];
36197
+ const nextArticles = [...articles];
36198
+ nextArticles[index] = {
36199
+ ...current,
36200
+ ...input.markdown === void 0 ? {} : { markdown: input.markdown },
36201
+ ...input.title === void 0 ? {} : { title: input.title },
36202
+ ...input.summary === void 0 ? {} : { summary: input.summary },
36203
+ ...input.category === void 0 ? {} : { category: input.category },
36204
+ ...input.kicker === void 0 ? {} : { kicker: input.kicker },
36205
+ ...input.order === void 0 ? {} : { order: input.order }
36206
+ };
36207
+ const editionInput = { site: latest.site, deck: latest.deck, articles: nextArticles };
36208
+ const canonicalUrl = editionPublicUrl(subdomain, editionSlug);
36209
+ const rendered = renderEditorialReadingRoom(editionInput);
36210
+ const html = addPublicMetadata(rendered.html, canonicalUrl, publication.title);
36211
+ const editionId = `tced_${randomUUID18()}`;
36212
+ const revision = latest.revision + 1;
36213
+ const now = (/* @__PURE__ */ new Date()).toISOString();
36214
+ await getDb().batch([
36215
+ {
36216
+ sql: `
36217
+ INSERT INTO commons_publication_editions (
36218
+ id, publication_id, owner_user_id, edition_slug, revision, title, site_json, deck,
36219
+ articles_json, html, filename, sha256, article_count, word_count, bytes, warnings_json,
36220
+ idempotency_key, created_at, published_at
36221
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
36222
+ `,
36223
+ args: [
36224
+ editionId,
36225
+ publication.id,
36226
+ Number(user.id),
36227
+ editionSlug,
36228
+ revision,
36229
+ latest.site.title,
36230
+ JSON.stringify(latest.site),
36231
+ latest.deck,
36232
+ JSON.stringify(nextArticles),
36233
+ html,
36234
+ rendered.filename,
36235
+ createHash16("sha256").update(html).digest("hex"),
36236
+ rendered.articleCount,
36237
+ rendered.wordCount,
36238
+ Buffer.byteLength(html),
36239
+ JSON.stringify(rendered.warnings),
36240
+ idempotencyKey3,
36241
+ now,
36242
+ now
36243
+ ]
36244
+ },
36245
+ {
36246
+ sql: "UPDATE commons_publications SET latest_edition_id = ?, updated_at = ? WHERE id = ? AND owner_user_id = ?",
36247
+ args: [editionId, now, publication.id, Number(user.id)]
36248
+ }
36249
+ ], "write");
36250
+ const edition = await getPublicationEditionById(editionId);
36251
+ if (!edition) throw new CommonsPublicationError("publication_publish_failed", "The edited edition was not persisted.");
36252
+ return {
36253
+ ...publicationResult({ ...publication, latestEditionId: editionId, updatedAt: now }, edition, false),
36254
+ updatedArticle: { slug: input.articleSlug, previousRevision: latest.revision, revision },
36255
+ unchangedArticles: articles.length - 1
36256
+ };
36257
+ }
35920
36258
  async function getCommonsPublicationBySubdomain(subdomainInput) {
35921
36259
  await ensureCommonsSchema();
35922
36260
  const subdomain = normalizePublicationSubdomain(subdomainInput);
@@ -35945,6 +36283,20 @@ async function listCommonsPublicationEditions(publicationId) {
35945
36283
  if (!publication) return [];
35946
36284
  return result.rows.map((row) => rowToEdition(row, publication.subdomain));
35947
36285
  }
36286
+ async function getCommonsPublicationArticleHtml(subdomainInput, articleSlug, editionSlugInput) {
36287
+ const found = await getCommonsPublicationEditionHtml(subdomainInput, editionSlugInput);
36288
+ if (!found) return null;
36289
+ const { publication, edition } = found;
36290
+ const page = renderEditorialArticlePage({
36291
+ edition: { site: edition.site, deck: edition.deck, articles: edition.articles },
36292
+ articleSlug,
36293
+ origin: publicationPublicUrl(publication.subdomain),
36294
+ editionUrl: editionPublicUrl(publication.subdomain, edition.editionSlug),
36295
+ publicationTitle: publication.title
36296
+ });
36297
+ if (!page) return null;
36298
+ return { publication, edition, html: page.html, canonicalUrl: page.canonicalUrl };
36299
+ }
35948
36300
  async function getCommonsPublicationEditionHtml(subdomainInput, editionSlugInput) {
35949
36301
  const publication = await getCommonsPublicationBySubdomain(subdomainInput);
35950
36302
  if (!publication) return null;
@@ -36014,6 +36366,7 @@ function rowToEdition(row, subdomain) {
36014
36366
  revision: Number(row.revision),
36015
36367
  title: String(row.title),
36016
36368
  site: parseJson4(row.site_json, {}),
36369
+ articles: parseJson4(row.articles_json, []),
36017
36370
  deck: String(row.deck),
36018
36371
  filename: String(row.filename),
36019
36372
  sha256: String(row.sha256),
@@ -36089,6 +36442,7 @@ function addPublicMetadata(html, canonicalUrl, publicationTitle) {
36089
36442
  var commonsApp = new Hono31();
36090
36443
  var auth2 = createApiKeyAuth();
36091
36444
  var SearchBodySchema = z32.object({
36445
+ mode: z32.enum(["lexical", "semantic", "hybrid"]).optional(),
36092
36446
  query: z32.string().max(300).optional(),
36093
36447
  entityType: z32.string().max(120).optional(),
36094
36448
  tag: z32.string().max(80).optional(),
@@ -36251,6 +36605,15 @@ var PreparePublicationSchema = z32.object(CommonsPreparePublicationInputSchema).
36251
36605
  var ValidatePublicationSchema = z32.object(CommonsValidatePublicationInputSchema).strict();
36252
36606
  var ClaimPublicationSchema = z32.object(CommonsClaimPublicationInputSchema).strict();
36253
36607
  var PublishEditorialSchema = z32.object(CommonsPublishEditorialInputSchema).strict();
36608
+ var UpdateEditorialArticleSchema = z32.object(CommonsUpdateEditorialArticleInputSchema).strict();
36609
+ commonsApp.post("/index/embed", auth2, async (c) => {
36610
+ const body = await c.req.json().catch(() => ({}));
36611
+ const result = await embedQueuedCommonsDocuments(Number(body.limit) || 50);
36612
+ return c.json({ ok: true, data: result });
36613
+ });
36614
+ commonsApp.get("/index/status", auth2, async (c) => {
36615
+ return c.json({ ok: true, data: { queued: await queuedCommonsDocumentCount(), semanticSearchConfigured: commonsSemanticSearchConfigured() } });
36616
+ });
36254
36617
  commonsApp.get("/health", async (c) => {
36255
36618
  await ensureCommonsSchema();
36256
36619
  return c.json({ ok: true, data: commonsDatabaseReport() });
@@ -36286,11 +36649,16 @@ commonsApp.post("/publications/publish", auth2, async (c) => {
36286
36649
  if (!parsed.success) return validationError(c, parsed.error);
36287
36650
  return publicationOperation(c, () => publishCommonsEditorial(parsed.data, c.get("user")), 201);
36288
36651
  });
36652
+ commonsApp.post("/publications/articles", auth2, async (c) => {
36653
+ const parsed = UpdateEditorialArticleSchema.safeParse(await c.req.json().catch(() => ({})));
36654
+ if (!parsed.success) return validationError(c, parsed.error);
36655
+ return publicationOperation(c, () => updateCommonsEditorialArticle(parsed.data, c.get("user")), 201);
36656
+ });
36289
36657
  commonsApp.get("/publications/me", auth2, async (c) => {
36290
36658
  const publication = await getCommonsPublicationForOwner(Number(c.get("user").id));
36291
36659
  if (!publication) return c.json({ ok: false, error: "publication_not_found", message: "This account has not claimed a Commons publication yet." }, 404);
36292
36660
  const editions = c.req.query("includeEditions") === "false" ? [] : await listCommonsPublicationEditions(publication.id);
36293
- return c.json({ ok: true, data: { publication, editions } });
36661
+ return c.json({ ok: true, data: { publication, editions: withArticleSources(editions, c.req.query("includeArticles") === "true") } });
36294
36662
  });
36295
36663
  commonsApp.get("/publications/:subdomain/site", async (c) => {
36296
36664
  try {
@@ -36304,6 +36672,28 @@ commonsApp.get("/publications/:subdomain/site", async (c) => {
36304
36672
  return publicationError(c, error);
36305
36673
  }
36306
36674
  });
36675
+ commonsApp.get("/publications/:subdomain/articles/:articleSlug/site", async (c) => {
36676
+ try {
36677
+ const result = await getCommonsPublicationArticleHtml(c.req.param("subdomain"), c.req.param("articleSlug"));
36678
+ if (!result) return c.json({ ok: false, error: "article_not_found", message: "No published article matched that publication and slug." }, 404);
36679
+ return c.html(result.html, 200, {
36680
+ "cache-control": "public, max-age=60, s-maxage=300",
36681
+ "x-robots-tag": "index, follow",
36682
+ link: `<${result.canonicalUrl}>; rel="canonical"`
36683
+ });
36684
+ } catch (error) {
36685
+ return publicationError(c, error);
36686
+ }
36687
+ });
36688
+ commonsApp.get("/publications/:subdomain/editions/:editionSlug/articles/:articleSlug/site", async (c) => {
36689
+ try {
36690
+ const result = await getCommonsPublicationArticleHtml(c.req.param("subdomain"), c.req.param("articleSlug"), c.req.param("editionSlug"));
36691
+ if (!result) return c.json({ ok: false, error: "article_not_found", message: "No published article matched that publication, edition, and slug." }, 404);
36692
+ return c.html(result.html, 200, { "cache-control": "public, max-age=60, s-maxage=300", "x-robots-tag": "index, follow" });
36693
+ } catch (error) {
36694
+ return publicationError(c, error);
36695
+ }
36696
+ });
36307
36697
  commonsApp.get("/publications/:subdomain/editions/:editionSlug/site", async (c) => {
36308
36698
  try {
36309
36699
  const result = await getCommonsPublicationEditionHtml(c.req.param("subdomain"), c.req.param("editionSlug"));
@@ -36330,7 +36720,7 @@ commonsApp.get("/publications/:subdomain", async (c) => {
36330
36720
  const publication = await getCommonsPublicationBySubdomain(c.req.param("subdomain"));
36331
36721
  if (!publication) return c.json({ ok: false, error: "publication_not_found", message: "No Commons publication matched that name." }, 404);
36332
36722
  const editions = c.req.query("includeEditions") === "false" ? [] : await listCommonsPublicationEditions(publication.id);
36333
- return c.json({ ok: true, data: { publication, editions } });
36723
+ return c.json({ ok: true, data: { publication, editions: withArticleSources(editions, false) } });
36334
36724
  } catch (error) {
36335
36725
  return publicationError(c, error);
36336
36726
  }
@@ -36506,6 +36896,7 @@ ${urls.join("\n")}
36506
36896
  });
36507
36897
  function filtersFromQuery(query) {
36508
36898
  return {
36899
+ mode: query.mode === "lexical" || query.mode === "semantic" ? query.mode : void 0,
36509
36900
  query: query.query || query.q,
36510
36901
  entityType: query.entityType,
36511
36902
  tag: query.tag,
@@ -36561,6 +36952,13 @@ function publicationError(c, error) {
36561
36952
  }
36562
36953
  throw error;
36563
36954
  }
36955
+ function withArticleSources(editions, include) {
36956
+ if (include) return editions;
36957
+ return editions.map((edition) => {
36958
+ const { articles: _articles, ...rest } = edition;
36959
+ return rest;
36960
+ });
36961
+ }
36564
36962
  function xmlEscape(value) {
36565
36963
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
36566
36964
  }
@@ -37148,7 +37546,7 @@ function pixelSnippet(publicId) {
37148
37546
  function formSnippet(publicId) {
37149
37547
  return `<div data-mcp-form="${publicId}"></div><script async src="https://mcpscraper.dev/analytics/v1/form.js?form=${publicId}"></script>`;
37150
37548
  }
37151
- function escapeHtml6(value) {
37549
+ function escapeHtml7(value) {
37152
37550
  return String(value ?? "").replace(
37153
37551
  /[&<>"']/g,
37154
37552
  (character) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[character]
@@ -37160,13 +37558,13 @@ function renderPublicForm(form, placementUrl) {
37160
37558
  const fields = form.fields.map((field) => {
37161
37559
  const required = field.required ? " required" : "";
37162
37560
  const options = (field.options ?? []).map(
37163
- (option) => `<option value="${escapeHtml6(option)}">${escapeHtml6(option)}</option>`
37561
+ (option) => `<option value="${escapeHtml7(option)}">${escapeHtml7(option)}</option>`
37164
37562
  ).join("");
37165
- const control = field.type === "textarea" ? `<textarea id="${escapeHtml6(field.id)}" name="${escapeHtml6(field.id)}"${required}></textarea>` : field.type === "select" ? `<select id="${escapeHtml6(field.id)}" name="${escapeHtml6(field.id)}"${required}><option value="">Choose\u2026</option>${options}</select>` : field.type === "checkbox" ? `<input id="${escapeHtml6(field.id)}" name="${escapeHtml6(field.id)}" type="checkbox" value="true"${required}>` : `<input id="${escapeHtml6(field.id)}" name="${escapeHtml6(field.id)}" type="${escapeHtml6(field.type)}"${required}>`;
37166
- return `<label${field.type === "checkbox" ? ' class="check"' : ""}><span>${escapeHtml6(field.label)}${field.required ? " *" : ""}</span>${control}</label>`;
37563
+ const control = field.type === "textarea" ? `<textarea id="${escapeHtml7(field.id)}" name="${escapeHtml7(field.id)}"${required}></textarea>` : field.type === "select" ? `<select id="${escapeHtml7(field.id)}" name="${escapeHtml7(field.id)}"${required}><option value="">Choose\u2026</option>${options}</select>` : field.type === "checkbox" ? `<input id="${escapeHtml7(field.id)}" name="${escapeHtml7(field.id)}" type="checkbox" value="true"${required}>` : `<input id="${escapeHtml7(field.id)}" name="${escapeHtml7(field.id)}" type="${escapeHtml7(field.type)}"${required}>`;
37564
+ return `<label${field.type === "checkbox" ? ' class="check"' : ""}><span>${escapeHtml7(field.label)}${field.required ? " *" : ""}</span>${control}</label>`;
37167
37565
  }).join("");
37168
37566
  const brand = form.brand;
37169
- return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style>:root{font-family:ui-sans-serif,system-ui;color:${escapeHtml6(brand.textColor)};background:${escapeHtml6(brand.backgroundColor)}}*{box-sizing:border-box}body{margin:0;padding:18px}form{display:grid;gap:14px}label{display:grid;gap:6px;font-size:13px;font-weight:650}.check{grid-template-columns:auto 1fr;align-items:center}.check span{grid-column:2}.check input{grid-column:1;grid-row:1}input,textarea,select{width:100%;min-height:44px;padding:10px 12px;border:1px solid #ccd3df;border-radius:${brand.radius}px;background:white;color:inherit;font:inherit}textarea{min-height:110px;resize:vertical}button{min-height:46px;border:0;border-radius:${brand.radius}px;color:white;background:${escapeHtml6(brand.primaryColor)};font:inherit;font-weight:750;cursor:pointer}.consent{margin:0;color:#667085;font-size:11px;line-height:1.45}.notice{display:none;padding:12px;border-radius:${brand.radius}px;background:#edf8f2;color:#17613c}.hp{position:absolute!important;left:-9999px!important}</style></head><body><form id="mcp-form">${fields}<label class="hp">Website<input name="website" autocomplete="off" tabindex="-1"></label>${form.consent_text ? `<p class="consent">${escapeHtml6(form.consent_text)}</p>` : ""}<button>${escapeHtml6(form.submit_label)}</button><div class="notice" role="status"></div></form><script>(()=>{const form=document.querySelector('#mcp-form'),notice=form.querySelector('.notice'),q=new URLSearchParams(location.search);form.addEventListener('submit',async event=>{event.preventDefault();const button=form.querySelector('button');button.disabled=true;const raw=Object.fromEntries(new FormData(form).entries()),website=String(raw.website||''),clickIds={};delete raw.website;for(const k of ['fbclid','gclid','gbraid','wbraid','ttclid','rdt_cid','msclkid']){const v=q.get(k);if(v)clickIds[k]=v}try{const response=await fetch('/analytics/forms/${escapeHtml6(form.public_id)}/submissions',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({data:raw,website,placementUrl:${JSON.stringify(placementUrl)},visitorId:q.get('visitor')||undefined,sessionId:q.get('session')||undefined,source:q.get('source')||undefined,medium:q.get('medium')||undefined,campaign:q.get('campaign')||undefined,clickIds})});if(!response.ok)throw new Error('submit');notice.textContent=${JSON.stringify(form.success_message)};notice.style.display='block';form.reset();${form.redirect_url ? `setTimeout(()=>{top.location.href=${JSON.stringify(form.redirect_url)}},700);` : ""}}catch{notice.textContent='Your response could not be submitted. Please try again.';notice.style.display='block'}finally{button.disabled=false}})})()</script></body></html>`;
37567
+ return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style>:root{font-family:ui-sans-serif,system-ui;color:${escapeHtml7(brand.textColor)};background:${escapeHtml7(brand.backgroundColor)}}*{box-sizing:border-box}body{margin:0;padding:18px}form{display:grid;gap:14px}label{display:grid;gap:6px;font-size:13px;font-weight:650}.check{grid-template-columns:auto 1fr;align-items:center}.check span{grid-column:2}.check input{grid-column:1;grid-row:1}input,textarea,select{width:100%;min-height:44px;padding:10px 12px;border:1px solid #ccd3df;border-radius:${brand.radius}px;background:white;color:inherit;font:inherit}textarea{min-height:110px;resize:vertical}button{min-height:46px;border:0;border-radius:${brand.radius}px;color:white;background:${escapeHtml7(brand.primaryColor)};font:inherit;font-weight:750;cursor:pointer}.consent{margin:0;color:#667085;font-size:11px;line-height:1.45}.notice{display:none;padding:12px;border-radius:${brand.radius}px;background:#edf8f2;color:#17613c}.hp{position:absolute!important;left:-9999px!important}</style></head><body><form id="mcp-form">${fields}<label class="hp">Website<input name="website" autocomplete="off" tabindex="-1"></label>${form.consent_text ? `<p class="consent">${escapeHtml7(form.consent_text)}</p>` : ""}<button>${escapeHtml7(form.submit_label)}</button><div class="notice" role="status"></div></form><script>(()=>{const form=document.querySelector('#mcp-form'),notice=form.querySelector('.notice'),q=new URLSearchParams(location.search);form.addEventListener('submit',async event=>{event.preventDefault();const button=form.querySelector('button');button.disabled=true;const raw=Object.fromEntries(new FormData(form).entries()),website=String(raw.website||''),clickIds={};delete raw.website;for(const k of ['fbclid','gclid','gbraid','wbraid','ttclid','rdt_cid','msclkid']){const v=q.get(k);if(v)clickIds[k]=v}try{const response=await fetch('/analytics/forms/${escapeHtml7(form.public_id)}/submissions',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({data:raw,website,placementUrl:${JSON.stringify(placementUrl)},visitorId:q.get('visitor')||undefined,sessionId:q.get('session')||undefined,source:q.get('source')||undefined,medium:q.get('medium')||undefined,campaign:q.get('campaign')||undefined,clickIds})});if(!response.ok)throw new Error('submit');notice.textContent=${JSON.stringify(form.success_message)};notice.style.display='block';form.reset();${form.redirect_url ? `setTimeout(()=>{top.location.href=${JSON.stringify(form.redirect_url)}},700);` : ""}}catch{notice.textContent='Your response could not be submitted. Please try again.';notice.style.display='block'}finally{button.disabled=false}})})()</script></body></html>`;
37170
37568
  }
37171
37569
  analyticsApp.get(
37172
37570
  "/health/live",
@@ -38422,7 +38820,7 @@ async function revokeScheduledRunViewLink(ownerId, runId, shareId, now = /* @__P
38422
38820
 
38423
38821
  // src/personal-authority/render.ts
38424
38822
  import { createHash as createHash21 } from "crypto";
38425
- function escapeHtml7(value) {
38823
+ function escapeHtml8(value) {
38426
38824
  return value.replace(/[&<>"']/g, (character) => ({
38427
38825
  "&": "&amp;",
38428
38826
  "<": "&lt;",
@@ -38433,13 +38831,13 @@ function escapeHtml7(value) {
38433
38831
  }
38434
38832
  function safeHref(value) {
38435
38833
  const trimmed = value.trim();
38436
- return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ? escapeHtml7(trimmed) : "#";
38834
+ return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ? escapeHtml8(trimmed) : "#";
38437
38835
  }
38438
38836
  function initials(name) {
38439
38837
  return name.split(/\s+/).filter(Boolean).slice(0, 2).map((part) => part[0]?.toUpperCase()).join("") || "PA";
38440
38838
  }
38441
38839
  function action(action3, secondary = false) {
38442
- return `<a class="button${secondary ? " button--secondary" : ""}" href="${safeHref(action3.href)}">${escapeHtml7(action3.label)} <span aria-hidden="true">\u2197</span></a>`;
38840
+ return `<a class="button${secondary ? " button--secondary" : ""}" href="${safeHref(action3.href)}">${escapeHtml8(action3.label)} <span aria-hidden="true">\u2197</span></a>`;
38443
38841
  }
38444
38842
  function section(enabled, html) {
38445
38843
  return enabled ? html : "";
@@ -38448,7 +38846,7 @@ function renderPersonalAuthorityV1(input, config, generatedAt) {
38448
38846
  const flags = config.featureFlags;
38449
38847
  const brand = config.brandName || input.name;
38450
38848
  const generatedAtIso = generatedAt.toISOString();
38451
- const social = flags.socialLinks && input.socialLinks.length > 0 ? `<nav class="social" aria-label="Professional profiles">${input.socialLinks.map((link) => `<a href="${safeHref(link.href)}">${escapeHtml7(link.label)}</a>`).join("")}</nav>` : "";
38849
+ const social = flags.socialLinks && input.socialLinks.length > 0 ? `<nav class="social" aria-label="Professional profiles">${input.socialLinks.map((link) => `<a href="${safeHref(link.href)}">${escapeHtml8(link.label)}</a>`).join("")}</nav>` : "";
38452
38850
  const navigation = flags.navigation ? `<button class="menu" type="button" aria-expanded="false" aria-controls="nav">Menu</button><nav id="nav" class="nav" aria-label="Primary navigation"><a href="#about">About</a><a href="#services">Work</a><a href="#proof">Proof</a><a href="#contact">Contact</a></nav>` : "";
38453
38851
  const authority = input.authority;
38454
38852
  const consultation = input.consultation;
@@ -38460,21 +38858,21 @@ function renderPersonalAuthorityV1(input, config, generatedAt) {
38460
38858
  <html lang="en" data-theme="${config.theme}">
38461
38859
  <head>
38462
38860
  <meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
38463
- <meta name="description" content="${escapeHtml7(input.summary)}"><title>${escapeHtml7(input.name)} \u2014 ${escapeHtml7(input.professionalTitle)}</title>
38861
+ <meta name="description" content="${escapeHtml8(input.summary)}"><title>${escapeHtml8(input.name)} \u2014 ${escapeHtml8(input.professionalTitle)}</title>
38464
38862
  <style>
38465
38863
  :root{--blue:#2f66eb;--blue-soft:#dbe6ff;--ink:#050708;--paper:#f7f8fb;--white:#fff;--gray:#9ca5b5;--line:#27303b;--serif:Georgia,'Times New Roman',serif;--sans:Arial,Helvetica,sans-serif}*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--ink);color:var(--white);font-family:var(--sans);line-height:1.55}a{color:inherit}.skip{position:absolute;left:-9999px}.skip:focus{left:16px;top:16px;z-index:9;background:#fff;color:#000;padding:10px}.header{height:88px;display:flex;align-items:center;justify-content:space-between;padding:0 clamp(20px,4vw,72px);border-bottom:1px solid var(--line);position:relative;z-index:3;background:rgba(5,7,8,.96)}.brand{display:flex;align-items:center;gap:12px;text-decoration:none;font-family:var(--serif);font-size:24px}.mark{width:40px;height:40px;border-radius:50%;display:grid;place-items:center;background:var(--blue);font-family:var(--sans);font-weight:700}.nav{display:flex;align-items:center;gap:28px}.nav a{text-decoration:none;color:#c8ced8;font-size:14px}.nav a:hover{color:#fff}.menu{display:none;background:transparent;color:#fff;border:1px solid #5b6471;padding:10px 14px}.hero{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.25fr);min-height:760px;border-bottom:3px solid var(--blue)}.portrait{display:grid;place-items:end center;background:radial-gradient(circle at 50% 38%,#273243 0,#11161d 38%,#060708 70%);overflow:hidden}.portrait-card{width:min(82%,560px);aspect-ratio:4/5;display:grid;place-items:center;align-self:end;border:1px solid #263142;border-bottom:0;background:linear-gradient(145deg,#252d38,#0b0d10 58%);font-family:var(--serif);font-size:clamp(80px,13vw,180px);color:#d9e4ff;text-shadow:0 0 42px rgba(47,102,235,.5)}.hero-copy{padding:clamp(44px,7vw,110px) clamp(24px,6vw,100px);display:flex;flex-direction:column;justify-content:center;background:linear-gradient(135deg,#080a0d,#101318)}h1,h2,h3,p{margin-top:0}.hero h1{font-family:var(--serif);font-size:clamp(58px,8vw,116px);line-height:.92;font-weight:400;color:var(--blue);margin-bottom:24px}.role{font-family:var(--serif);font-size:clamp(28px,3.8vw,52px);line-height:1.05;border-left:5px solid var(--blue);padding-left:22px;max-width:820px}.summary{color:#c6cbd3;font-size:clamp(17px,1.5vw,22px);max-width:760px}.actions{display:flex;gap:12px;flex-wrap:wrap;margin:24px 0}.button{display:inline-flex;align-items:center;justify-content:space-between;gap:28px;min-height:58px;padding:0 26px;background:var(--blue);border:1px solid var(--blue);text-decoration:none;font-weight:700}.button--secondary{background:transparent;border-color:#5c6572}.social{display:flex;gap:10px;flex-wrap:wrap}.social a{border:1px solid #39414d;border-radius:999px;padding:8px 13px;text-decoration:none;color:#d8dce4;font-size:13px}.light{background:var(--paper);color:#111722;padding:clamp(70px,10vw,150px) clamp(20px,6vw,90px)}.light h2,.section h2{font-family:var(--serif);font-size:clamp(42px,6vw,82px);line-height:1.02;font-weight:400;max-width:1080px}.light p{max-width:920px;color:#4e596a;font-size:18px}.section{padding:clamp(70px,9vw,130px) clamp(20px,6vw,90px);border-bottom:1px solid var(--line)}.section-head{max-width:920px;margin-bottom:46px}.eyebrow{text-transform:uppercase;letter-spacing:.18em;font-size:12px;color:#aab2bf}.consult{display:grid;grid-template-columns:1.3fr .7fr;gap:50px;background:linear-gradient(130deg,#060708,#111721)}.accent-card{min-height:360px;border:1px solid #2a3545;background:linear-gradient(145deg,rgba(47,102,235,.22),transparent 55%);display:grid;place-items:center;font-family:var(--serif);font-size:96px;color:var(--blue)}.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}.card{border:1px solid #323a46;padding:26px;min-height:220px;background:#0b0e12}.card h3{font-family:var(--serif);font-size:30px}.card p{color:#b9c0ca}.learning{background:#020303}.topic-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1px;background:#29313c;border:1px solid #29313c}.topic{background:#050708;padding:30px}.topic strong{display:block;color:var(--blue);text-transform:uppercase;font-size:11px;letter-spacing:.15em}.topic h3{font-family:var(--serif);font-size:30px;margin:8px 0}.topic p{color:#aeb6c1}.proof{background:linear-gradient(180deg,#0a0d11,#050607)}.quotes{display:flex;gap:14px;overflow:auto;scroll-snap-type:x mandatory;padding-bottom:12px}.quote{min-width:min(420px,86vw);scroll-snap-align:start;border:1px solid #343d49;padding:30px;background:#0c1015}.quote q{font-family:var(--serif);font-size:30px;line-height:1.25}.quote span{display:block;margin-top:24px;color:#aeb5c0;font-size:12px;text-transform:uppercase;letter-spacing:.12em}.cta{text-align:center;border-top:3px solid var(--blue);background:radial-gradient(circle at 50% 0,rgba(47,102,235,.25),transparent 50%)}.cta h2{margin-left:auto;margin-right:auto}.footer{display:grid;grid-template-columns:1fr auto;gap:40px;padding:46px clamp(20px,6vw,90px);color:#abb3bf}.footer strong{color:#fff;font-family:var(--serif);font-size:26px}.generated{font-size:11px;color:#737d8b;margin-top:10px}html[data-theme='slate']{--blue:#7f95b8;--blue-soft:#dfe6ef}html[data-theme='monochrome']{--blue:#fff;--blue-soft:#e7e7e7}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)}
38466
38864
  @media(max-width:760px){.header{height:78px}.menu{display:block}.nav{display:none;position:absolute;left:0;right:0;top:77px;padding:18px 20px;background:#090b0e;border-bottom:1px solid #303844;flex-direction:column;align-items:stretch}.nav.open{display:flex}.hero{grid-template-columns:1fr;min-height:0}.portrait{min-height:390px}.portrait-card{width:72%;max-height:360px}.hero-copy{padding:48px 20px 66px}.hero h1{font-size:64px}.role{font-size:34px}.actions{display:grid}.button{width:100%}.consult{grid-template-columns:1fr}.accent-card{min-height:220px}.grid,.topic-grid{grid-template-columns:1fr}.light,.section{padding:64px 20px}.light h2,.section h2{font-size:46px}.footer{grid-template-columns:1fr}}
38467
38865
  </style></head>
38468
38866
  <body><a class="skip" href="#main">Skip to main content</a>
38469
- <header class="header"><a class="brand" href="#top"><span class="mark">${escapeHtml7(initials(input.name).slice(0, 1))}</span><strong>${escapeHtml7(brand)}</strong></a>${navigation}</header>
38470
- <main id="main"><section class="hero" id="top"><div class="portrait" aria-label="Portrait placeholder"><div class="portrait-card" aria-hidden="true">${escapeHtml7(initials(input.name))}</div></div><div class="hero-copy"><h1>${escapeHtml7(input.name)}</h1><p class="role">${escapeHtml7(input.professionalTitle)}</p><p class="summary">${escapeHtml7(input.summary)}</p><div class="actions">${action(input.primaryAction)}${input.secondaryAction ? action(input.secondaryAction, true) : ""}</div>${social}</div></section>
38471
- ${section(flags.authority && Boolean(authority), `<section class="light" id="about"><h2>${escapeHtml7(authority?.heading ?? "")}</h2>${authority?.paragraphs.map((paragraph) => `<p>${escapeHtml7(paragraph)}</p>`).join("") ?? ""}</section>`)}
38472
- ${section(flags.consultation && Boolean(consultation), `<section class="section consult"><div><p class="eyebrow">${escapeHtml7(consultation?.eyebrow ?? "Start a conversation")}</p><h2>${escapeHtml7(consultation?.heading ?? "")}</h2><p class="summary">${escapeHtml7(consultation?.summary ?? "")}</p>${consultation ? action(consultation.action) : ""}</div><div class="accent-card" aria-label="Image placeholder">${escapeHtml7(initials(input.name))}</div></section>`)}
38473
- ${section(flags.learning && Boolean(learning), `<section class="section learning"><div class="section-head"><h2>${escapeHtml7(learning?.heading ?? "")}</h2><p class="summary">${escapeHtml7(learning?.summary ?? "")}</p></div><div class="topic-grid">${learning?.topics.map((topic) => `<article class="topic"><strong>${escapeHtml7(topic.title)}</strong><h3>${escapeHtml7(topic.headline)}</h3><p>${escapeHtml7(topic.summary)}</p>${topic.href ? `<a href="${safeHref(topic.href)}">Explore \u2192</a>` : ""}</article>`).join("") ?? ""}</div></section>`)}
38474
- ${section(flags.services && Boolean(services), `<section class="section" id="services"><div class="section-head"><h2>${escapeHtml7(services?.heading ?? "")}</h2><p class="summary">${escapeHtml7(services?.summary ?? "")}</p></div><div class="grid">${services?.offers.map((offer) => `<article class="card"><h3>${escapeHtml7(offer.title)}</h3><p>${escapeHtml7(offer.description)}</p>${offer.action ? action(offer.action, true) : ""}</article>`).join("") ?? ""}</div></section>`)}
38475
- ${section(flags.proof && Boolean(proof), `<section class="section proof" id="proof"><div class="section-head"><h2>${escapeHtml7(proof?.heading ?? "")}</h2><p class="summary">${escapeHtml7(proof?.summary ?? "")}</p></div><div class="quotes">${proof?.testimonials.map((item) => `<article class="quote"><q>${escapeHtml7(item.quote)}</q><span>${escapeHtml7(item.person)}${item.role ? ` / ${escapeHtml7(item.role)}` : ""}</span></article>`).join("") ?? ""}</div></section>`)}
38476
- ${section(flags.finalCta && Boolean(finalCta), `<section class="section cta" id="contact"><p class="eyebrow">${escapeHtml7(finalCta?.eyebrow ?? "Ready when you are")}</p><h2>${escapeHtml7(finalCta?.heading ?? "")}</h2><p class="summary">${escapeHtml7(finalCta?.summary ?? "")}</p>${finalCta ? action(finalCta.action) : ""}</section>`)}
38477
- </main><footer class="footer"><div><strong>${escapeHtml7(input.name)}</strong><div>${escapeHtml7(input.professionalTitle)}</div>${config.showGeneratedAt ? `<div class="generated">Generated ${escapeHtml7(generatedAtIso)}</div>` : ""}</div><div>${input.location ? `<div>${escapeHtml7(input.location)}</div>` : ""}${input.email ? `<a href="mailto:${escapeHtml7(input.email)}">${escapeHtml7(input.email)}</a>` : ""}${input.phone ? `<div>${escapeHtml7(input.phone)}</div>` : ""}</div></footer>
38867
+ <header class="header"><a class="brand" href="#top"><span class="mark">${escapeHtml8(initials(input.name).slice(0, 1))}</span><strong>${escapeHtml8(brand)}</strong></a>${navigation}</header>
38868
+ <main id="main"><section class="hero" id="top"><div class="portrait" aria-label="Portrait placeholder"><div class="portrait-card" aria-hidden="true">${escapeHtml8(initials(input.name))}</div></div><div class="hero-copy"><h1>${escapeHtml8(input.name)}</h1><p class="role">${escapeHtml8(input.professionalTitle)}</p><p class="summary">${escapeHtml8(input.summary)}</p><div class="actions">${action(input.primaryAction)}${input.secondaryAction ? action(input.secondaryAction, true) : ""}</div>${social}</div></section>
38869
+ ${section(flags.authority && Boolean(authority), `<section class="light" id="about"><h2>${escapeHtml8(authority?.heading ?? "")}</h2>${authority?.paragraphs.map((paragraph) => `<p>${escapeHtml8(paragraph)}</p>`).join("") ?? ""}</section>`)}
38870
+ ${section(flags.consultation && Boolean(consultation), `<section class="section consult"><div><p class="eyebrow">${escapeHtml8(consultation?.eyebrow ?? "Start a conversation")}</p><h2>${escapeHtml8(consultation?.heading ?? "")}</h2><p class="summary">${escapeHtml8(consultation?.summary ?? "")}</p>${consultation ? action(consultation.action) : ""}</div><div class="accent-card" aria-label="Image placeholder">${escapeHtml8(initials(input.name))}</div></section>`)}
38871
+ ${section(flags.learning && Boolean(learning), `<section class="section learning"><div class="section-head"><h2>${escapeHtml8(learning?.heading ?? "")}</h2><p class="summary">${escapeHtml8(learning?.summary ?? "")}</p></div><div class="topic-grid">${learning?.topics.map((topic) => `<article class="topic"><strong>${escapeHtml8(topic.title)}</strong><h3>${escapeHtml8(topic.headline)}</h3><p>${escapeHtml8(topic.summary)}</p>${topic.href ? `<a href="${safeHref(topic.href)}">Explore \u2192</a>` : ""}</article>`).join("") ?? ""}</div></section>`)}
38872
+ ${section(flags.services && Boolean(services), `<section class="section" id="services"><div class="section-head"><h2>${escapeHtml8(services?.heading ?? "")}</h2><p class="summary">${escapeHtml8(services?.summary ?? "")}</p></div><div class="grid">${services?.offers.map((offer) => `<article class="card"><h3>${escapeHtml8(offer.title)}</h3><p>${escapeHtml8(offer.description)}</p>${offer.action ? action(offer.action, true) : ""}</article>`).join("") ?? ""}</div></section>`)}
38873
+ ${section(flags.proof && Boolean(proof), `<section class="section proof" id="proof"><div class="section-head"><h2>${escapeHtml8(proof?.heading ?? "")}</h2><p class="summary">${escapeHtml8(proof?.summary ?? "")}</p></div><div class="quotes">${proof?.testimonials.map((item) => `<article class="quote"><q>${escapeHtml8(item.quote)}</q><span>${escapeHtml8(item.person)}${item.role ? ` / ${escapeHtml8(item.role)}` : ""}</span></article>`).join("") ?? ""}</div></section>`)}
38874
+ ${section(flags.finalCta && Boolean(finalCta), `<section class="section cta" id="contact"><p class="eyebrow">${escapeHtml8(finalCta?.eyebrow ?? "Ready when you are")}</p><h2>${escapeHtml8(finalCta?.heading ?? "")}</h2><p class="summary">${escapeHtml8(finalCta?.summary ?? "")}</p>${finalCta ? action(finalCta.action) : ""}</section>`)}
38875
+ </main><footer class="footer"><div><strong>${escapeHtml8(input.name)}</strong><div>${escapeHtml8(input.professionalTitle)}</div>${config.showGeneratedAt ? `<div class="generated">Generated ${escapeHtml8(generatedAtIso)}</div>` : ""}</div><div>${input.location ? `<div>${escapeHtml8(input.location)}</div>` : ""}${input.email ? `<a href="mailto:${escapeHtml8(input.email)}">${escapeHtml8(input.email)}</a>` : ""}${input.phone ? `<div>${escapeHtml8(input.phone)}</div>` : ""}</div></footer>
38478
38876
  <script>document.querySelector('.menu')?.addEventListener('click',function(){var nav=document.querySelector('.nav');var open=this.getAttribute('aria-expanded')!=='true';this.setAttribute('aria-expanded',String(open));nav?.classList.toggle('open',open)});document.querySelectorAll('.nav a').forEach(function(link){link.addEventListener('click',function(){document.querySelector('.nav')?.classList.remove('open');document.querySelector('.menu')?.setAttribute('aria-expanded','false')})});</script></body></html>`;
38479
38877
  const bytes = Buffer.byteLength(html, "utf8");
38480
38878
  return {
@@ -38493,7 +38891,7 @@ var FONT_STACKS = Object.freeze({
38493
38891
  "modern-sans": "Avenir Next, Avenir, Helvetica Neue, Arial, sans-serif",
38494
38892
  "humanist-sans": "Optima, Candara, Segoe UI, sans-serif"
38495
38893
  });
38496
- function escapeHtml8(value) {
38894
+ function escapeHtml9(value) {
38497
38895
  return value.replace(
38498
38896
  /[&<>"']/g,
38499
38897
  (character) => ({
@@ -38507,13 +38905,13 @@ function escapeHtml8(value) {
38507
38905
  }
38508
38906
  function safeHref2(value) {
38509
38907
  const trimmed = value.trim();
38510
- return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ? escapeHtml8(trimmed) : "#";
38908
+ return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ? escapeHtml9(trimmed) : "#";
38511
38909
  }
38512
38910
  function initials2(name) {
38513
38911
  return name.split(/\s+/).filter(Boolean).slice(0, 2).map((part) => part[0]?.toUpperCase()).join("") || "PA";
38514
38912
  }
38515
38913
  function action2(action3, secondary = false) {
38516
- return `<a class="button${secondary ? " button--secondary" : ""}" href="${safeHref2(action3.href)}">${escapeHtml8(action3.label)} <span aria-hidden="true">\u2197</span></a>`;
38914
+ return `<a class="button${secondary ? " button--secondary" : ""}" href="${safeHref2(action3.href)}">${escapeHtml9(action3.label)} <span aria-hidden="true">\u2197</span></a>`;
38517
38915
  }
38518
38916
  function section2(enabled, html) {
38519
38917
  return enabled ? html : "";
@@ -38557,7 +38955,7 @@ function renderPersonalAuthorityV2(input, config, generatedAt) {
38557
38955
  const surfaceContrast = bestContrastTextColor(colors.surface);
38558
38956
  const accentChannels = hexChannels(colors.accent);
38559
38957
  const generatedAtIso = generatedAt.toISOString();
38560
- const social = flags.socialLinks && input.socialLinks.length > 0 ? `<nav class="social" aria-label="Professional profiles">${input.socialLinks.map((link) => `<a href="${safeHref2(link.href)}">${escapeHtml8(link.label)}</a>`).join("")}</nav>` : "";
38958
+ const social = flags.socialLinks && input.socialLinks.length > 0 ? `<nav class="social" aria-label="Professional profiles">${input.socialLinks.map((link) => `<a href="${safeHref2(link.href)}">${escapeHtml9(link.label)}</a>`).join("")}</nav>` : "";
38561
38959
  const navigation = flags.navigation ? `<button class="menu" type="button" aria-expanded="false" aria-controls="nav">Menu</button><nav id="nav" class="nav" aria-label="Primary navigation"><a href="#about">About</a><a href="#services">Work</a><a href="#proof">Proof</a><a href="#contact">Contact</a></nav>` : "";
38562
38960
  const authority = input.authority;
38563
38961
  const consultation = input.consultation;
@@ -38569,22 +38967,22 @@ function renderPersonalAuthorityV2(input, config, generatedAt) {
38569
38967
  <html lang="en" data-theme="${config.theme}">
38570
38968
  <head>
38571
38969
  <meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
38572
- <meta name="description" content="${escapeHtml8(input.summary)}"><title>${escapeHtml8(input.name)} - ${escapeHtml8(input.professionalTitle)}</title>
38970
+ <meta name="description" content="${escapeHtml9(input.summary)}"><title>${escapeHtml9(input.name)} - ${escapeHtml9(input.professionalTitle)}</title>
38573
38971
  <style>
38574
38972
  :root{--accent:${colors.accent};--accent-rgb:${accentChannels};--accent-contrast:${accentContrast};--background:${colors.background};--surface:${colors.surface};--surface-contrast:${surfaceContrast};--text:${colors.text};--muted:color-mix(in srgb,var(--text) 68%,var(--background));--surface-muted:color-mix(in srgb,var(--surface-contrast) 72%,var(--surface));--line:color-mix(in srgb,var(--text) 16%,var(--background));--display:${displayFont};--body:${bodyFont}}*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--background);color:var(--text);font-family:var(--body);line-height:1.55}a{color:inherit}.skip{position:absolute;left:-9999px}.skip:focus{left:16px;top:16px;z-index:9;background:var(--accent);color:var(--accent-contrast);padding:10px 14px;border-radius:999px}.header{height:80px;display:flex;align-items:center;justify-content:space-between;padding:0 clamp(20px,4vw,72px);position:relative;z-index:3;background:var(--surface);color:var(--surface-contrast);border-radius:0 0 24px 24px}.brand{display:flex;align-items:center;gap:12px;text-decoration:none;font-family:var(--display);font-size:24px}.mark{width:40px;height:40px;border-radius:12px;display:grid;place-items:center;background:var(--accent);color:var(--accent-contrast);font-family:var(--body);font-weight:700}.nav{display:flex;align-items:center;gap:28px}.nav a{text-decoration:none;color:var(--surface-muted);font-size:14px}.nav a:hover{color:var(--surface-contrast)}.nav a:focus-visible,.button:focus-visible,.social a:focus-visible,.menu:focus-visible{outline:3px solid var(--accent);outline-offset:4px}.menu{display:none;background:transparent;color:var(--surface-contrast);border:1px solid color-mix(in srgb,var(--surface-contrast) 28%,var(--surface));border-radius:999px;padding:10px 14px}.hero{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.25fr);min-height:min(760px,calc(100dvh - 80px));border-bottom:1px solid var(--line);background:var(--background)}.portrait{margin:clamp(16px,3vw,36px) clamp(12px,2vw,24px) clamp(16px,3vw,36px) clamp(16px,3vw,36px);display:grid;place-items:end center;background:var(--surface);border-radius:28px;overflow:hidden}.portrait-card{width:min(82%,560px);aspect-ratio:4/5;display:grid;place-items:center;align-self:end;border:1px solid color-mix(in srgb,var(--surface-contrast) 18%,var(--surface));border-bottom:0;background:linear-gradient(145deg,color-mix(in srgb,var(--surface-contrast) 12%,var(--surface)),var(--surface) 66%);font-family:var(--display);font-size:clamp(80px,13vw,180px);color:var(--surface-contrast)}.hero-copy{padding:clamp(44px,7vw,110px) clamp(24px,6vw,100px);display:flex;flex-direction:column;justify-content:center;background:var(--background)}h1,h2,h3,p{margin-top:0}.hero h1{font-family:var(--display);font-size:clamp(58px,8vw,116px);line-height:.96;font-weight:500;letter-spacing:-.04em;color:var(--text);margin-bottom:24px;text-wrap:balance}.role{font-family:var(--display);font-size:clamp(28px,3.8vw,52px);line-height:1.08;border-left:5px solid var(--accent);padding-left:22px;max-width:820px;text-wrap:balance}.summary{color:var(--muted);font-size:clamp(17px,1.5vw,22px);max-width:65ch}.actions{display:flex;gap:12px;flex-wrap:wrap;margin:24px 0}.button{display:inline-flex;align-items:center;justify-content:space-between;gap:28px;min-height:58px;padding:0 26px;background:var(--accent);color:var(--accent-contrast);border:1px solid var(--accent);border-radius:999px;text-decoration:none;font-weight:700;transition:transform .2s ease,filter .2s ease}.button:hover{filter:brightness(1.06)}.button:active{transform:translateY(1px)}.button--secondary{background:transparent;color:var(--text);border-color:var(--line)}.social{display:flex;gap:10px;flex-wrap:wrap}.social a{border:1px solid var(--line);border-radius:999px;padding:8px 13px;text-decoration:none;color:var(--muted);font-size:13px}.light{background:var(--background);color:var(--text);padding:clamp(70px,10vw,150px) clamp(20px,6vw,90px)}.light h2,.section h2{font-family:var(--display);font-size:clamp(42px,6vw,82px);line-height:1.05;font-weight:500;letter-spacing:-.035em;max-width:1080px;text-wrap:balance}.light p{max-width:65ch;color:var(--muted);font-size:18px}.section{padding:clamp(70px,9vw,130px) clamp(20px,6vw,90px);border-bottom:1px solid var(--line)}.section-head{max-width:920px;margin-bottom:46px}.eyebrow{text-transform:uppercase;letter-spacing:.18em;font-size:12px;color:var(--accent);font-weight:700}.consult{margin:clamp(20px,4vw,64px);display:grid;grid-template-columns:1.3fr .7fr;gap:50px;background:var(--surface);color:var(--surface-contrast);border:0;border-radius:28px}.consult .summary{color:var(--surface-muted)}.accent-card{min-height:360px;border:1px solid color-mix(in srgb,var(--surface-contrast) 18%,var(--surface));border-radius:24px;background:color-mix(in srgb,var(--accent) 14%,var(--surface));display:grid;place-items:center;font-family:var(--display);font-size:96px;color:var(--surface-contrast)}.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}.card{padding:30px;min-height:240px;border-radius:28px;background:var(--surface);color:var(--surface-contrast)}.card h3{font-family:var(--display);font-size:30px}.card p{color:var(--surface-muted)}.card .button--secondary{color:var(--surface-contrast);border-color:color-mix(in srgb,var(--surface-contrast) 28%,var(--surface))}.learning{background:var(--background)}.topic-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px}.topic{background:color-mix(in srgb,var(--text) 5%,var(--background));color:var(--text);border:1px solid var(--line);border-radius:28px;padding:30px}.topic strong{display:block;color:var(--accent);text-transform:uppercase;font-size:11px;letter-spacing:.15em}.topic h3{font-family:var(--display);font-size:30px;margin:8px 0}.topic p{color:var(--muted)}.topic a{color:var(--text);font-weight:700}.proof{background:color-mix(in srgb,var(--text) 5%,var(--background))}.quotes{display:flex;gap:14px;overflow:auto;scroll-snap-type:x mandatory;padding-bottom:12px}.quote{min-width:min(420px,86vw);scroll-snap-align:start;border:1px solid var(--line);border-radius:24px;padding:30px;background:var(--background)}.quote q{font-family:var(--display);font-size:30px;line-height:1.25}.quote span{display:block;margin-top:24px;color:var(--muted);font-size:12px;text-transform:uppercase;letter-spacing:.12em}.cta{margin:clamp(20px,4vw,64px);text-align:center;border:0;border-radius:28px;background:var(--surface);color:var(--surface-contrast)}.cta .summary{color:var(--surface-muted);margin-left:auto;margin-right:auto}.cta h2{margin-left:auto;margin-right:auto}.footer{display:grid;grid-template-columns:1fr auto;gap:40px;padding:46px clamp(20px,6vw,90px);color:var(--muted);background:var(--background)}.footer strong{color:var(--text);font-family:var(--display);font-size:26px}.generated{font-size:11px;color:var(--muted);margin-top:10px}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)}
38575
38973
  @media(max-width:760px){.header{height:78px;border-radius:0 0 18px 18px}.menu{display:block}.nav{display:none;position:absolute;left:0;right:0;top:77px;padding:18px 20px;background:var(--surface);border-radius:0 0 18px 18px;flex-direction:column;align-items:stretch}.nav.open{display:flex}.hero{grid-template-columns:1fr;min-height:0}.portrait{min-height:390px;margin:16px;border-radius:22px}.portrait-card{width:72%;max-height:360px}.hero-copy{padding:36px 20px 66px}.hero h1{font-size:58px}.role{font-size:34px}.actions{display:grid}.button{width:100%}.consult{grid-template-columns:1fr;margin:16px;border-radius:22px}.cta{margin:16px;border-radius:22px}.accent-card{min-height:220px}.grid,.topic-grid{grid-template-columns:1fr}.card,.topic{border-radius:22px}.light,.section{padding:64px 20px}.consult,.cta{padding:52px 20px}.light h2,.section h2{font-size:46px}.footer{grid-template-columns:1fr}}
38576
38974
  @media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}.button{transition:none}}
38577
38975
  </style></head>
38578
38976
  <body><a class="skip" href="#main">Skip to main content</a>
38579
- <header class="header"><a class="brand" href="#top"><span class="mark">${escapeHtml8(initials2(input.name).slice(0, 1))}</span><strong>${escapeHtml8(brand)}</strong></a>${navigation}</header>
38580
- <main id="main"><section class="hero" id="top"><div class="portrait" aria-label="Portrait placeholder"><div class="portrait-card" aria-hidden="true">${escapeHtml8(initials2(input.name))}</div></div><div class="hero-copy"><h1>${escapeHtml8(input.name)}</h1><p class="role">${escapeHtml8(input.professionalTitle)}</p><p class="summary">${escapeHtml8(input.summary)}</p><div class="actions">${action2(input.primaryAction)}${input.secondaryAction ? action2(input.secondaryAction, true) : ""}</div>${social}</div></section>
38581
- ${section2(flags.authority && Boolean(authority), `<section class="light" id="about"><h2>${escapeHtml8(authority?.heading ?? "")}</h2>${authority?.paragraphs.map((paragraph) => `<p>${escapeHtml8(paragraph)}</p>`).join("") ?? ""}</section>`)}
38582
- ${section2(flags.consultation && Boolean(consultation), `<section class="section consult"><div><p class="eyebrow">${escapeHtml8(consultation?.eyebrow ?? "Start a conversation")}</p><h2>${escapeHtml8(consultation?.heading ?? "")}</h2><p class="summary">${escapeHtml8(consultation?.summary ?? "")}</p>${consultation ? action2(consultation.action) : ""}</div><div class="accent-card" aria-label="Image placeholder">${escapeHtml8(initials2(input.name))}</div></section>`)}
38583
- ${section2(flags.learning && Boolean(learning), `<section class="section learning"><div class="section-head"><h2>${escapeHtml8(learning?.heading ?? "")}</h2><p class="summary">${escapeHtml8(learning?.summary ?? "")}</p></div><div class="topic-grid">${learning?.topics.map((topic) => `<article class="topic"><strong>${escapeHtml8(topic.title)}</strong><h3>${escapeHtml8(topic.headline)}</h3><p>${escapeHtml8(topic.summary)}</p>${topic.href ? `<a href="${safeHref2(topic.href)}">Explore \u2192</a>` : ""}</article>`).join("") ?? ""}</div></section>`)}
38584
- ${section2(flags.services && Boolean(services), `<section class="section" id="services"><div class="section-head"><h2>${escapeHtml8(services?.heading ?? "")}</h2><p class="summary">${escapeHtml8(services?.summary ?? "")}</p></div><div class="grid">${services?.offers.map((offer) => `<article class="card"><h3>${escapeHtml8(offer.title)}</h3><p>${escapeHtml8(offer.description)}</p>${offer.action ? action2(offer.action, true) : ""}</article>`).join("") ?? ""}</div></section>`)}
38585
- ${section2(flags.proof && Boolean(proof), `<section class="section proof" id="proof"><div class="section-head"><h2>${escapeHtml8(proof?.heading ?? "")}</h2><p class="summary">${escapeHtml8(proof?.summary ?? "")}</p></div><div class="quotes">${proof?.testimonials.map((item) => `<article class="quote"><q>${escapeHtml8(item.quote)}</q><span>${escapeHtml8(item.person)}${item.role ? ` / ${escapeHtml8(item.role)}` : ""}</span></article>`).join("") ?? ""}</div></section>`)}
38586
- ${section2(flags.finalCta && Boolean(finalCta), `<section class="section cta" id="contact"><p class="eyebrow">${escapeHtml8(finalCta?.eyebrow ?? "Ready when you are")}</p><h2>${escapeHtml8(finalCta?.heading ?? "")}</h2><p class="summary">${escapeHtml8(finalCta?.summary ?? "")}</p>${finalCta ? action2(finalCta.action) : ""}</section>`)}
38587
- </main><footer class="footer"><div><strong>${escapeHtml8(input.name)}</strong><div>${escapeHtml8(input.professionalTitle)}</div>${config.showGeneratedAt ? `<div class="generated">Generated ${escapeHtml8(generatedAtIso)}</div>` : ""}</div><div>${input.location ? `<div>${escapeHtml8(input.location)}</div>` : ""}${input.email ? `<a href="mailto:${escapeHtml8(input.email)}">${escapeHtml8(input.email)}</a>` : ""}${input.phone ? `<div>${escapeHtml8(input.phone)}</div>` : ""}</div></footer>
38977
+ <header class="header"><a class="brand" href="#top"><span class="mark">${escapeHtml9(initials2(input.name).slice(0, 1))}</span><strong>${escapeHtml9(brand)}</strong></a>${navigation}</header>
38978
+ <main id="main"><section class="hero" id="top"><div class="portrait" aria-label="Portrait placeholder"><div class="portrait-card" aria-hidden="true">${escapeHtml9(initials2(input.name))}</div></div><div class="hero-copy"><h1>${escapeHtml9(input.name)}</h1><p class="role">${escapeHtml9(input.professionalTitle)}</p><p class="summary">${escapeHtml9(input.summary)}</p><div class="actions">${action2(input.primaryAction)}${input.secondaryAction ? action2(input.secondaryAction, true) : ""}</div>${social}</div></section>
38979
+ ${section2(flags.authority && Boolean(authority), `<section class="light" id="about"><h2>${escapeHtml9(authority?.heading ?? "")}</h2>${authority?.paragraphs.map((paragraph) => `<p>${escapeHtml9(paragraph)}</p>`).join("") ?? ""}</section>`)}
38980
+ ${section2(flags.consultation && Boolean(consultation), `<section class="section consult"><div><p class="eyebrow">${escapeHtml9(consultation?.eyebrow ?? "Start a conversation")}</p><h2>${escapeHtml9(consultation?.heading ?? "")}</h2><p class="summary">${escapeHtml9(consultation?.summary ?? "")}</p>${consultation ? action2(consultation.action) : ""}</div><div class="accent-card" aria-label="Image placeholder">${escapeHtml9(initials2(input.name))}</div></section>`)}
38981
+ ${section2(flags.learning && Boolean(learning), `<section class="section learning"><div class="section-head"><h2>${escapeHtml9(learning?.heading ?? "")}</h2><p class="summary">${escapeHtml9(learning?.summary ?? "")}</p></div><div class="topic-grid">${learning?.topics.map((topic) => `<article class="topic"><strong>${escapeHtml9(topic.title)}</strong><h3>${escapeHtml9(topic.headline)}</h3><p>${escapeHtml9(topic.summary)}</p>${topic.href ? `<a href="${safeHref2(topic.href)}">Explore \u2192</a>` : ""}</article>`).join("") ?? ""}</div></section>`)}
38982
+ ${section2(flags.services && Boolean(services), `<section class="section" id="services"><div class="section-head"><h2>${escapeHtml9(services?.heading ?? "")}</h2><p class="summary">${escapeHtml9(services?.summary ?? "")}</p></div><div class="grid">${services?.offers.map((offer) => `<article class="card"><h3>${escapeHtml9(offer.title)}</h3><p>${escapeHtml9(offer.description)}</p>${offer.action ? action2(offer.action, true) : ""}</article>`).join("") ?? ""}</div></section>`)}
38983
+ ${section2(flags.proof && Boolean(proof), `<section class="section proof" id="proof"><div class="section-head"><h2>${escapeHtml9(proof?.heading ?? "")}</h2><p class="summary">${escapeHtml9(proof?.summary ?? "")}</p></div><div class="quotes">${proof?.testimonials.map((item) => `<article class="quote"><q>${escapeHtml9(item.quote)}</q><span>${escapeHtml9(item.person)}${item.role ? ` / ${escapeHtml9(item.role)}` : ""}</span></article>`).join("") ?? ""}</div></section>`)}
38984
+ ${section2(flags.finalCta && Boolean(finalCta), `<section class="section cta" id="contact"><p class="eyebrow">${escapeHtml9(finalCta?.eyebrow ?? "Ready when you are")}</p><h2>${escapeHtml9(finalCta?.heading ?? "")}</h2><p class="summary">${escapeHtml9(finalCta?.summary ?? "")}</p>${finalCta ? action2(finalCta.action) : ""}</section>`)}
38985
+ </main><footer class="footer"><div><strong>${escapeHtml9(input.name)}</strong><div>${escapeHtml9(input.professionalTitle)}</div>${config.showGeneratedAt ? `<div class="generated">Generated ${escapeHtml9(generatedAtIso)}</div>` : ""}</div><div>${input.location ? `<div>${escapeHtml9(input.location)}</div>` : ""}${input.email ? `<a href="mailto:${escapeHtml9(input.email)}">${escapeHtml9(input.email)}</a>` : ""}${input.phone ? `<div>${escapeHtml9(input.phone)}</div>` : ""}</div></footer>
38588
38986
  <script>document.querySelector('.menu')?.addEventListener('click',function(){var nav=document.querySelector('.nav');var open=this.getAttribute('aria-expanded')!=='true';this.setAttribute('aria-expanded',String(open));nav?.classList.toggle('open',open)});document.querySelectorAll('.nav a').forEach(function(link){link.addEventListener('click',function(){document.querySelector('.nav')?.classList.remove('open');document.querySelector('.menu')?.setAttribute('aria-expanded','false')})});</script></body></html>`;
38589
38987
  const bytes = Buffer.byteLength(html, "utf8");
38590
38988
  return {
@@ -38598,7 +38996,7 @@ ${section2(flags.finalCta && Boolean(finalCta), `<section class="section cta" id
38598
38996
 
38599
38997
  // src/newsroom-publisher/render.ts
38600
38998
  import { createHash as createHash23 } from "crypto";
38601
- function escapeHtml9(value) {
38999
+ function escapeHtml10(value) {
38602
39000
  return value.replace(/[&<>"']/g, (character) => ({
38603
39001
  "&": "&amp;",
38604
39002
  "<": "&lt;",
@@ -38609,30 +39007,30 @@ function escapeHtml9(value) {
38609
39007
  }
38610
39008
  function safeHref3(value) {
38611
39009
  const trimmed = value.trim();
38612
- return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ? escapeHtml9(trimmed) : "#";
39010
+ return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ? escapeHtml10(trimmed) : "#";
38613
39011
  }
38614
39012
  function formatDate(value) {
38615
39013
  const date = new Date(value);
38616
- return Number.isNaN(date.getTime()) ? escapeHtml9(value) : new Intl.DateTimeFormat("en", { month: "short", day: "numeric", year: "numeric" }).format(date);
39014
+ return Number.isNaN(date.getTime()) ? escapeHtml10(value) : new Intl.DateTimeFormat("en", { month: "short", day: "numeric", year: "numeric" }).format(date);
38617
39015
  }
38618
39016
  function initials3(value) {
38619
39017
  return value.split(/\s+/).filter(Boolean).slice(0, 2).map((part) => part[0]).join("").toUpperCase();
38620
39018
  }
38621
39019
  function storyMedia(story, className = "") {
38622
39020
  if (story.imageUrl) {
38623
- return `<div class="story-media ${className}"><img src="${safeHref3(story.imageUrl)}" alt="${escapeHtml9(story.imageAlt || story.title)}" loading="lazy"></div>`;
39021
+ return `<div class="story-media ${className}"><img src="${safeHref3(story.imageUrl)}" alt="${escapeHtml10(story.imageAlt || story.title)}" loading="lazy"></div>`;
38624
39022
  }
38625
39023
  const tone = [...story.title].reduce((total, character) => total + character.charCodeAt(0), 0) % 5;
38626
- return `<div class="story-media story-media--placeholder story-media--tone-${tone} ${className}" role="img" aria-label="Editorial image placeholder for ${escapeHtml9(story.title)}"><i></i><b></b><span>${escapeHtml9(story.category)}</span></div>`;
39024
+ return `<div class="story-media story-media--placeholder story-media--tone-${tone} ${className}" role="img" aria-label="Editorial image placeholder for ${escapeHtml10(story.title)}"><i></i><b></b><span>${escapeHtml10(story.category)}</span></div>`;
38627
39025
  }
38628
39026
  function byline(story, showBylines) {
38629
- const author = story.author.href ? `<a href="${safeHref3(story.author.href)}">${escapeHtml9(story.author.name)}</a>` : escapeHtml9(story.author.name);
38630
- return `<div class="byline">${showBylines ? `<span>By ${author}</span>` : ""}<time datetime="${escapeHtml9(story.publishedAt)}">${formatDate(story.publishedAt)}</time>${story.sponsored ? "<b>Sponsored</b>" : ""}</div>`;
39027
+ const author = story.author.href ? `<a href="${safeHref3(story.author.href)}">${escapeHtml10(story.author.name)}</a>` : escapeHtml10(story.author.name);
39028
+ return `<div class="byline">${showBylines ? `<span>By ${author}</span>` : ""}<time datetime="${escapeHtml10(story.publishedAt)}">${formatDate(story.publishedAt)}</time>${story.sponsored ? "<b>Sponsored</b>" : ""}</div>`;
38631
39029
  }
38632
39030
  function storyCard(story, showBylines, variant = "") {
38633
39031
  return `<article class="story-card ${variant}">
38634
39032
  <a class="story-card__media" href="${safeHref3(story.href)}">${storyMedia(story)}</a>
38635
- <div class="story-card__body"><a class="kicker" href="${safeHref3(story.href)}">${escapeHtml9(story.category)}</a><h3><a href="${safeHref3(story.href)}">${escapeHtml9(story.title)}</a></h3>${story.dek ? `<p>${escapeHtml9(story.dek)}</p>` : ""}${byline(story, showBylines)}</div>
39033
+ <div class="story-card__body"><a class="kicker" href="${safeHref3(story.href)}">${escapeHtml10(story.category)}</a><h3><a href="${safeHref3(story.href)}">${escapeHtml10(story.title)}</a></h3>${story.dek ? `<p>${escapeHtml10(story.dek)}</p>` : ""}${byline(story, showBylines)}</div>
38636
39034
  </article>`;
38637
39035
  }
38638
39036
  function renderNewsroomPublisherV1(input, config, generatedAt) {
@@ -38649,22 +39047,22 @@ function renderNewsroomPublisherV1(input, config, generatedAt) {
38649
39047
  input.primaryPages.contact
38650
39048
  ];
38651
39049
  const trustPages = Object.values(input.trustPages);
38652
- const ticker = flags.breakingTicker && input.ticker ? `<div class="ticker"><div><b>${escapeHtml9(input.ticker.label)}</b><a href="${safeHref3(input.ticker.href || "#latest")}">${escapeHtml9(input.ticker.headline)}</a><span>${formatDate(generatedAtIso)}</span></div></div>` : "";
38653
- const masthead = `<nav class="utility-nav" aria-label="Publication pages"><div><span>${escapeHtml9(input.publication.location || "Independent newsroom")}</span>${primaryPages.slice(1).map((link) => `<a href="${safeHref3(link.href)}">${escapeHtml9(link.label)}</a>`).join("")}</div></nav><header class="masthead">
38654
- <a class="wordmark" href="${safeHref3(input.publication.url)}"><span>${escapeHtml9(brand)}</span><small>${escapeHtml9(input.publication.tagline)}</small></a>
39050
+ const ticker = flags.breakingTicker && input.ticker ? `<div class="ticker"><div><b>${escapeHtml10(input.ticker.label)}</b><a href="${safeHref3(input.ticker.href || "#latest")}">${escapeHtml10(input.ticker.headline)}</a><span>${formatDate(generatedAtIso)}</span></div></div>` : "";
39051
+ const masthead = `<nav class="utility-nav" aria-label="Publication pages"><div><span>${escapeHtml10(input.publication.location || "Independent newsroom")}</span>${primaryPages.slice(1).map((link) => `<a href="${safeHref3(link.href)}">${escapeHtml10(link.label)}</a>`).join("")}</div></nav><header class="masthead">
39052
+ <a class="wordmark" href="${safeHref3(input.publication.url)}"><span>${escapeHtml10(brand)}</span><small>${escapeHtml10(input.publication.tagline)}</small></a>
38655
39053
  <div class="masthead__date"><span>Independent journalism</span><time datetime="${generatedAtIso}">${formatDate(generatedAtIso)}</time></div>
38656
39054
  <div class="masthead__tools"><button type="button" aria-label="Search">Search</button><button type="button" aria-label="Open menu">Menu</button></div>
38657
39055
  </header>`;
38658
- const navigation = flags.navigation ? `<nav class="desk-nav" aria-label="Publication categories"><div><a class="desk-nav__home" href="#top">Home</a>${input.categories.map((category) => `<a href="${safeHref3(category.href)}">${escapeHtml9(category.label)}</a>`).join("")}<a class="desk-nav__latest" href="#latest">Latest</a></div></nav>` : "";
39056
+ const navigation = flags.navigation ? `<nav class="desk-nav" aria-label="Publication categories"><div><a class="desk-nav__home" href="#top">Home</a>${input.categories.map((category) => `<a href="${safeHref3(category.href)}">${escapeHtml10(category.label)}</a>`).join("")}<a class="desk-nav__latest" href="#latest">Latest</a></div></nav>` : "";
38659
39057
  const leadGrid = flags.leadGrid ? `<section class="lead-grid" aria-label="Top stories">
38660
39058
  <div class="lead-grid__label"><span>Today\u2019s edition</span><b>Top stories</b></div>
38661
- <article class="lead-story"><a class="lead-story__media" href="${safeHref3(lead.href)}">${storyMedia(lead, "story-media--lead")}</a><div class="lead-story__body"><a class="kicker" href="${safeHref3(lead.href)}">${escapeHtml9(lead.category)}</a><h1><a href="${safeHref3(lead.href)}">${escapeHtml9(lead.title)}</a></h1>${lead.dek ? `<p>${escapeHtml9(lead.dek)}</p>` : ""}${byline(lead, config.showBylines)}<a class="read-story" href="${safeHref3(lead.href)}">Read the full report <span>\u2197</span></a></div></article>
39059
+ <article class="lead-story"><a class="lead-story__media" href="${safeHref3(lead.href)}">${storyMedia(lead, "story-media--lead")}</a><div class="lead-story__body"><a class="kicker" href="${safeHref3(lead.href)}">${escapeHtml10(lead.category)}</a><h1><a href="${safeHref3(lead.href)}">${escapeHtml10(lead.title)}</a></h1>${lead.dek ? `<p>${escapeHtml10(lead.dek)}</p>` : ""}${byline(lead, config.showBylines)}<a class="read-story" href="${safeHref3(lead.href)}">Read the full report <span>\u2197</span></a></div></article>
38662
39060
  <div class="lead-support">${supporting.slice(0, 4).map((story, index) => `<div class="lead-support__item"><span>${String(index + 1).padStart(2, "0")}</span>${storyCard(story, config.showBylines, "story-card--support")}</div>`).join("")}</div>
38663
39061
  </section>` : "";
38664
39062
  const latest = flags.latestNews && input.latest.length > 0 ? `<section class="latest" id="latest">
38665
39063
  <div class="section-title"><div><span>Live desk</span><h2>Latest news</h2></div><a href="#top">Back to top \u2191</a></div>
38666
- <div class="latest__layout"><div class="latest__feed">${input.latest.map((story, index) => `<article class="feed-story"><span>${String(index + 1).padStart(2, "0")}</span><div><a class="kicker" href="${safeHref3(story.href)}">${escapeHtml9(story.category)}</a><h3><a href="${safeHref3(story.href)}">${escapeHtml9(story.title)}</a></h3>${story.dek ? `<p>${escapeHtml9(story.dek)}</p>` : ""}${byline(story, config.showBylines)}</div>${storyMedia(story, "story-media--feed")}</article>`).join("")}</div>
38667
- <aside class="editor-note"><span>From the newsroom</span><h3>Reporting with context, sources, and accountable bylines.</h3><p>${escapeHtml9(input.editorial.disclosure)}</p>${trustPages.slice(0, 4).map((link) => `<a href="${safeHref3(link.href)}">${escapeHtml9(link.label)} \u2197</a>`).join("")}</aside></div>
39064
+ <div class="latest__layout"><div class="latest__feed">${input.latest.map((story, index) => `<article class="feed-story"><span>${String(index + 1).padStart(2, "0")}</span><div><a class="kicker" href="${safeHref3(story.href)}">${escapeHtml10(story.category)}</a><h3><a href="${safeHref3(story.href)}">${escapeHtml10(story.title)}</a></h3>${story.dek ? `<p>${escapeHtml10(story.dek)}</p>` : ""}${byline(story, config.showBylines)}</div>${storyMedia(story, "story-media--feed")}</article>`).join("")}</div>
39065
+ <aside class="editor-note"><span>From the newsroom</span><h3>Reporting with context, sources, and accountable bylines.</h3><p>${escapeHtml10(input.editorial.disclosure)}</p>${trustPages.slice(0, 4).map((link) => `<a href="${safeHref3(link.href)}">${escapeHtml10(link.label)} \u2197</a>`).join("")}</aside></div>
38668
39066
  </section>` : "";
38669
39067
  const sectionLayouts = ["panorama", "mosaic", "tiles"];
38670
39068
  const sections = flags.categorySections ? input.sections.map((section3, sectionIndex) => {
@@ -38675,16 +39073,16 @@ function renderNewsroomPublisherV1(input, config, generatedAt) {
38675
39073
  layout === "panorama" && index === 0 ? "story-card--panorama" : layout === "mosaic" && index === 0 ? "story-card--mosaic-lead" : ""
38676
39074
  )).join("");
38677
39075
  return `<section class="desk-section desk-section--${sectionIndex % 2 ? "tint" : "plain"} desk-section--layout-${layout}">
38678
- <div class="section-title"><div><span>Coverage desk \xB7 ${String(sectionIndex + 1).padStart(2, "0")}</span><h2>${escapeHtml9(section3.name)}</h2></div>${section3.href ? `<a href="${safeHref3(section3.href)}">View all ${escapeHtml9(section3.name)} \u2192</a>` : ""}</div>
39076
+ <div class="section-title"><div><span>Coverage desk \xB7 ${String(sectionIndex + 1).padStart(2, "0")}</span><h2>${escapeHtml10(section3.name)}</h2></div>${section3.href ? `<a href="${safeHref3(section3.href)}">View all ${escapeHtml10(section3.name)} \u2192</a>` : ""}</div>
38679
39077
  <div class="desk-section__grid desk-section__grid--${layout}">${cards}</div>
38680
39078
  </section>`;
38681
39079
  }).join("") : "";
38682
- const newsletter = flags.newsletter && input.newsletter ? `<section class="newsletter"><div><span>${escapeHtml9(input.newsletter.eyebrow || "Reader briefing")}</span><h2>${escapeHtml9(input.newsletter.heading)}</h2><p>${escapeHtml9(input.newsletter.summary)}</p></div><a href="${safeHref3(input.newsletter.action.href)}">${escapeHtml9(input.newsletter.action.label)} \u2192</a></section>` : "";
38683
- const pressRoom = flags.pressRoom && input.pressRoom ? `<section class="press-room" id="press-room"><div class="press-room__intro"><span>Separate from editorial coverage</span><h2>${escapeHtml9(input.pressRoom.heading)}</h2><p>${escapeHtml9(input.pressRoom.summary)}</p><a href="${safeHref3(input.pressRoom.action.href)}">${escapeHtml9(input.pressRoom.action.label)} \u2192</a></div><div class="release-list">${input.pressRoom.releases.map((release) => `<article><time datetime="${escapeHtml9(release.publishedAt)}">${formatDate(release.publishedAt)}</time><span>${escapeHtml9(release.originatingCity)}</span><h3><a href="${safeHref3(release.href)}">${escapeHtml9(release.headline)}</a></h3></article>`).join("") || "<p>No releases are currently published.</p>"}</div></section>` : "";
38684
- const trustCenter = `<section class="trust-center" id="trust"><div class="trust-center__intro"><span>Public record</span><h2>How this newsroom works.</h2><p>Ownership, editorial practice, technology use, commercial relationships, and reader rights should be easy to find\u2014and written to be understood.</p></div><div class="trust-center__grid">${trustPages.map((link, index) => `<a href="${safeHref3(link.href)}"><span>${String(index + 1).padStart(2, "0")}</span><strong>${escapeHtml9(link.label)}</strong><small>Read \u2192</small></a>`).join("")}</div></section>`;
38685
- const trustFooter = flags.trustFooter ? `<footer class="site-footer"><div class="editor"><span class="editor__avatar">${escapeHtml9(initials3(input.editorial.managingEditor.name))}</span><div><small>${escapeHtml9(input.editorial.managingEditor.role)}</small><h2>${input.editorial.managingEditor.href ? `<a href="${safeHref3(input.editorial.managingEditor.href)}">${escapeHtml9(input.editorial.managingEditor.name)}</a>` : escapeHtml9(input.editorial.managingEditor.name)}</h2><p>${escapeHtml9(input.editorial.managingEditor.bio)}</p></div></div><div class="footer-links"><h3>${escapeHtml9(brand)}</h3><p>${escapeHtml9(input.publication.tagline)}</p><nav>${primaryPages.map((link) => `<a href="${safeHref3(link.href)}">${escapeHtml9(link.label)}</a>`).join("")}</nav>${config.showGeneratedAt ? `<time datetime="${generatedAtIso}">Updated ${formatDate(generatedAtIso)}</time>` : ""}</div></footer>` : "";
39080
+ const newsletter = flags.newsletter && input.newsletter ? `<section class="newsletter"><div><span>${escapeHtml10(input.newsletter.eyebrow || "Reader briefing")}</span><h2>${escapeHtml10(input.newsletter.heading)}</h2><p>${escapeHtml10(input.newsletter.summary)}</p></div><a href="${safeHref3(input.newsletter.action.href)}">${escapeHtml10(input.newsletter.action.label)} \u2192</a></section>` : "";
39081
+ const pressRoom = flags.pressRoom && input.pressRoom ? `<section class="press-room" id="press-room"><div class="press-room__intro"><span>Separate from editorial coverage</span><h2>${escapeHtml10(input.pressRoom.heading)}</h2><p>${escapeHtml10(input.pressRoom.summary)}</p><a href="${safeHref3(input.pressRoom.action.href)}">${escapeHtml10(input.pressRoom.action.label)} \u2192</a></div><div class="release-list">${input.pressRoom.releases.map((release) => `<article><time datetime="${escapeHtml10(release.publishedAt)}">${formatDate(release.publishedAt)}</time><span>${escapeHtml10(release.originatingCity)}</span><h3><a href="${safeHref3(release.href)}">${escapeHtml10(release.headline)}</a></h3></article>`).join("") || "<p>No releases are currently published.</p>"}</div></section>` : "";
39082
+ const trustCenter = `<section class="trust-center" id="trust"><div class="trust-center__intro"><span>Public record</span><h2>How this newsroom works.</h2><p>Ownership, editorial practice, technology use, commercial relationships, and reader rights should be easy to find\u2014and written to be understood.</p></div><div class="trust-center__grid">${trustPages.map((link, index) => `<a href="${safeHref3(link.href)}"><span>${String(index + 1).padStart(2, "0")}</span><strong>${escapeHtml10(link.label)}</strong><small>Read \u2192</small></a>`).join("")}</div></section>`;
39083
+ const trustFooter = flags.trustFooter ? `<footer class="site-footer"><div class="editor"><span class="editor__avatar">${escapeHtml10(initials3(input.editorial.managingEditor.name))}</span><div><small>${escapeHtml10(input.editorial.managingEditor.role)}</small><h2>${input.editorial.managingEditor.href ? `<a href="${safeHref3(input.editorial.managingEditor.href)}">${escapeHtml10(input.editorial.managingEditor.name)}</a>` : escapeHtml10(input.editorial.managingEditor.name)}</h2><p>${escapeHtml10(input.editorial.managingEditor.bio)}</p></div></div><div class="footer-links"><h3>${escapeHtml10(brand)}</h3><p>${escapeHtml10(input.publication.tagline)}</p><nav>${primaryPages.map((link) => `<a href="${safeHref3(link.href)}">${escapeHtml10(link.label)}</a>`).join("")}</nav>${config.showGeneratedAt ? `<time datetime="${generatedAtIso}">Updated ${formatDate(generatedAtIso)}</time>` : ""}</div></footer>` : "";
38686
39084
  const html = `<!doctype html>
38687
- <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex,nofollow"><title>${escapeHtml9(brand)} \xB7 News Publisher</title><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@75..125,300..900&family=Instrument+Serif:ital@0;1&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
39085
+ <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex,nofollow"><title>${escapeHtml10(brand)} \xB7 News Publisher</title><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@75..125,300..900&family=Instrument+Serif:ital@0;1&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
38688
39086
  <style>
38689
39087
  :root{--ink:#0b0b0c;--soft-ink:#222326;--muted:#696b70;--paper:#fff;--cream:#f4f0e8;--wash:#f5f5f3;--line:#d8d8d4;--signal:#275cf3;--acid:#d9ff43;--dark:#0b0b0c;--serif:"Instrument Serif",Georgia,serif;--sans:"Archivo",Arial,sans-serif;--mono:"JetBrains Mono",monospace;font-family:var(--sans);color:var(--ink);background:var(--paper)}*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--paper);line-height:1.45}body[data-theme=journal]{--cream:#eee7da;--signal:#9d2d25;--acid:#f0c84f}body[data-theme=midnight]{--paper:#e8e9ec;--cream:#dfe1e6;--wash:#d8dae0;--line:#b9bdc6;--signal:#224bcc}a{color:inherit;text-decoration:none}a,button{transition:color .18s ease,background .18s ease,opacity .18s ease,transform .18s ease}button{font:inherit}.utility-nav{color:#d2d2d2;background:var(--dark);border-bottom:1px solid #292929}.utility-nav>div{max-width:1180px;height:35px;margin:auto;display:flex;align-items:center;justify-content:flex-end;gap:20px;padding:0 18px;overflow:auto}.utility-nav span{margin-right:auto;color:#8d8d8d}.utility-nav a,.utility-nav span{font:600 8px/1 var(--mono);letter-spacing:.08em;text-transform:uppercase;white-space:nowrap}.utility-nav a:hover{color:#fff}.ticker{color:var(--ink);background:var(--acid);padding:0 18px}.ticker>div{max-width:1180px;height:36px;margin:auto;display:flex;align-items:center;gap:16px;font:600 10px/1 var(--mono)}.ticker b{padding:5px 7px;color:#fff;background:var(--ink);font-size:8px;letter-spacing:.1em;text-transform:uppercase}.ticker a{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ticker a:hover{text-decoration:underline}.ticker span{margin-left:auto;opacity:.58;font-size:8px;text-transform:uppercase}.masthead{max-width:1180px;height:126px;margin:auto;display:grid;grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:42px;padding:0 18px}.wordmark{display:grid;justify-self:start}.wordmark span{font:400 clamp(40px,5vw,68px)/.82 var(--serif);letter-spacing:-.055em}.wordmark small{max-width:430px;margin-top:11px;color:var(--muted);font:600 8px/1 var(--mono);letter-spacing:.1em;text-transform:uppercase}.masthead__date{display:grid;gap:3px;text-align:right}.masthead__date span,.masthead__date time{font:600 8px/1.4 var(--mono);letter-spacing:.08em;text-transform:uppercase}.masthead__date span{color:var(--signal)}.masthead__date time{color:var(--muted)}.masthead__tools{display:flex;border:1px solid var(--ink)}.masthead__tools button{height:38px;padding:0 13px;border:0;background:transparent;font:700 9px/1 var(--mono);text-transform:uppercase;cursor:pointer}.masthead__tools button+button{border-left:1px solid var(--ink)}.masthead__tools button:hover{color:#fff;background:var(--ink)}.desk-nav{position:sticky;top:0;z-index:20;color:var(--ink);background:rgba(255,255,255,.96);border-top:1px solid var(--ink);border-bottom:1px solid var(--ink);backdrop-filter:blur(10px)}.desk-nav>div{max-width:1180px;height:43px;margin:auto;display:flex;align-items:center;overflow-x:auto;padding:0 18px}.desk-nav a{height:42px;display:grid;place-items:center;padding:0 17px;border-right:1px solid var(--line);font:650 9px/1 var(--mono);letter-spacing:.04em;text-transform:uppercase;white-space:nowrap}.desk-nav a:first-child{border-left:1px solid var(--line)}.desk-nav a:hover,.desk-nav__home{color:#fff!important;background:var(--ink)}.desk-nav__latest{margin-left:auto;color:var(--signal);border-left:1px solid var(--line)}main{max-width:1180px;margin:auto;padding:30px 18px 90px}.lead-grid{margin:0 -18px;padding:0 18px 42px;color:#fff;background:var(--dark);border-bottom:1px solid var(--ink)}.lead-grid__label{height:50px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #303030}.lead-grid__label span,.lead-grid__label b{font:600 8px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase}.lead-grid__label span{color:var(--acid)}.lead-grid__label b{color:#8f8f8f}.lead-story{display:grid;grid-template-columns:minmax(0,1.28fr) minmax(340px,.72fr);min-height:500px;border-bottom:1px solid #303030}.lead-story__media{display:block;margin-left:calc((1180px - 100vw)/2);min-width:0}.story-media{position:relative;aspect-ratio:16/10;overflow:hidden;background:#e2e2df}.story-media img{width:100%;height:100%;display:block;object-fit:cover;filter:saturate(.88) contrast(1.03);transition:transform .55s cubic-bezier(.2,.7,.2,1)}a:hover .story-media img{transform:scale(1.025)}.story-media--lead{height:100%;min-height:500px;aspect-ratio:auto}.story-media--placeholder{isolation:isolate;display:block;background:#d9d7d1}.story-media--placeholder:after{position:absolute;z-index:1;inset:0;background:linear-gradient(145deg,transparent 35%,rgba(0,0,0,.14));content:""}.story-media--placeholder i,.story-media--placeholder b{position:absolute;display:block}.story-media--placeholder i{width:72%;aspect-ratio:1;right:-20%;top:-32%;border:clamp(22px,5vw,72px) solid currentColor;border-radius:50%;opacity:.78}.story-media--placeholder b{width:42%;height:115%;left:15%;bottom:-45%;background:currentColor;transform:rotate(32deg);opacity:.88}.story-media--placeholder span{position:absolute;z-index:2;left:18px;bottom:15px;padding:6px 8px;color:#fff;background:var(--ink);font:600 8px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase}.story-media--tone-0{color:#123fce;background:#a5c8ff}.story-media--tone-1{color:#ef4d25;background:#ffd9bd}.story-media--tone-2{color:#907000;background:#f3df36}.story-media--tone-3{color:#1a7857;background:#b8e8cc}.story-media--tone-4{color:#7d3de0;background:#dfc5ff}.lead-story__body{display:flex;flex-direction:column;justify-content:center;padding:45px 0 45px 40px}.kicker{display:inline-flex;width:max-content;color:var(--signal);font:700 8px/1 var(--mono);letter-spacing:.11em;text-transform:uppercase}.lead-grid .kicker{color:var(--acid)}.lead-story h1{max-width:540px;margin:13px 0 18px;font:400 clamp(48px,5vw,76px)/.92 var(--serif);letter-spacing:-.052em}.lead-story p{max-width:490px;margin:0;color:#bdbdbd;font-size:15px;line-height:1.55}.byline{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:16px;color:var(--muted);font:600 8px/1.4 var(--mono);letter-spacing:.05em;text-transform:uppercase}.byline span{color:var(--ink);font-weight:700}.lead-grid .byline{color:#848484}.lead-grid .byline span{color:#e7e7e7}.byline b{padding:4px 6px;color:var(--ink);background:var(--acid)}.read-story{width:max-content;margin-top:34px;padding-bottom:6px;border-bottom:1px solid #777;font:650 10px/1 var(--mono);text-transform:uppercase}.read-story span{color:var(--acid)}.read-story:hover{border-color:#fff}.lead-support{display:grid;grid-template-columns:repeat(4,1fr);gap:0}.lead-support__item{display:grid;grid-template-columns:25px minmax(0,1fr);gap:12px;padding:22px 18px 0 0;border-right:1px solid #303030}.lead-support__item+.lead-support__item{padding-left:18px}.lead-support__item:last-child{border-right:0}.lead-support__item>span{color:#666;font:600 9px/1 var(--mono)}.story-card{min-width:0}.story-card h3{margin:7px 0;font:400 26px/1.02 var(--serif);letter-spacing:-.025em}.story-card p{margin:9px 0;color:var(--muted);font-size:12px}.story-card__body{padding-top:11px}.story-card--support .story-card__media{display:none}.story-card--support .story-card__body{padding:0}.story-card--support h3{margin-top:8px;color:#fff;font-size:21px}.story-card--support p,.story-card--support .byline span{display:none}.story-card--support .byline{color:#777}.section-title{display:flex;align-items:end;justify-content:space-between;gap:30px;margin-bottom:24px;padding-bottom:11px;border-bottom:2px solid var(--ink)}.section-title span,.newsletter span,.press-room__intro>span,.trust-center__intro>span{display:block;color:var(--signal);font:700 8px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase}.section-title h2,.newsletter h2,.press-room h2,.trust-center h2,.site-footer h2{margin:7px 0 0;font:400 clamp(38px,5vw,58px)/.95 var(--serif);letter-spacing:-.04em}.section-title>a{padding-bottom:4px;border-bottom:1px solid var(--ink);font:650 9px/1 var(--mono);text-transform:uppercase}.latest{padding:64px 0}.latest__layout{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:55px}.latest__feed{border-top:1px solid var(--ink)}.feed-story{display:grid;grid-template-columns:34px minmax(0,1fr) 180px;gap:18px;align-items:start;padding:19px 0;border-bottom:1px solid var(--line)}.feed-story>span{color:#a0a0a0;font:600 9px/1 var(--mono)}.feed-story h3{margin:7px 0;font:400 29px/1.02 var(--serif);letter-spacing:-.025em}.feed-story p{margin:8px 0;color:var(--muted);font-size:12px}.story-media--feed{aspect-ratio:4/3}.editor-note{position:sticky;top:68px;align-self:start;padding:25px;color:#fff;background:var(--dark);border-top:5px solid var(--acid)}.editor-note>span{color:var(--acid);font:600 8px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase}.editor-note h3{margin:13px 0;font:400 31px/.98 var(--serif)}.editor-note p{color:#aaa;font-size:12px}.editor-note a{display:block;padding:11px 0;border-top:1px solid #333;font:600 9px/1 var(--mono);text-transform:uppercase}.editor-note a:hover{color:var(--acid)}.desk-section{margin:0 -18px;padding:58px 18px;border-top:1px solid var(--ink)}.desk-section--tint{background:var(--cream)}.desk-section__grid{display:grid;grid-template-columns:repeat(4,1fr);gap:26px 14px}.story-card--wide{grid-column:span 2;grid-row:span 2}.story-card--wide h3{max-width:530px;font-size:40px}.story-card--wide p{max-width:540px;font-size:13px}.desk-section__grid>.story-card:not(.story-card--wide) .story-media{aspect-ratio:1}.newsletter{position:relative;margin:64px 0;display:grid;grid-template-columns:1fr auto;align-items:end;gap:50px;overflow:hidden;padding:clamp(38px,6vw,72px);color:var(--ink);background:var(--acid)}.newsletter:after{position:absolute;width:260px;height:260px;right:18%;top:-160px;border:55px solid var(--ink);border-radius:50%;content:"";opacity:.08}.newsletter span{color:var(--ink)}.newsletter h2{max-width:760px;font-size:clamp(44px,6vw,72px)}.newsletter p{max-width:680px;margin-bottom:0;color:#303030}.newsletter>a,.press-room__intro>a{position:relative;z-index:1;display:inline-flex;padding:14px 18px;color:#fff;background:var(--ink);border:1px solid var(--ink);font:700 9px/1 var(--mono);text-transform:uppercase}.newsletter>a:hover,.press-room__intro>a:hover{color:var(--ink);background:transparent}.press-room{display:grid;grid-template-columns:.7fr 1.3fr;gap:56px;padding:62px 0;border-top:6px solid var(--ink)}.press-room__intro p{max-width:390px;color:var(--muted)}.release-list{border-top:1px solid var(--ink)}.release-list article{display:grid;grid-template-columns:105px 105px 1fr;gap:15px;align-items:start;padding:20px 0;border-bottom:1px solid var(--line)}.release-list time,.release-list span{color:var(--muted);font:500 8px/1.4 var(--mono);text-transform:uppercase}.release-list h3{margin:0;font:400 22px/1.04 var(--serif)}.trust-center{margin:20px -18px -90px;padding:70px max(18px,calc((100vw - 1144px)/2)) 82px;color:#fff;background:var(--dark)}.trust-center__intro{max-width:810px;margin-bottom:38px}.trust-center__intro>span{color:var(--acid)}.trust-center__intro p{max-width:670px;color:#aaa}.trust-center__grid{display:grid;grid-template-columns:repeat(2,1fr);border-top:1px solid #444}.trust-center__grid a{display:grid;grid-template-columns:32px minmax(0,1fr) auto;align-items:center;gap:15px;min-height:70px;padding:0 18px 0 0;border-bottom:1px solid #333}.trust-center__grid a:nth-child(odd){margin-right:28px}.trust-center__grid a:hover{color:var(--acid)}.trust-center__grid span,.trust-center__grid small{color:#696969;font:600 8px/1 var(--mono)}.trust-center__grid strong{font:400 20px/1 var(--serif)}.site-footer{display:grid;grid-template-columns:1.15fr .85fr;gap:80px;padding:70px max(24px,calc((100vw - 1144px)/2));color:var(--ink);background:var(--cream);border-top:1px solid var(--ink)}.editor{display:grid;grid-template-columns:78px 1fr;gap:22px}.editor__avatar{width:78px;height:78px;display:grid;place-items:center;color:#fff;background:var(--signal);font:400 27px/1 var(--serif)}.editor small{color:var(--signal);font:700 8px/1 var(--mono);letter-spacing:.08em;text-transform:uppercase}.editor h2{font-size:38px}.editor p,.footer-links p{max-width:620px;color:var(--muted)}.footer-links h3{margin-top:0;font:400 29px/1 var(--serif)}.footer-links nav{display:grid;grid-template-columns:1fr 1fr;border-top:1px solid var(--ink)}.footer-links nav a{padding:9px 0;border-bottom:1px solid var(--line);font:600 8px/1 var(--mono);text-transform:uppercase}.footer-links time{display:block;margin-top:24px;color:var(--muted);font:500 8px/1 var(--mono)}@media(max-width:900px){.masthead{grid-template-columns:1fr auto;height:110px}.masthead__date{display:none}.lead-story{grid-template-columns:1fr}.lead-story__media{margin:0}.lead-story__body{padding:35px 0}.lead-support{grid-template-columns:1fr 1fr}.lead-support__item:nth-child(2){border-right:0}.lead-support__item:nth-child(n+3){border-top:1px solid #303030}.latest__layout,.press-room,.site-footer{grid-template-columns:1fr}.editor-note{position:static}.desk-section__grid{grid-template-columns:1fr 1fr}.story-card--wide{grid-column:1/-1}.site-footer{gap:40px}.feed-story{grid-template-columns:30px 1fr 150px}}@media(max-width:620px){.utility-nav span,.utility-nav a:nth-of-type(-n+2),.ticker span{display:none}.ticker>div{height:34px}.masthead{height:92px;gap:14px}.wordmark span{font-size:38px}.wordmark small{max-width:220px;font-size:6px}.masthead__tools button:first-child{display:none}.desk-nav>div{padding:0}.desk-nav a{padding:0 13px}.lead-grid{padding-bottom:20px}.lead-grid__label{height:40px}.story-media--lead{min-height:320px}.lead-story{min-height:0}.lead-story h1{font-size:48px}.lead-story__body{padding:27px 0 34px}.lead-support{grid-template-columns:1fr}.lead-support__item,.lead-support__item+.lead-support__item{padding:17px 0;border-right:0;border-top:1px solid #303030}.story-card--support h3{font-size:24px}.section-title{align-items:start}.section-title>a{display:none}.latest{padding:48px 0}.feed-story{grid-template-columns:25px 1fr}.story-media--feed{grid-column:2}.feed-story h3{font-size:26px}.desk-section__grid{grid-template-columns:1fr}.story-card--wide{grid-column:auto;grid-row:auto}.story-card--wide h3{font-size:34px}.newsletter{grid-template-columns:1fr}.newsletter h2{font-size:48px}.release-list article{grid-template-columns:1fr}.trust-center__grid{grid-template-columns:1fr}.trust-center__grid a:nth-child(odd){margin-right:0}.site-footer{padding:50px 20px}.editor{grid-template-columns:1fr}.footer-links nav{grid-template-columns:1fr}}
38690
39088
  /* Tampa-inspired publication palette */
@@ -38701,7 +39099,7 @@ body{overflow-x:hidden}.lead-story__body,.lead-support__item,.story-card__body{m
38701
39099
  @media(max-width:620px){main{width:100%}.story-media--lead{height:360px;min-height:0}.lead-story__body,.lead-support,.latest,.feed-story{width:100%;max-width:calc(100vw - 36px)}.feed-story>div{min-width:0}.lead-story h1,.story-card h3,.feed-story h3,.story-card h3 a,.feed-story h3 a{white-space:normal;word-break:break-word;overflow-wrap:anywhere}.lead-story h1{max-width:100%;font-size:40px;line-height:.94}.lead-support__item{width:100%;max-width:100%;grid-template-columns:24px minmax(0,1fr);overflow:hidden}.story-card--support,.story-card--support .story-card__body,.story-card--support h3{width:100%;max-width:calc(100vw - 92px)}.feed-story>div,.feed-story h3,.feed-story p{max-width:calc(100vw - 100px)}}
38702
39100
  @media(max-width:900px){.story-card--panorama{grid-template-columns:1fr}.desk-section__grid--mosaic{grid-template-columns:repeat(2,1fr)}.desk-section__grid--tiles{grid-template-columns:repeat(2,1fr)}}
38703
39101
  @media(max-width:620px){.desk-section__grid--panorama,.desk-section__grid--mosaic,.desk-section__grid--tiles{grid-template-columns:1fr}.story-card--panorama{display:block}.story-card--panorama h3,.story-card--mosaic-lead h3{font-size:34px}.story-card--mosaic-lead{grid-column:auto;grid-row:auto}.desk-section__grid--tiles>.story-card:nth-child(3n+2){margin-top:0}}
38704
- </style></head><body data-theme="${escapeHtml9(config.theme)}" id="top" data-scheduled-renderer="newsroom_publisher_v1">${ticker}${masthead}${navigation}<main>${leadGrid}${latest}${sections}${newsletter}${pressRoom}${trustCenter}</main>${trustFooter}</body></html>`;
39102
+ </style></head><body data-theme="${escapeHtml10(config.theme)}" id="top" data-scheduled-renderer="newsroom_publisher_v1">${ticker}${masthead}${navigation}<main>${leadGrid}${latest}${sections}${newsletter}${pressRoom}${trustCenter}</main>${trustFooter}</body></html>`;
38705
39103
  const bytes = Buffer.byteLength(html);
38706
39104
  const sha2563 = createHash23("sha256").update(html).digest("hex");
38707
39105
  const filename = `${brand.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "newsroom"}-news-site.html`;
@@ -38710,7 +39108,7 @@ body{overflow-x:hidden}.lead-story__body,.lead-support__item,.story-card__body{m
38710
39108
 
38711
39109
  // src/blog-article/render.ts
38712
39110
  import { createHash as createHash24 } from "crypto";
38713
- function escapeHtml10(value) {
39111
+ function escapeHtml11(value) {
38714
39112
  return value.replace(
38715
39113
  /[&<>"']/g,
38716
39114
  (character) => ({
@@ -38724,11 +39122,11 @@ function escapeHtml10(value) {
38724
39122
  }
38725
39123
  function safeHref4(value) {
38726
39124
  const trimmed = value.trim();
38727
- return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ? escapeHtml10(trimmed) : "#";
39125
+ return /^(?:https?:|mailto:|tel:|#|\/)/i.test(trimmed) ? escapeHtml11(trimmed) : "#";
38728
39126
  }
38729
39127
  function formatDate2(value) {
38730
39128
  const date = new Date(value);
38731
- return Number.isNaN(date.getTime()) ? escapeHtml10(value) : new Intl.DateTimeFormat("en", {
39129
+ return Number.isNaN(date.getTime()) ? escapeHtml11(value) : new Intl.DateTimeFormat("en", {
38732
39130
  month: "long",
38733
39131
  day: "numeric",
38734
39132
  year: "numeric"
@@ -38742,15 +39140,15 @@ function jsonForScript(value) {
38742
39140
  }
38743
39141
  function portrait(input) {
38744
39142
  if (input.author.portraitUrl) {
38745
- return `<img class="author-portrait" src="${safeHref4(input.author.portraitUrl)}" alt="${escapeHtml10(input.author.portraitAlt || input.author.name)}">`;
39143
+ return `<img class="author-portrait" src="${safeHref4(input.author.portraitUrl)}" alt="${escapeHtml11(input.author.portraitAlt || input.author.name)}">`;
38746
39144
  }
38747
- return `<span class="author-portrait author-initials" aria-label="${escapeHtml10(input.author.name)}">${escapeHtml10(initials4(input.author.name))}</span>`;
39145
+ return `<span class="author-portrait author-initials" aria-label="${escapeHtml11(input.author.name)}">${escapeHtml11(initials4(input.author.name))}</span>`;
38748
39146
  }
38749
39147
  function sidebarArt(input) {
38750
39148
  if (input.sidebarMedia?.imageUrl) {
38751
- return `<img src="${safeHref4(input.sidebarMedia.imageUrl)}" alt="${escapeHtml10(input.sidebarMedia.imageAlt)}">`;
39149
+ return `<img src="${safeHref4(input.sidebarMedia.imageUrl)}" alt="${escapeHtml11(input.sidebarMedia.imageAlt)}">`;
38752
39150
  }
38753
- return `<svg viewBox="0 0 560 330" role="img" aria-label="${escapeHtml10(input.sidebarMedia?.imageAlt || "Editorial article illustration")}"><defs><linearGradient id="ba-sky" x1="0" x2="1"><stop stop-color="#dbeafe"/><stop offset="1" stop-color="#d1fae5"/></linearGradient></defs><rect width="560" height="330" fill="url(#ba-sky)"/><circle cx="455" cy="72" r="88" fill="#93c5fd" opacity=".35"/><path d="M76 180 280 42l204 138v118H76Z" fill="#fff"/><path d="M52 185 280 28l228 157" fill="none" stroke="#10213d" stroke-width="18" stroke-linecap="round" stroke-linejoin="round"/><rect x="232" y="180" width="96" height="118" rx="8" fill="#bfdbfe"/><circle cx="385" cy="178" r="40" fill="#f8d5b8"/><path d="M335 330v-70c0-39 22-68 50-68s50 29 50 68v70" fill="#2563eb"/><circle cx="458" cy="196" r="34" fill="#8b5e3c"/><path d="M418 330v-64c0-34 18-60 40-60s40 26 40 60v64" fill="#45d5aa"/></svg>`;
39151
+ return `<svg viewBox="0 0 560 330" role="img" aria-label="${escapeHtml11(input.sidebarMedia?.imageAlt || "Editorial article illustration")}"><defs><linearGradient id="ba-sky" x1="0" x2="1"><stop stop-color="#dbeafe"/><stop offset="1" stop-color="#d1fae5"/></linearGradient></defs><rect width="560" height="330" fill="url(#ba-sky)"/><circle cx="455" cy="72" r="88" fill="#93c5fd" opacity=".35"/><path d="M76 180 280 42l204 138v118H76Z" fill="#fff"/><path d="M52 185 280 28l228 157" fill="none" stroke="#10213d" stroke-width="18" stroke-linecap="round" stroke-linejoin="round"/><rect x="232" y="180" width="96" height="118" rx="8" fill="#bfdbfe"/><circle cx="385" cy="178" r="40" fill="#f8d5b8"/><path d="M335 330v-70c0-39 22-68 50-68s50 29 50 68v70" fill="#2563eb"/><circle cx="458" cy="196" r="34" fill="#8b5e3c"/><path d="M418 330v-64c0-34 18-60 40-60s40 26 40 60v64" fill="#45d5aa"/></svg>`;
38754
39152
  }
38755
39153
  function citations(input) {
38756
39154
  const published = new Date(input.publishedAt);
@@ -38779,23 +39177,23 @@ function renderBlogArticleV1(input, config, generatedAt) {
38779
39177
  ...flags.faq && input.faq.length ? [{ id: "faq", title: "Frequently asked questions" }] : []
38780
39178
  ];
38781
39179
  const contributorText = [
38782
- `Written by <a href="${safeHref4(input.author.href || "#author")}">${escapeHtml10(input.author.name)}</a>`,
38783
- input.editor ? `Edited by <a href="${safeHref4(input.editor.href || "#")}">${escapeHtml10(input.editor.name)}</a>` : "",
38784
- input.reviewer ? `Reviewed by <a href="${safeHref4(input.reviewer.href || "#")}">${escapeHtml10(input.reviewer.name)}${input.reviewer.credential ? `, ${escapeHtml10(input.reviewer.credential)}` : ""}</a>` : ""
39180
+ `Written by <a href="${safeHref4(input.author.href || "#author")}">${escapeHtml11(input.author.name)}</a>`,
39181
+ input.editor ? `Edited by <a href="${safeHref4(input.editor.href || "#")}">${escapeHtml11(input.editor.name)}</a>` : "",
39182
+ input.reviewer ? `Reviewed by <a href="${safeHref4(input.reviewer.href || "#")}">${escapeHtml11(input.reviewer.name)}${input.reviewer.credential ? `, ${escapeHtml11(input.reviewer.credential)}` : ""}</a>` : ""
38785
39183
  ].filter(Boolean).join(" \xB7 ");
38786
39184
  const sections = input.sections.map(
38787
- (section3) => `<section id="${escapeHtml10(section3.id)}" class="article-section"><header>${section3.eyebrow ? `<span class="eyebrow">${escapeHtml10(section3.eyebrow)}</span>` : ""}<h2>${escapeHtml10(section3.title)}</h2></header>${section3.paragraphs.map((paragraph) => `<p>${escapeHtml10(paragraph)}</p>`).join("")}${section3.bullets?.length ? `<ul>${section3.bullets.map((item) => `<li>${escapeHtml10(item)}</li>`).join("")}</ul>` : ""}${section3.callout ? `<aside class="callout"><span>Worth noting</span><h3>${escapeHtml10(section3.callout.heading)}</h3><p>${escapeHtml10(section3.callout.body)}</p></aside>` : ""}</section>`
39185
+ (section3) => `<section id="${escapeHtml11(section3.id)}" class="article-section"><header>${section3.eyebrow ? `<span class="eyebrow">${escapeHtml11(section3.eyebrow)}</span>` : ""}<h2>${escapeHtml11(section3.title)}</h2></header>${section3.paragraphs.map((paragraph) => `<p>${escapeHtml11(paragraph)}</p>`).join("")}${section3.bullets?.length ? `<ul>${section3.bullets.map((item) => `<li>${escapeHtml11(item)}</li>`).join("")}</ul>` : ""}${section3.callout ? `<aside class="callout"><span>Worth noting</span><h3>${escapeHtml11(section3.callout.heading)}</h3><p>${escapeHtml11(section3.callout.body)}</p></aside>` : ""}</section>`
38788
39186
  ).join("");
38789
- const faq = flags.faq && input.faq.length ? `<section id="faq" class="faq"><span class="eyebrow">Common questions</span><h2>Frequently asked questions</h2><div>${input.faq.map((item, index) => `<article><h3><button type="button" aria-expanded="false" aria-controls="faq-${index}"><span>${escapeHtml10(item.question)}</span><b aria-hidden="true">+</b></button></h3><p id="faq-${index}" hidden>${escapeHtml10(item.answer)}</p></article>`).join("")}</div></section>` : "";
38790
- const media = flags.sidebarMedia && input.sidebarMedia ? `<figure class="sidebar-media" data-article-media>${sidebarArt(input)}${input.sidebarMedia.caption ? `<figcaption>${escapeHtml10(input.sidebarMedia.caption)}</figcaption>` : ""}</figure>` : "";
38791
- const disclosure = flags.disclosure && input.disclosure ? `<section class="disclosure"><button type="button" aria-expanded="false" aria-controls="disclosure-details"><span>${escapeHtml10(input.disclosure.summary)}</span><b aria-hidden="true">\u2304</b></button><p id="disclosure-details" hidden>${escapeHtml10(input.disclosure.details)}</p></section>` : "";
38792
- const toc = flags.stickyToc ? `<aside class="toc" data-sticky-toc><header><strong>Table of contents</strong><button type="button" aria-expanded="true" aria-controls="toc-links" aria-label="Collapse table of contents">\u2303</button></header><nav id="toc-links" aria-label="Table of contents">${tocItems.map((item, index) => `<a href="#${escapeHtml10(item.id)}"${index === 0 ? ' aria-current="location"' : ""}><i></i><span>${escapeHtml10(item.title)}</span></a>`).join("")}</nav><button class="back-top" type="button">Back to top \u2191</button></aside>` : "";
39187
+ const faq = flags.faq && input.faq.length ? `<section id="faq" class="faq"><span class="eyebrow">Common questions</span><h2>Frequently asked questions</h2><div>${input.faq.map((item, index) => `<article><h3><button type="button" aria-expanded="false" aria-controls="faq-${index}"><span>${escapeHtml11(item.question)}</span><b aria-hidden="true">+</b></button></h3><p id="faq-${index}" hidden>${escapeHtml11(item.answer)}</p></article>`).join("")}</div></section>` : "";
39188
+ const media = flags.sidebarMedia && input.sidebarMedia ? `<figure class="sidebar-media" data-article-media>${sidebarArt(input)}${input.sidebarMedia.caption ? `<figcaption>${escapeHtml11(input.sidebarMedia.caption)}</figcaption>` : ""}</figure>` : "";
39189
+ const disclosure = flags.disclosure && input.disclosure ? `<section class="disclosure"><button type="button" aria-expanded="false" aria-controls="disclosure-details"><span>${escapeHtml11(input.disclosure.summary)}</span><b aria-hidden="true">\u2304</b></button><p id="disclosure-details" hidden>${escapeHtml11(input.disclosure.details)}</p></section>` : "";
39190
+ const toc = flags.stickyToc ? `<aside class="toc" data-sticky-toc><header><strong>Table of contents</strong><button type="button" aria-expanded="true" aria-controls="toc-links" aria-label="Collapse table of contents">\u2303</button></header><nav id="toc-links" aria-label="Table of contents">${tocItems.map((item, index) => `<a href="#${escapeHtml11(item.id)}"${index === 0 ? ' aria-current="location"' : ""}><i></i><span>${escapeHtml11(item.title)}</span></a>`).join("")}</nav><button class="back-top" type="button">Back to top \u2191</button></aside>` : "";
38793
39191
  const actions = flags.citation || flags.share ? `<div class="article-actions">${flags.citation ? '<button type="button" data-cite aria-haspopup="dialog">\u270E <span>Cite us</span></button>' : ""}${flags.share ? '<button type="button" data-share>\u21E7 <span>Share this article</span></button>' : ""}</div><p class="action-status" aria-live="polite"></p>` : "";
38794
- const author = flags.authorCard ? `<section id="author" class="author-card">${actions}<div class="author-grid">${portrait(input)}<div><span>Written by</span><h2>${input.author.href ? `<a href="${safeHref4(input.author.href)}">${escapeHtml10(input.author.name)}</a>` : escapeHtml10(input.author.name)}</h2><p>${escapeHtml10(input.author.role)}</p>${input.author.socialLinks.length || input.author.email ? `<nav aria-label="Author links">${input.author.socialLinks.map((link) => `<a href="${safeHref4(link.href)}">${escapeHtml10(link.label)}</a>`).join("")}${input.author.email ? `<a href="mailto:${escapeHtml10(input.author.email)}">Email</a>` : ""}</nav>` : ""}</div>${input.author.href ? `<a class="author-more" href="${safeHref4(input.author.href)}">Read more from ${escapeHtml10(input.author.name.split(/\s+/)[0] || input.author.name)}</a>` : ""}</div><p class="author-bio">${escapeHtml10(input.author.bio)}</p></section>` : actions;
38795
- const citationDialog = flags.citation ? `<dialog id="citation-dialog"><div><button class="dialog-close" type="button" aria-label="Close citation guide">\xD7</button><h2>Quick citation guide</h2><p>Select a citation to automatically copy it to your clipboard.</p><section>${Object.keys(citationValues).map((style) => `<button type="button" data-citation="${style}"><strong>${style}:</strong> ${escapeHtml10(citationValues[style])}</button>`).join("")}</section><p class="citation-status" aria-live="polite"></p></div></dialog>` : "";
38796
- const html = `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex,nofollow"><meta name="description" content="${escapeHtml10(input.dek || input.keyTakeaways[0])}"><title>${escapeHtml10(input.title)} \xB7 ${escapeHtml10(brand)}</title><style>
39192
+ const author = flags.authorCard ? `<section id="author" class="author-card">${actions}<div class="author-grid">${portrait(input)}<div><span>Written by</span><h2>${input.author.href ? `<a href="${safeHref4(input.author.href)}">${escapeHtml11(input.author.name)}</a>` : escapeHtml11(input.author.name)}</h2><p>${escapeHtml11(input.author.role)}</p>${input.author.socialLinks.length || input.author.email ? `<nav aria-label="Author links">${input.author.socialLinks.map((link) => `<a href="${safeHref4(link.href)}">${escapeHtml11(link.label)}</a>`).join("")}${input.author.email ? `<a href="mailto:${escapeHtml11(input.author.email)}">Email</a>` : ""}</nav>` : ""}</div>${input.author.href ? `<a class="author-more" href="${safeHref4(input.author.href)}">Read more from ${escapeHtml11(input.author.name.split(/\s+/)[0] || input.author.name)}</a>` : ""}</div><p class="author-bio">${escapeHtml11(input.author.bio)}</p></section>` : actions;
39193
+ const citationDialog = flags.citation ? `<dialog id="citation-dialog"><div><button class="dialog-close" type="button" aria-label="Close citation guide">\xD7</button><h2>Quick citation guide</h2><p>Select a citation to automatically copy it to your clipboard.</p><section>${Object.keys(citationValues).map((style) => `<button type="button" data-citation="${style}"><strong>${style}:</strong> ${escapeHtml11(citationValues[style])}</button>`).join("")}</section><p class="citation-status" aria-live="polite"></p></div></dialog>` : "";
39194
+ const html = `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex,nofollow"><meta name="description" content="${escapeHtml11(input.dek || input.keyTakeaways[0])}"><title>${escapeHtml11(input.title)} \xB7 ${escapeHtml11(brand)}</title><style>
38797
39195
  :root{--ink:#10213d;--ink2:#1c355a;--blue:#2563eb;--blue2:#1749b6;--mint:#45d5aa;--paper:#f7f5f0;--line:#dce4ef;--card:#fff;--body:#475569;--serif:Iowan Old Style,Palatino Linotype,Palatino,Georgia,serif;--sans:Inter,Avenir Next,ui-sans-serif,system-ui,sans-serif}body[data-theme="slate"]{--ink:#1e293b;--ink2:#334155;--blue:#475569;--blue2:#1e293b;--mint:#94a3b8;--paper:#f8fafc}body[data-theme="forest"]{--ink:#12352e;--ink2:#23584c;--blue:#147d64;--blue2:#0c5b48;--mint:#79d8bd;--paper:#f4f8f3}*{box-sizing:border-box}html{scroll-behavior:smooth;background:var(--paper)}body{margin:0;color:#252a33;background:var(--paper);font-family:var(--sans);line-height:1.6}a{color:inherit}button{font:inherit}button:focus-visible,a:focus-visible{outline:3px solid var(--mint);outline-offset:3px}.progress{position:fixed;z-index:50;top:0;left:0;height:4px;width:0;background:var(--mint)}.hero{position:relative;overflow:hidden;color:#fff;background:var(--ink)}.hero:after{position:absolute;right:-110px;top:-150px;width:420px;height:420px;border:1px solid #ffffff1a;border-radius:50%;content:""}.hero-inner{position:relative;z-index:1;max-width:1240px;margin:auto;padding:58px 42px 126px}.breadcrumb{display:flex;gap:8px;margin-bottom:34px;color:#dbeafecc;font-size:14px}.eyebrow{display:block;color:var(--blue);font-size:12px;font-weight:800;letter-spacing:.16em;text-transform:uppercase}.hero .eyebrow{color:var(--mint)}h1,h2,h3,p{margin-top:0}.hero h1{max-width:1000px;margin:14px 0 24px;font:700 clamp(44px,6vw,78px)/.98 var(--serif);letter-spacing:-.035em}.hero .dek{max-width:780px;color:#dbeafe;font-size:20px}.contributors{margin-top:30px;color:#eff6ff;font-size:14px}.contributors a{font-weight:800}.meta{display:flex;flex-wrap:wrap;gap:12px;margin-top:6px;color:#dbeafecc}.layout{position:relative;z-index:2;display:grid;grid-template-columns:minmax(0,760px) 290px;gap:64px;max-width:1240px;margin:-78px auto 0;padding:0 42px 80px}.main{min-width:0}.takeaways{padding:38px 44px;border-radius:24px;background:#fff;box-shadow:0 24px 70px #10213d24}.takeaways h2{margin:5px 0 20px;font:700 32px/1.1 var(--serif);color:var(--ink)}.takeaways ul{display:grid;gap:16px;margin:0;padding:0;list-style:none}.takeaways li{position:relative;padding-left:26px;color:var(--body);font-size:17px}.takeaways li:before{position:absolute;left:2px;top:.7em;width:8px;height:8px;border-radius:50%;background:var(--blue);content:""}.intro{padding:40px 0 4px}.intro p,.article-section>p{margin-bottom:22px;color:var(--body);font:400 18px/1.75 var(--sans)}.article-section{scroll-margin-top:28px;padding-top:45px}.article-section h2,.faq h2{margin:6px 0 20px;color:var(--ink);font:700 38px/1.08 var(--serif);letter-spacing:-.02em}.article-section ul{display:grid;gap:10px;margin:22px 0;padding-left:24px;color:var(--body);font-size:17px}.article-section li::marker{color:var(--blue)}.callout{margin:34px 0;padding:24px 28px;border-left:4px solid var(--blue);border-radius:0 16px 16px 0;background:#fff}.callout span{color:var(--blue);font-size:11px;font-weight:800;letter-spacing:.13em;text-transform:uppercase}.callout h3{margin:5px 0 8px;color:var(--ink);font:700 24px/1.15 var(--serif)}.callout p{margin:0;color:var(--body)}.rail{padding-top:0}.sidebar-media{overflow:hidden;margin:0 0 18px;border:1px solid #dbeafe;border-radius:16px;background:#fff}.sidebar-media img,.sidebar-media svg{display:block;width:100%;aspect-ratio:16/9;object-fit:cover}.sidebar-media figcaption{padding:10px 13px;color:#64748b;font-size:11px}.disclosure{margin-bottom:28px;border-top:1px solid #dbeafe;border-bottom:1px solid #dbeafe}.disclosure button{display:flex;width:100%;align-items:center;justify-content:space-between;gap:14px;padding:15px 0;border:0;color:#64748b;background:transparent;text-align:left;font-size:12px;cursor:pointer}.disclosure button b{color:var(--blue);font-size:18px;transition:transform .2s}.disclosure button[aria-expanded="true"] b{transform:rotate(180deg)}.disclosure p{padding:0 0 16px;margin:0;color:#64748b;font-size:12px}.toc{position:sticky;top:30px;padding:22px;border:1px solid var(--line);border-radius:16px;background:#fff;box-shadow:0 2px 5px #10213d12}.toc header{display:flex;align-items:center;justify-content:space-between}.toc header strong{color:var(--ink);font:700 21px/1 var(--serif)}.toc header button{width:34px;height:34px;border:0;border-radius:50%;color:var(--blue);background:transparent;cursor:pointer}.toc nav{display:grid;margin-top:14px}.toc nav a{display:flex;align-items:flex-start;gap:11px;padding:8px 0;color:#64748b;text-decoration:none;font-size:13px;line-height:1.35}.toc nav i{width:8px;height:8px;margin-top:5px;border:2px solid #bfdbfe;border-radius:50%}.toc nav a[aria-current="location"]{color:var(--ink);font-weight:800}.toc nav a[aria-current="location"] i{border-color:var(--blue);background:var(--blue)}.back-top{width:100%;margin-top:18px;padding:16px 0 0;border:0;border-top:1px solid var(--line);color:var(--blue);background:transparent;text-align:right;font-size:13px;font-weight:800;cursor:pointer}.faq{scroll-margin-top:28px;padding-top:64px}.faq>div{border-top:1px solid var(--line);border-bottom:1px solid var(--line)}.faq article+article{border-top:1px solid var(--line)}.faq h3{margin:0}.faq h3 button{display:flex;width:100%;align-items:center;justify-content:space-between;gap:18px;padding:19px 0;border:0;color:var(--ink);background:transparent;text-align:left;font-weight:800;cursor:pointer}.faq h3 b{color:var(--blue);font-size:22px}.faq article>p{padding:0 0 20px;margin:0;color:var(--body);font-size:16px}.author-card{margin-top:64px;padding:32px 36px;border-radius:18px;background:#fff}.article-actions{display:flex;flex-wrap:wrap;justify-content:space-between;gap:14px}.article-actions button{display:inline-flex;min-height:46px;align-items:center;justify-content:center;gap:8px;padding:8px 18px;border:2px solid var(--blue);border-radius:999px;color:var(--ink);background:#fff;font-weight:800;cursor:pointer}.article-actions button:hover{color:#fff;background:var(--blue)}.action-status{min-height:20px;margin:8px 0 0;color:var(--blue);text-align:right;font-size:13px;font-weight:700}.author-grid{display:grid;grid-template-columns:auto 1fr auto;gap:22px;align-items:center;margin-top:24px}.author-portrait{width:88px;height:88px;border-radius:50%;object-fit:cover}.author-initials{display:grid;place-items:center;color:var(--ink);background:#fecdd3;font-size:22px;font-weight:900}.author-grid span{color:#64748b;font-size:13px}.author-grid h2{margin:2px 0;color:var(--ink);font:700 27px/1 var(--serif)}.author-grid h2 a{text-decoration:none}.author-grid p{margin:8px 0;color:#64748b;font-size:14px}.author-grid nav{display:flex;flex-wrap:wrap;gap:14px}.author-grid nav a{color:#64748b;font-size:12px}.author-more{display:inline-flex;min-height:48px;align-items:center;justify-content:center;padding:10px 24px;border:2px solid var(--blue);color:var(--blue);text-align:center;text-decoration:none;font-size:13px;font-weight:800}.author-bio{margin:24px 0 0!important;padding-top:20px;border-top:1px solid var(--line);color:var(--body);font-size:16px}dialog{width:min(720px,calc(100% - 30px));max-height:calc(100dvh - 30px);padding:0;border:0;border-radius:18px;color:var(--ink);background:#fff;box-shadow:0 24px 70px #10213d38}dialog::backdrop{background:#0f172a7a;backdrop-filter:blur(2px)}dialog>div{position:relative;padding:30px}dialog h2{margin:0 50px 2px 0;font:700 30px/1.1 var(--serif)}dialog>div>p{color:#64748b}.dialog-close{position:absolute;top:13px;right:13px;width:44px;height:44px;border:0;border-radius:50%;color:var(--blue);background:transparent;font-size:29px;cursor:pointer}dialog section{border-top:1px solid var(--line)}dialog section button{display:block;width:100%;padding:17px 5px;border:0;border-bottom:1px solid var(--line);color:var(--body);background:#fff;text-align:left;line-height:1.65;cursor:pointer}.citation-status{min-height:22px;margin:14px 0 0!important;color:var(--blue)!important;font-size:13px;font-weight:800}.generated{max-width:1156px;margin:-52px auto 50px;padding:0 42px;color:#94a3b8;font-size:11px}@media(max-width:900px){.layout{display:block}.rail{display:none}.hero-inner{padding-bottom:116px}}@media(max-width:620px){.hero-inner{padding:36px 20px 104px}.hero h1{font-size:46px}.hero .dek{font-size:17px}.layout{margin-top:-70px;padding:0 16px 54px}.takeaways{padding:28px 24px}.article-section h2,.faq h2{font-size:32px}.author-card{padding:24px}.article-actions{display:grid;justify-content:start}.author-grid{grid-template-columns:1fr;gap:12px}.author-more{width:100%}dialog>div{padding:24px}.generated{padding:0 20px}}
38798
- </style></head><body data-theme="${escapeHtml10(config.theme)}" data-scheduled-renderer="blog_article_v1"><div class="progress" aria-hidden="true"></div><header class="hero"><div class="hero-inner"><nav class="breadcrumb" aria-label="Breadcrumb"><a href="${safeHref4(input.canonicalUrl)}">${escapeHtml10(input.category)}</a><span>/</span><span>Article</span></nav><span class="eyebrow">${escapeHtml10(input.eyebrow)}</span><h1>${escapeHtml10(input.title)}</h1>${input.dek ? `<p class="dek">${escapeHtml10(input.dek)}</p>` : ""}<div class="contributors">${contributorText}<div class="meta"><time datetime="${escapeHtml10(articleDate)}">Updated ${formatDate2(articleDate)}</time><span>\u2022</span><span>${input.readTimeMinutes} min read</span>${input.reviewer ? "<span>\u2022</span><strong>Expert reviewed</strong>" : ""}</div></div></div></header><main class="layout"><article class="main"><section class="takeaways"><span class="eyebrow">The short answer</span><h2>Key takeaways</h2><ul>${input.keyTakeaways.map((item) => `<li>${escapeHtml10(item)}</li>`).join("")}</ul></section><section class="intro">${input.introduction.map((paragraph) => `<p>${escapeHtml10(paragraph)}</p>`).join("")}</section>${sections}${faq}${author}</article><div class="rail">${media}${disclosure}${toc}</div></main>${config.showGeneratedAt ? `<p class="generated">Rendered ${formatDate2(generatedAtIso)} by MCP Scraper.</p>` : ""}${citationDialog}<script>(()=>{const citations=${jsonForScript(citationValues)};const canonical=${jsonForScript(input.canonicalUrl)};const title=${jsonForScript(input.title)};const progress=document.querySelector('.progress');const tocLinks=[...document.querySelectorAll('.toc nav a')];const targets=tocLinks.map(link=>document.querySelector(link.hash)).filter(Boolean);const update=()=>{const max=document.documentElement.scrollHeight-innerHeight;if(progress)progress.style.width=(max>0?scrollY/max*100:0)+'%';let active=targets[0]?.id;for(const target of targets){if(target.getBoundingClientRect().top<=innerHeight*.55)active=target.id}tocLinks.forEach(link=>link.toggleAttribute('aria-current',link.hash==='#'+active));tocLinks.forEach(link=>{if(link.hash==='#'+active)link.setAttribute('aria-current','location');else link.removeAttribute('aria-current')})};addEventListener('scroll',update,{passive:true});addEventListener('resize',update);update();document.querySelectorAll('.faq h3 button').forEach(button=>button.addEventListener('click',()=>{const panel=document.getElementById(button.getAttribute('aria-controls'));const open=button.getAttribute('aria-expanded')==='true';button.setAttribute('aria-expanded',String(!open));panel.hidden=open;button.querySelector('b').textContent=open?'+':'\u2212'}));const disclosure=document.querySelector('.disclosure button');disclosure?.addEventListener('click',()=>{const panel=document.getElementById(disclosure.getAttribute('aria-controls'));const open=disclosure.getAttribute('aria-expanded')==='true';disclosure.setAttribute('aria-expanded',String(!open));panel.hidden=open});const tocToggle=document.querySelector('.toc header button');tocToggle?.addEventListener('click',()=>{const nav=document.getElementById('toc-links');const open=tocToggle.getAttribute('aria-expanded')==='true';tocToggle.setAttribute('aria-expanded',String(!open));nav.hidden=open;tocToggle.textContent=open?'\u2304':'\u2303'});document.querySelector('.back-top')?.addEventListener('click',()=>scrollTo({top:0,behavior:'smooth'}));const copy=async text=>{try{await navigator.clipboard.writeText(text)}catch{const area=document.createElement('textarea');area.value=text;area.style.position='fixed';area.style.opacity='0';document.body.append(area);area.select();document.execCommand('copy');area.remove()}};const dialog=document.getElementById('citation-dialog');document.querySelector('[data-cite]')?.addEventListener('click',()=>dialog.showModal());document.querySelector('.dialog-close')?.addEventListener('click',()=>dialog.close());dialog?.addEventListener('click',event=>{if(event.target===dialog)dialog.close()});document.querySelectorAll('[data-citation]').forEach(button=>button.addEventListener('click',async()=>{const style=button.dataset.citation;await copy(citations[style]);document.querySelector('.citation-status').textContent=style+' citation copied to clipboard.'}));document.querySelector('[data-share]')?.addEventListener('click',async()=>{const status=document.querySelector('.action-status');if(navigator.share){try{await navigator.share({title,url:canonical});status.textContent='Sharing options opened.';return}catch(error){if(error.name==='AbortError')return}}await copy(canonical);status.textContent='Article link copied to clipboard.'})})()</script></body></html>`;
39196
+ </style></head><body data-theme="${escapeHtml11(config.theme)}" data-scheduled-renderer="blog_article_v1"><div class="progress" aria-hidden="true"></div><header class="hero"><div class="hero-inner"><nav class="breadcrumb" aria-label="Breadcrumb"><a href="${safeHref4(input.canonicalUrl)}">${escapeHtml11(input.category)}</a><span>/</span><span>Article</span></nav><span class="eyebrow">${escapeHtml11(input.eyebrow)}</span><h1>${escapeHtml11(input.title)}</h1>${input.dek ? `<p class="dek">${escapeHtml11(input.dek)}</p>` : ""}<div class="contributors">${contributorText}<div class="meta"><time datetime="${escapeHtml11(articleDate)}">Updated ${formatDate2(articleDate)}</time><span>\u2022</span><span>${input.readTimeMinutes} min read</span>${input.reviewer ? "<span>\u2022</span><strong>Expert reviewed</strong>" : ""}</div></div></div></header><main class="layout"><article class="main"><section class="takeaways"><span class="eyebrow">The short answer</span><h2>Key takeaways</h2><ul>${input.keyTakeaways.map((item) => `<li>${escapeHtml11(item)}</li>`).join("")}</ul></section><section class="intro">${input.introduction.map((paragraph) => `<p>${escapeHtml11(paragraph)}</p>`).join("")}</section>${sections}${faq}${author}</article><div class="rail">${media}${disclosure}${toc}</div></main>${config.showGeneratedAt ? `<p class="generated">Rendered ${formatDate2(generatedAtIso)} by MCP Scraper.</p>` : ""}${citationDialog}<script>(()=>{const citations=${jsonForScript(citationValues)};const canonical=${jsonForScript(input.canonicalUrl)};const title=${jsonForScript(input.title)};const progress=document.querySelector('.progress');const tocLinks=[...document.querySelectorAll('.toc nav a')];const targets=tocLinks.map(link=>document.querySelector(link.hash)).filter(Boolean);const update=()=>{const max=document.documentElement.scrollHeight-innerHeight;if(progress)progress.style.width=(max>0?scrollY/max*100:0)+'%';let active=targets[0]?.id;for(const target of targets){if(target.getBoundingClientRect().top<=innerHeight*.55)active=target.id}tocLinks.forEach(link=>link.toggleAttribute('aria-current',link.hash==='#'+active));tocLinks.forEach(link=>{if(link.hash==='#'+active)link.setAttribute('aria-current','location');else link.removeAttribute('aria-current')})};addEventListener('scroll',update,{passive:true});addEventListener('resize',update);update();document.querySelectorAll('.faq h3 button').forEach(button=>button.addEventListener('click',()=>{const panel=document.getElementById(button.getAttribute('aria-controls'));const open=button.getAttribute('aria-expanded')==='true';button.setAttribute('aria-expanded',String(!open));panel.hidden=open;button.querySelector('b').textContent=open?'+':'\u2212'}));const disclosure=document.querySelector('.disclosure button');disclosure?.addEventListener('click',()=>{const panel=document.getElementById(disclosure.getAttribute('aria-controls'));const open=disclosure.getAttribute('aria-expanded')==='true';disclosure.setAttribute('aria-expanded',String(!open));panel.hidden=open});const tocToggle=document.querySelector('.toc header button');tocToggle?.addEventListener('click',()=>{const nav=document.getElementById('toc-links');const open=tocToggle.getAttribute('aria-expanded')==='true';tocToggle.setAttribute('aria-expanded',String(!open));nav.hidden=open;tocToggle.textContent=open?'\u2304':'\u2303'});document.querySelector('.back-top')?.addEventListener('click',()=>scrollTo({top:0,behavior:'smooth'}));const copy=async text=>{try{await navigator.clipboard.writeText(text)}catch{const area=document.createElement('textarea');area.value=text;area.style.position='fixed';area.style.opacity='0';document.body.append(area);area.select();document.execCommand('copy');area.remove()}};const dialog=document.getElementById('citation-dialog');document.querySelector('[data-cite]')?.addEventListener('click',()=>dialog.showModal());document.querySelector('.dialog-close')?.addEventListener('click',()=>dialog.close());dialog?.addEventListener('click',event=>{if(event.target===dialog)dialog.close()});document.querySelectorAll('[data-citation]').forEach(button=>button.addEventListener('click',async()=>{const style=button.dataset.citation;await copy(citations[style]);document.querySelector('.citation-status').textContent=style+' citation copied to clipboard.'}));document.querySelector('[data-share]')?.addEventListener('click',async()=>{const status=document.querySelector('.action-status');if(navigator.share){try{await navigator.share({title,url:canonical});status.textContent='Sharing options opened.';return}catch(error){if(error.name==='AbortError')return}}await copy(canonical);status.textContent='Article link copied to clipboard.'})})()</script></body></html>`;
38799
39197
  const bytes = Buffer.byteLength(html);
38800
39198
  const sha2563 = createHash24("sha256").update(html).digest("hex");
38801
39199
  return {
@@ -41395,7 +41793,7 @@ async function getFreeCreditBreakdown(userId) {
41395
41793
  }
41396
41794
 
41397
41795
  // src/api/memory-db.ts
41398
- import { neon } from "@neondatabase/serverless";
41796
+ import { neon as neon2 } from "@neondatabase/serverless";
41399
41797
 
41400
41798
  // src/api/memory-universe.ts
41401
41799
  var SEP = "\n";
@@ -41492,7 +41890,7 @@ function sql() {
41492
41890
  if (_sql) return _sql;
41493
41891
  const url = process.env.MEMORY_DATABASE_URL?.trim();
41494
41892
  if (!url) throw new Error("MEMORY_DATABASE_URL is not set (paa-crawler needs mcp-memory Neon URL for reads)");
41495
- _sql = neon(url);
41893
+ _sql = neon2(url);
41496
41894
  return _sql;
41497
41895
  }
41498
41896
  function physicalVault(owner, vault) {
@@ -47191,11 +47589,11 @@ app.get("/cron/tick", async (c) => {
47191
47589
  return c.json({ error: "Unauthorized" }, 401);
47192
47590
  }
47193
47591
  const startedAt = Date.now();
47194
- const { drainQueue } = await import("./worker-S2WXELUC.js");
47592
+ const { drainQueue } = await import("./worker-QFSOMF2N.js");
47195
47593
  const budget = { maxJobs: 10, deadlineMs: startedAt + CRON_TICK_DRAIN_BUDGET_MS };
47196
47594
  const origin = `${new URL(c.req.url).protocol}//${new URL(c.req.url).host}`;
47197
47595
  const unfinished = [];
47198
- const [results, sweepResult, reapResult, expiredResult, blobCleanup, connectedDataArtifactCleanup, connectedAccountBilling, directoryWorkflowDispatch, directoryWorkflowReconciliation, directoryArtifactCleanup, siteExtractArtifactCleanup, siteExtractRedispatch, siteExtractReconciliation, paaHarvestRedispatch, paaHarvestReconciliation, localSourcebookRedispatch, analyticsRollup, analyticsFormDelivery, workflowDispatchResult, scheduledRunReconciliation, retentionSweep] = await Promise.all([
47596
+ const [results, sweepResult, reapResult, expiredResult, blobCleanup, connectedDataArtifactCleanup, connectedAccountBilling, directoryWorkflowDispatch, directoryWorkflowReconciliation, directoryArtifactCleanup, siteExtractArtifactCleanup, siteExtractRedispatch, siteExtractReconciliation, paaHarvestRedispatch, paaHarvestReconciliation, commonsEmbeddingDrain, localSourcebookRedispatch, analyticsRollup, analyticsFormDelivery, workflowDispatchResult, scheduledRunReconciliation, retentionSweep] = await Promise.all([
47199
47597
  settleWithinTickBudget("drainQueue", unfinished, drainQueue(budget), []),
47200
47598
  settleWithinTickBudget("monthlyRefreshSweep", unfinished, runMonthlyRefreshSweep(), { status: "skipped_deadline" }),
47201
47599
  settleWithinTickBudget("reapBrowserSessions", unfinished, reapIdleBrowserSessions(120), { reaped: 0 }),
@@ -47212,6 +47610,7 @@ app.get("/cron/tick", async (c) => {
47212
47610
  settleWithinTickBudget("siteExtractReconcile", unfinished, reconcileSiteExtractSettlements(10), { checked: 0, settled: 0, failed: 0 }),
47213
47611
  settleWithinTickBudget("paaRedispatch", unfinished, redispatchPendingPaaHarvests(10), { checked: 0, dispatched: 0, failed: 0 }),
47214
47612
  settleWithinTickBudget("paaReconcile", unfinished, reconcilePaaHarvestSettlements(10), { checked: 0, staleFailed: 0, settled: 0, failed: 0 }),
47613
+ settleWithinTickBudget("commonsEmbeddingDrain", unfinished, embedQueuedCommonsDocuments(50), { claimed: 0, embedded: 0, failed: 0, remaining: 0 }),
47215
47614
  settleWithinTickBudget("localSourcebookRedispatch", unfinished, redispatchQueuedLocalSourcebookAcquisitions(5), { checked: 0, dispatched: 0, failed: 0 }),
47216
47615
  settleWithinTickBudget("analyticsRollup", unfinished, refreshAnalyticsDailyRollupsIfDue(), { status: "failed", rows: 0 }),
47217
47616
  settleWithinTickBudget("analyticsForms", unfinished, deliverPendingAnalyticsForms(10), { claimed: 0, delivered: 0, deferred: 0 }),
@@ -47242,6 +47641,7 @@ app.get("/cron/tick", async (c) => {
47242
47641
  siteExtractReconciliation,
47243
47642
  paaHarvestRedispatch,
47244
47643
  paaHarvestReconciliation,
47644
+ commonsEmbeddingDrain,
47245
47645
  localSourcebookRedispatch,
47246
47646
  analyticsRollup,
47247
47647
  analyticsFormDelivery,
@@ -47261,8 +47661,8 @@ app.post("/api/internal/extract-refinalize/:id", async (c) => {
47261
47661
  finishExtractJob: finishExtractJob2,
47262
47662
  terminalExtractJobStatus: terminalExtractJobStatus2,
47263
47663
  extractJobLimitInfo: extractJobLimitInfo2
47264
- } = await import("./site-extract-repository-CFMSWAVL.js");
47265
- const { assembleExtractArtifacts } = await import("./extract-bundle-H7JEELY7.js");
47664
+ } = await import("./site-extract-repository-XAA2FVDN.js");
47665
+ const { assembleExtractArtifacts } = await import("./extract-bundle-XRRN6NAZ.js");
47266
47666
  const existing = await getExtractJob2(jobId2);
47267
47667
  if (!existing) return c.json({ error: "job not found" }, 404);
47268
47668
  if (existing.status !== "failed") {
@@ -47289,7 +47689,7 @@ app.post("/api/internal/extract-refinalize/:id", async (c) => {
47289
47689
  if (!updated) return c.json({ error: "job state changed during re-finalization" }, 409);
47290
47690
  let settlement = "already_settled_or_refunded";
47291
47691
  if (job.billedMc == null && job.userId != null) {
47292
- const { settleExtractJob: settleExtractJob3, countSuccessfulPages: countSuccessfulPages2 } = await import("./site-extract-repository-CFMSWAVL.js");
47692
+ const { settleExtractJob: settleExtractJob3, countSuccessfulPages: countSuccessfulPages2 } = await import("./site-extract-repository-XAA2FVDN.js");
47293
47693
  const heldMc = Number(job.options.heldMc ?? 0);
47294
47694
  const successful = await countSuccessfulPages2(jobId2);
47295
47695
  const usedMc = Math.min(successful * MC_COSTS.page_scrape, heldMc);
@@ -47474,4 +47874,4 @@ app.get("/blog/:slug/", (c) => {
47474
47874
  export {
47475
47875
  app
47476
47876
  };
47477
- //# sourceMappingURL=server-EP2SK2ID.js.map
47877
+ //# sourceMappingURL=server-IRKNU6LO.js.map