@consilioweb/payload-seo-analyzer 1.12.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.cjs CHANGED
@@ -1068,6 +1068,8 @@ var fr = {
1068
1068
  bulkOptimizeMeta: "Optimiser m\xE9ta (IA)",
1069
1069
  bulkOptimizing: "Analyse\u2026",
1070
1070
  bulkConfirm: "Confirmer ?",
1071
+ optimizeSite: "Optimiser le site",
1072
+ optimizeSiteHint: "Cible automatiquement les pages \xE0 probl\xE8me (m\xE9ta manquante, sans mot-cl\xE9, score faible) \u2192 aper\xE7u \u2192 appliquer",
1071
1073
  bulkPreviewTitle: "Corrections m\xE9ta propos\xE9es",
1072
1074
  bulkApply: "Appliquer",
1073
1075
  bulkApplying: "Application\u2026",
@@ -1670,6 +1672,8 @@ var en = {
1670
1672
  bulkOptimizeMeta: "Optimize meta (AI)",
1671
1673
  bulkOptimizing: "Analyzing\u2026",
1672
1674
  bulkConfirm: "Confirm?",
1675
+ optimizeSite: "Optimize site",
1676
+ optimizeSiteHint: "Auto-targets pages that need work (missing meta, no keyword, low score) \u2192 preview \u2192 apply",
1673
1677
  bulkPreviewTitle: "Proposed meta corrections",
1674
1678
  bulkApply: "Apply",
1675
1679
  bulkApplying: "Applying\u2026",
@@ -9544,9 +9548,9 @@ function SeoView() {
9544
9548
  },
9545
9549
  [selectedIds, fetchAudit]
9546
9550
  );
9547
- const handleBulkOptimizeMeta = React4.useCallback(async () => {
9548
- const ids = Array.from(selectedIds).filter((k) => !k.startsWith("global:"));
9549
- if (ids.length === 0) return;
9551
+ const runBulkPreview = React4.useCallback(async (ids) => {
9552
+ const clean = ids.filter((k) => !k.startsWith("global:"));
9553
+ if (clean.length === 0) return;
9550
9554
  setBulkOptimizing(true);
9551
9555
  setBulkPreview(null);
9552
9556
  try {
@@ -9554,7 +9558,7 @@ function SeoView() {
9554
9558
  method: "POST",
9555
9559
  headers: { "Content-Type": "application/json" },
9556
9560
  credentials: "include",
9557
- body: JSON.stringify({ ids, apply: false, limit: 100 })
9561
+ body: JSON.stringify({ ids: clean, apply: false, limit: 100 })
9558
9562
  });
9559
9563
  if (res.ok) {
9560
9564
  const data = await res.json();
@@ -9564,7 +9568,15 @@ function SeoView() {
9564
9568
  } catch {
9565
9569
  }
9566
9570
  setBulkOptimizing(false);
9567
- }, [selectedIds]);
9571
+ }, []);
9572
+ const handleBulkOptimizeMeta = React4.useCallback(
9573
+ () => runBulkPreview(Array.from(selectedIds)),
9574
+ [selectedIds, runBulkPreview]
9575
+ );
9576
+ const handleOptimizeSite = React4.useCallback(() => {
9577
+ const targets = items.filter((i) => !i.collection.startsWith("global:")).filter((i) => !i.metaTitle || !i.metaDescription || !i.focusKeyword || i.score < 70).slice(0, 100).map(itemKey);
9578
+ runBulkPreview(targets);
9579
+ }, [items, runBulkPreview]);
9568
9580
  const handleBulkApplyPreview = React4.useCallback(async () => {
9569
9581
  if (!bulkPreview || bulkPreview.results.length === 0) return;
9570
9582
  setBulkApplying(true);
@@ -9931,6 +9943,16 @@ function SeoView() {
9931
9943
  ] })
9932
9944
  ] }),
9933
9945
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: 8 }, children: [
9946
+ /* @__PURE__ */ jsxRuntime.jsx(
9947
+ "button",
9948
+ {
9949
+ onClick: handleOptimizeSite,
9950
+ disabled: bulkOptimizing || items.length === 0,
9951
+ title: t.seoView.optimizeSiteHint,
9952
+ style: { ...btnBase, backgroundColor: "#7c3aed", color: "#fff", opacity: bulkOptimizing || items.length === 0 ? 0.6 : 1 },
9953
+ children: bulkOptimizing ? t.seoView.bulkOptimizing : `\u2728 ${t.seoView.optimizeSite}`
9954
+ }
9955
+ ),
9934
9956
  /* @__PURE__ */ jsxRuntime.jsxs(
9935
9957
  "button",
9936
9958
  {
@@ -17355,9 +17377,210 @@ var C7 = {
17355
17377
  green: "#22c55e",
17356
17378
  red: "#ef4444",
17357
17379
  amber: "#f59e0b",
17358
- blue: "#3b82f6"
17380
+ violet: "#7c3aed"
17359
17381
  };
17360
17382
  var S4 = {
17383
+ fr: {
17384
+ title: "Opportunit\xE9s CTR (faible clic / bonne position)",
17385
+ subtitle: "Pages bien positionn\xE9es mais peu cliqu\xE9es (m\xE9ta peu attractive). Donn\xE9es Google Search Console \u2192 r\xE9\xE9criture m\xE9ta cibl\xE9e.",
17386
+ needGsc: "Connectez Google Search Console ci-dessus pour activer les opportunit\xE9s CTR.",
17387
+ none: "Aucune opportunit\xE9 d\xE9tect\xE9e sur la p\xE9riode. \u{1F389}",
17388
+ loading: "Analyse des donn\xE9es GSC\u2026",
17389
+ page: "Page",
17390
+ pos: "Pos.",
17391
+ ctr: "CTR",
17392
+ expected: "attendu",
17393
+ potential: "Clics/mois potentiels",
17394
+ optimize: "Optimiser",
17395
+ optimizing: "\u2026",
17396
+ apply: "Appliquer",
17397
+ applied: "Appliqu\xE9 \u2713",
17398
+ noKey: "Cl\xE9 API Claude requise (ANTHROPIC_API_KEY).",
17399
+ open: "Ouvrir",
17400
+ refresh: "Rafra\xEEchir"
17401
+ },
17402
+ en: {
17403
+ title: "CTR opportunities (low clicks / good rank)",
17404
+ subtitle: "Pages that rank well but get few clicks (weak meta). Google Search Console data \u2192 targeted meta rewrite.",
17405
+ needGsc: "Connect Google Search Console above to enable CTR opportunities.",
17406
+ none: "No opportunities for the period. \u{1F389}",
17407
+ loading: "Analyzing GSC data\u2026",
17408
+ page: "Page",
17409
+ pos: "Pos.",
17410
+ ctr: "CTR",
17411
+ expected: "expected",
17412
+ potential: "Potential clicks/mo",
17413
+ optimize: "Optimize",
17414
+ optimizing: "\u2026",
17415
+ apply: "Apply",
17416
+ applied: "Applied \u2713",
17417
+ noKey: "Claude API key required (ANTHROPIC_API_KEY).",
17418
+ open: "Open",
17419
+ refresh: "Refresh"
17420
+ }
17421
+ };
17422
+ function CtrOpportunitiesPanel({ locale }) {
17423
+ const s = S4[locale] ?? S4.fr;
17424
+ const [opps, setOpps] = React4.useState(null);
17425
+ const [loading, setLoading] = React4.useState(true);
17426
+ const [notConnected, setNotConnected] = React4.useState(false);
17427
+ const [error, setError] = React4.useState(null);
17428
+ const [state, setState] = React4.useState({});
17429
+ const load = React4.useCallback(async () => {
17430
+ setLoading(true);
17431
+ setError(null);
17432
+ try {
17433
+ const res = await fetch("/api/seo-plugin/ctr-opportunities", { credentials: "include", cache: "no-store" });
17434
+ if (res.status === 403 || res.status === 409 || res.status === 400) {
17435
+ setNotConnected(true);
17436
+ return;
17437
+ }
17438
+ const json = await res.json();
17439
+ if (!res.ok) {
17440
+ setError(json.error || `Error ${res.status}`);
17441
+ return;
17442
+ }
17443
+ setNotConnected(false);
17444
+ setOpps(json.opportunities || []);
17445
+ } catch (e) {
17446
+ setError(e instanceof Error ? e.message : "Network error");
17447
+ } finally {
17448
+ setLoading(false);
17449
+ }
17450
+ }, []);
17451
+ React4.useEffect(() => {
17452
+ void load();
17453
+ }, [load]);
17454
+ const setRow = (url, patch) => setState((p) => ({ ...p, [url]: { ...p[url], ...patch } }));
17455
+ const optimize = async (o) => {
17456
+ if (!o.doc) return;
17457
+ setRow(o.url, { busy: true, error: void 0 });
17458
+ try {
17459
+ const res = await fetch("/api/seo-plugin/ai-optimize", {
17460
+ method: "POST",
17461
+ credentials: "include",
17462
+ headers: { "Content-Type": "application/json" },
17463
+ body: JSON.stringify({ collection: o.doc.collection, id: o.doc.id })
17464
+ });
17465
+ const json = await res.json();
17466
+ if (!res.ok) {
17467
+ setRow(o.url, { busy: false, error: json.code === "no_api_key" ? s.noKey : json.error || `Error ${res.status}` });
17468
+ return;
17469
+ }
17470
+ setRow(o.url, { busy: false, suggestion: { ...json.suggestions, current: json.current } });
17471
+ } catch (e) {
17472
+ setRow(o.url, { busy: false, error: e instanceof Error ? e.message : "Network error" });
17473
+ }
17474
+ };
17475
+ const apply = async (o) => {
17476
+ const rs = state[o.url];
17477
+ if (!o.doc || !rs?.suggestion) return;
17478
+ setRow(o.url, { busy: true, error: void 0 });
17479
+ const patch = {};
17480
+ if (rs.suggestion.metaTitle || rs.suggestion.metaDescription) {
17481
+ patch.meta = { title: rs.suggestion.metaTitle, description: rs.suggestion.metaDescription };
17482
+ }
17483
+ if (rs.suggestion.focusKeyword && rs.suggestion.focusKeyword !== rs.suggestion.current?.focusKeyword) {
17484
+ patch.focusKeyword = rs.suggestion.focusKeyword;
17485
+ }
17486
+ try {
17487
+ await fetch(`/api/${o.doc.collection}/${o.doc.id}`, {
17488
+ method: "PATCH",
17489
+ credentials: "include",
17490
+ headers: { "Content-Type": "application/json" },
17491
+ body: JSON.stringify(patch)
17492
+ });
17493
+ setRow(o.url, { busy: false, applied: true });
17494
+ } catch (e) {
17495
+ setRow(o.url, { busy: false, error: e instanceof Error ? e.message : "Network error" });
17496
+ }
17497
+ };
17498
+ const card = { padding: 16, borderRadius: 12, border: `1px solid ${C7.border}`, backgroundColor: C7.card, marginBottom: 20 };
17499
+ const btn = (bg) => ({
17500
+ padding: "5px 10px",
17501
+ borderRadius: 6,
17502
+ border: `1px solid ${bg}`,
17503
+ backgroundColor: bg,
17504
+ color: "#fff",
17505
+ fontSize: 11,
17506
+ fontWeight: 700,
17507
+ cursor: "pointer"
17508
+ });
17509
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: card, children: [
17510
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8, flexWrap: "wrap" }, children: [
17511
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
17512
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 16, fontWeight: 800, color: C7.text }, children: s.title }),
17513
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C7.sub, marginTop: 2 }, children: s.subtitle })
17514
+ ] }),
17515
+ !notConnected && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void load(), style: btn(C7.sub), children: s.refresh })
17516
+ ] }),
17517
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: C7.red, fontSize: 13, fontWeight: 600, marginTop: 10 }, children: error }),
17518
+ notConnected && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C7.sub }, children: s.needGsc }),
17519
+ loading && !notConnected && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C7.sub }, children: s.loading }),
17520
+ !loading && !notConnected && opps && opps.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C7.sub }, children: s.none }),
17521
+ !notConnected && opps && opps.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { overflowX: "auto", marginTop: 12 }, children: /* @__PURE__ */ jsxRuntime.jsxs("table", { style: { width: "100%", borderCollapse: "collapse", fontSize: 12 }, children: [
17522
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { style: { textAlign: "left", color: C7.sub }, children: [
17523
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: { padding: "6px 8px" }, children: s.page }),
17524
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: { padding: "6px 8px", textAlign: "right" }, children: s.pos }),
17525
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: { padding: "6px 8px", textAlign: "right" }, children: s.ctr }),
17526
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: { padding: "6px 8px", textAlign: "right" }, children: s.potential }),
17527
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: { padding: "6px 8px" } })
17528
+ ] }) }),
17529
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: opps.slice(0, 50).map((o) => {
17530
+ const rs = state[o.url] || {};
17531
+ const path = (() => {
17532
+ try {
17533
+ return new URL(o.url).pathname;
17534
+ } catch {
17535
+ return o.url;
17536
+ }
17537
+ })();
17538
+ return /* @__PURE__ */ jsxRuntime.jsxs(React4__default.default.Fragment, { children: [
17539
+ /* @__PURE__ */ jsxRuntime.jsxs("tr", { style: { borderTop: `1px solid ${C7.border}`, color: C7.text }, children: [
17540
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "6px 8px", maxWidth: 320, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: path }),
17541
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "6px 8px", textAlign: "right" }, children: o.position.toFixed(1) }),
17542
+ /* @__PURE__ */ jsxRuntime.jsxs("td", { style: { padding: "6px 8px", textAlign: "right" }, children: [
17543
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: C7.red }, children: [
17544
+ (o.ctr * 100).toFixed(1),
17545
+ "%"
17546
+ ] }),
17547
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: C7.sub }, children: [
17548
+ " / ",
17549
+ (o.expectedCtr * 100).toFixed(0),
17550
+ "% ",
17551
+ s.expected
17552
+ ] })
17553
+ ] }),
17554
+ /* @__PURE__ */ jsxRuntime.jsxs("td", { style: { padding: "6px 8px", textAlign: "right", fontWeight: 700, color: C7.amber }, children: [
17555
+ "+",
17556
+ o.potentialClicks
17557
+ ] }),
17558
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "6px 8px", textAlign: "right" }, children: rs.applied ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 11, fontWeight: 700, color: C7.green }, children: s.applied }) : o.doc ? rs.suggestion ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void apply(o), disabled: rs.busy, style: btn(C7.green), children: rs.busy ? s.optimizing : s.apply }) : /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void optimize(o), disabled: rs.busy, style: btn(C7.violet), children: rs.busy ? s.optimizing : `\u2728 ${s.optimize}` }) : /* @__PURE__ */ jsxRuntime.jsxs("a", { href: o.url, target: "_blank", rel: "noopener noreferrer", style: { fontSize: 11, color: C7.sub }, children: [
17559
+ s.open,
17560
+ " \u2197"
17561
+ ] }) })
17562
+ ] }),
17563
+ rs.suggestion && !rs.applied && /* @__PURE__ */ jsxRuntime.jsx("tr", { style: { color: C7.text }, children: /* @__PURE__ */ jsxRuntime.jsxs("td", { colSpan: 5, style: { padding: "0 8px 8px 8px" }, children: [
17564
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: C7.green, fontWeight: 600 }, children: rs.suggestion.metaTitle }),
17565
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: C7.sub }, children: rs.suggestion.metaDescription })
17566
+ ] }) }),
17567
+ rs.error && /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: 5, style: { padding: "0 8px 6px 8px", fontSize: 11, color: C7.red }, children: rs.error }) })
17568
+ ] }, o.url);
17569
+ }) })
17570
+ ] }) })
17571
+ ] });
17572
+ }
17573
+ var C8 = {
17574
+ text: "var(--theme-text, #1a1a1a)",
17575
+ sub: "var(--theme-elevation-600, #6b7280)",
17576
+ card: "var(--theme-elevation-50, #f9fafb)",
17577
+ border: "var(--theme-elevation-200, #e5e7eb)",
17578
+ green: "#22c55e",
17579
+ red: "#ef4444",
17580
+ amber: "#f59e0b",
17581
+ blue: "#3b82f6"
17582
+ };
17583
+ var S5 = {
17361
17584
  fr: {
17362
17585
  title: "Monitoring & alertes",
17363
17586
  subtitle: "Digest p\xE9riodique : r\xE9gressions de score, nouveaux 404, chutes de position (webhook / email).",
@@ -17400,7 +17623,7 @@ var S4 = {
17400
17623
  }
17401
17624
  };
17402
17625
  function AlertsPanel({ locale }) {
17403
- const s = S4[locale] ?? S4.fr;
17626
+ const s = S5[locale] ?? S5.fr;
17404
17627
  const [digest, setDigest] = React4.useState(null);
17405
17628
  const [config, setConfig] = React4.useState(null);
17406
17629
  const [loading, setLoading] = React4.useState(true);
@@ -17455,15 +17678,15 @@ function AlertsPanel({ locale }) {
17455
17678
  const card = {
17456
17679
  padding: 16,
17457
17680
  borderRadius: 12,
17458
- border: `1px solid ${C7.border}`,
17459
- backgroundColor: C7.card,
17681
+ border: `1px solid ${C8.border}`,
17682
+ backgroundColor: C8.card,
17460
17683
  marginBottom: 20
17461
17684
  };
17462
17685
  const btn = {
17463
17686
  padding: "8px 12px",
17464
17687
  borderRadius: 8,
17465
- border: `1px solid ${C7.blue}`,
17466
- backgroundColor: C7.blue,
17688
+ border: `1px solid ${C8.blue}`,
17689
+ backgroundColor: C8.blue,
17467
17690
  color: "#fff",
17468
17691
  fontSize: 12,
17469
17692
  fontWeight: 700,
@@ -17476,32 +17699,32 @@ function AlertsPanel({ locale }) {
17476
17699
  padding: "3px 8px",
17477
17700
  borderRadius: 999,
17478
17701
  color: "#fff",
17479
- backgroundColor: ok ? C7.green : C7.sub,
17702
+ backgroundColor: ok ? C8.green : C8.sub,
17480
17703
  marginRight: 6
17481
17704
  });
17482
17705
  const hasChannel = config && (config.webhookConfigured || config.emailConfigured);
17483
17706
  const list = (title, rows) => rows.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 10 }, children: [
17484
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, fontWeight: 700, color: C7.text, marginBottom: 4 }, children: [
17707
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, fontWeight: 700, color: C8.text, marginBottom: 4 }, children: [
17485
17708
  title,
17486
17709
  " ",
17487
- /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: C7.amber }, children: [
17710
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: C8.amber }, children: [
17488
17711
  "(",
17489
17712
  rows.length,
17490
17713
  ")"
17491
17714
  ] })
17492
17715
  ] }),
17493
- /* @__PURE__ */ jsxRuntime.jsx("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 12, color: C7.sub, lineHeight: 1.6 }, children: rows.slice(0, 8).map((r, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: r }, i)) })
17716
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 12, color: C8.sub, lineHeight: 1.6 }, children: rows.slice(0, 8).map((r, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: r }, i)) })
17494
17717
  ] }) : null;
17495
17718
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: card, children: [
17496
17719
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8, flexWrap: "wrap" }, children: [
17497
17720
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
17498
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 16, fontWeight: 800, color: C7.text }, children: s.title }),
17499
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C7.sub, marginTop: 2 }, children: s.subtitle })
17721
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 16, fontWeight: 800, color: C8.text }, children: s.title }),
17722
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C8.sub, marginTop: 2 }, children: s.subtitle })
17500
17723
  ] }),
17501
17724
  hasChannel && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: sendNow, disabled: busy, style: btn, children: busy ? s.sending : s.sendNow })
17502
17725
  ] }),
17503
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: C7.red, fontSize: 13, fontWeight: 600, marginTop: 10 }, children: error }),
17504
- notice && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: C7.green, fontSize: 13, fontWeight: 600, marginTop: 10 }, children: notice }),
17726
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: C8.red, fontSize: 13, fontWeight: 600, marginTop: 10 }, children: error }),
17727
+ notice && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: C8.green, fontSize: 13, fontWeight: 600, marginTop: 10 }, children: notice }),
17505
17728
  config && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 12 }, children: [
17506
17729
  /* @__PURE__ */ jsxRuntime.jsxs("span", { style: chip(config.webhookConfigured, s.webhook), children: [
17507
17730
  s.webhook,
@@ -17514,15 +17737,15 @@ function AlertsPanel({ locale }) {
17514
17737
  config.emailConfigured ? s.configured : s.missing
17515
17738
  ] })
17516
17739
  ] }),
17517
- !loading && !hasChannel && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C7.sub }, children: s.notConfigured }),
17518
- loading && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C7.sub }, children: s.loading }),
17740
+ !loading && !hasChannel && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C8.sub }, children: s.notConfigured }),
17741
+ loading && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C8.sub }, children: s.loading }),
17519
17742
  digest && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 8 }, children: [
17520
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, color: C7.sub, marginTop: 6 }, children: [
17743
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, color: C8.sub, marginTop: 6 }, children: [
17521
17744
  digest.totalIssues,
17522
17745
  " ",
17523
17746
  s.issues
17524
17747
  ] }),
17525
- digest.totalIssues === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 8, fontSize: 13, color: C7.sub }, children: s.noIssues }),
17748
+ digest.totalIssues === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 8, fontSize: 13, color: C8.sub }, children: s.noIssues }),
17526
17749
  list(
17527
17750
  s.scoreReg,
17528
17751
  digest.scoreRegressions.map((r) => `${r.collection}/${r.documentId} \u2014 ${r.from} \u2192 ${r.to} (\u2212${r.drop})`)
@@ -17532,7 +17755,7 @@ function AlertsPanel({ locale }) {
17532
17755
  ] })
17533
17756
  ] });
17534
17757
  }
17535
- var C8 = {
17758
+ var C9 = {
17536
17759
  text: "var(--theme-text, #1a1a1a)",
17537
17760
  sub: "var(--theme-elevation-600, #6b7280)",
17538
17761
  card: "var(--theme-elevation-50, #f9fafb)",
@@ -17542,7 +17765,7 @@ var C8 = {
17542
17765
  red: "#ef4444",
17543
17766
  violet: "#7c3aed"
17544
17767
  };
17545
- var S5 = {
17768
+ var S6 = {
17546
17769
  fr: {
17547
17770
  title: "Alt-text IA des images",
17548
17771
  subtitle: "G\xE9n\xE8re l'attribut alt des images qui n'en ont pas (Claude vision), pour l'accessibilit\xE9 et le SEO.",
@@ -17575,7 +17798,7 @@ var S5 = {
17575
17798
  }
17576
17799
  };
17577
17800
  function AltTextPanel({ locale }) {
17578
- const s = S5[locale] ?? S5.fr;
17801
+ const s = S6[locale] ?? S6.fr;
17579
17802
  const [items, setItems] = React4.useState(null);
17580
17803
  const [collection, setCollection] = React4.useState("media");
17581
17804
  const [missingCount, setMissingCount] = React4.useState(0);
@@ -17652,8 +17875,8 @@ function AltTextPanel({ locale }) {
17652
17875
  const card = {
17653
17876
  padding: 16,
17654
17877
  borderRadius: 12,
17655
- border: `1px solid ${C8.border}`,
17656
- backgroundColor: C8.card,
17878
+ border: `1px solid ${C9.border}`,
17879
+ backgroundColor: C9.card,
17657
17880
  marginBottom: 20
17658
17881
  };
17659
17882
  const btn = (bg) => ({
@@ -17669,18 +17892,18 @@ function AltTextPanel({ locale }) {
17669
17892
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: card, children: [
17670
17893
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8, flexWrap: "wrap" }, children: [
17671
17894
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
17672
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 16, fontWeight: 800, color: C8.text }, children: s.title }),
17673
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C8.sub, marginTop: 2 }, children: s.subtitle })
17895
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 16, fontWeight: 800, color: C9.text }, children: s.title }),
17896
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C9.sub, marginTop: 2 }, children: s.subtitle })
17674
17897
  ] }),
17675
- status === "ok" && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void load(), style: btn(C8.sub), children: s.refresh })
17898
+ status === "ok" && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void load(), style: btn(C9.sub), children: s.refresh })
17676
17899
  ] }),
17677
- status === "forbidden" && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C8.sub }, children: s.forbidden }),
17678
- status === "disabled" && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C8.sub }, children: s.disabled }),
17900
+ status === "forbidden" && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C9.sub }, children: s.forbidden }),
17901
+ status === "disabled" && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C9.sub }, children: s.disabled }),
17679
17902
  status === "ok" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 12 }, children: [
17680
- loading && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, color: C8.sub }, children: s.loading }),
17681
- !loading && items && items.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, color: C8.sub }, children: s.none }),
17903
+ loading && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, color: C9.sub }, children: s.loading }),
17904
+ !loading && items && items.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, color: C9.sub }, children: s.none }),
17682
17905
  !loading && items && items.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
17683
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, color: C8.sub, marginBottom: 10 }, children: [
17906
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, color: C9.sub, marginBottom: 10 }, children: [
17684
17907
  missingCount,
17685
17908
  " ",
17686
17909
  s.missing
@@ -17696,8 +17919,8 @@ function AltTextPanel({ locale }) {
17696
17919
  alignItems: "center",
17697
17920
  padding: 8,
17698
17921
  borderRadius: 8,
17699
- border: `1px solid ${C8.border}`,
17700
- backgroundColor: C8.bg
17922
+ border: `1px solid ${C9.border}`,
17923
+ backgroundColor: C9.bg
17701
17924
  },
17702
17925
  children: [
17703
17926
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -17705,11 +17928,11 @@ function AltTextPanel({ locale }) {
17705
17928
  {
17706
17929
  src: item.url,
17707
17930
  alt: "",
17708
- style: { width: 48, height: 48, objectFit: "cover", borderRadius: 6, flexShrink: 0, border: `1px solid ${C8.border}` }
17931
+ style: { width: 48, height: 48, objectFit: "cover", borderRadius: 6, flexShrink: 0, border: `1px solid ${C9.border}` }
17709
17932
  }
17710
17933
  ),
17711
17934
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
17712
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: C8.sub, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: item.filename }),
17935
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: C9.sub, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: item.filename }),
17713
17936
  rs.alt !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
17714
17937
  "input",
17715
17938
  {
@@ -17723,15 +17946,15 @@ function AltTextPanel({ locale }) {
17723
17946
  padding: "4px 8px",
17724
17947
  fontSize: 12,
17725
17948
  borderRadius: 6,
17726
- border: `1px solid ${C8.border}`,
17727
- backgroundColor: C8.bg,
17728
- color: C8.text
17949
+ border: `1px solid ${C9.border}`,
17950
+ backgroundColor: C9.bg,
17951
+ color: C9.text
17729
17952
  }
17730
17953
  }
17731
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C8.sub, marginTop: 4, fontStyle: "italic" }, children: "\u2014" }),
17732
- rs.error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: C8.red, marginTop: 2 }, children: rs.error })
17954
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C9.sub, marginTop: 4, fontStyle: "italic" }, children: "\u2014" }),
17955
+ rs.error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: C9.red, marginTop: 2 }, children: rs.error })
17733
17956
  ] }),
17734
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flexShrink: 0 }, children: rs.applied ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 11, fontWeight: 700, color: C8.green }, children: s.applied }) : rs.alt !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void apply(item), disabled: rs.busy, style: btn(C8.green), children: rs.busy ? s.generating : s.apply }) : /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void generate(item), disabled: rs.busy, style: btn(C8.violet), children: rs.busy ? s.generating : s.generate }) })
17957
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flexShrink: 0 }, children: rs.applied ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 11, fontWeight: 700, color: C9.green }, children: s.applied }) : rs.alt !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void apply(item), disabled: rs.busy, style: btn(C9.green), children: rs.busy ? s.generating : s.apply }) : /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void generate(item), disabled: rs.busy, style: btn(C9.violet), children: rs.busy ? s.generating : s.generate }) })
17735
17958
  ]
17736
17959
  },
17737
17960
  item.id
@@ -18156,6 +18379,7 @@ function PerformanceView() {
18156
18379
  /* @__PURE__ */ jsxRuntime.jsx(CoreWebVitalsPanel, { locale }),
18157
18380
  /* @__PURE__ */ jsxRuntime.jsx(GscPanel, { locale }),
18158
18381
  /* @__PURE__ */ jsxRuntime.jsx(RankTrackingPanel, { locale }),
18382
+ /* @__PURE__ */ jsxRuntime.jsx(CtrOpportunitiesPanel, { locale }),
18159
18383
  /* @__PURE__ */ jsxRuntime.jsx(AlertsPanel, { locale }),
18160
18384
  /* @__PURE__ */ jsxRuntime.jsx(AltTextPanel, { locale }),
18161
18385
  showImport && /* @__PURE__ */ jsxRuntime.jsxs(
@@ -18681,7 +18905,7 @@ function PerformanceView() {
18681
18905
  }
18682
18906
  );
18683
18907
  }
18684
- var C9 = {
18908
+ var C10 = {
18685
18909
  text: "var(--theme-text, #1a1a1a)",
18686
18910
  sub: "var(--theme-elevation-600, #6b7280)",
18687
18911
  card: "var(--theme-elevation-50, #f9fafb)",
@@ -18691,7 +18915,7 @@ var C9 = {
18691
18915
  red: "#ef4444",
18692
18916
  blue: "#3b82f6"
18693
18917
  };
18694
- var S6 = {
18918
+ var S7 = {
18695
18919
  fr: {
18696
18920
  title: "Brief de contenu IA",
18697
18921
  subtitle: "G\xE9n\xE8re un plan r\xE9dactionnel optimis\xE9 pour un mot-cl\xE9 (plan, entit\xE9s, questions, longueur cible).",
@@ -18726,7 +18950,7 @@ var S6 = {
18726
18950
  }
18727
18951
  };
18728
18952
  function ContentBriefPanel({ locale }) {
18729
- const s = S6[locale] ?? S6.fr;
18953
+ const s = S7[locale] ?? S7.fr;
18730
18954
  const [keyword, setKeyword] = React4.useState("");
18731
18955
  const [brief, setBrief] = React4.useState(null);
18732
18956
  const [busy, setBusy] = React4.useState(false);
@@ -18762,8 +18986,8 @@ function ContentBriefPanel({ locale }) {
18762
18986
  const card = {
18763
18987
  padding: 16,
18764
18988
  borderRadius: 12,
18765
- border: `1px solid ${C9.border}`,
18766
- backgroundColor: C9.card,
18989
+ border: `1px solid ${C10.border}`,
18990
+ backgroundColor: C10.card,
18767
18991
  marginBottom: 20
18768
18992
  };
18769
18993
  const chip = {
@@ -18772,14 +18996,14 @@ function ContentBriefPanel({ locale }) {
18772
18996
  padding: "3px 8px",
18773
18997
  borderRadius: 999,
18774
18998
  backgroundColor: "rgba(59,130,246,0.12)",
18775
- color: C9.blue,
18776
- border: `1px solid ${C9.border}`,
18999
+ color: C10.blue,
19000
+ border: `1px solid ${C10.border}`,
18777
19001
  margin: "0 6px 6px 0"
18778
19002
  };
18779
- const h4 = { fontSize: 12, fontWeight: 800, color: C9.text, margin: "14px 0 6px", textTransform: "uppercase" };
19003
+ const h4 = { fontSize: 12, fontWeight: 800, color: C10.text, margin: "14px 0 6px", textTransform: "uppercase" };
18780
19004
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: card, children: [
18781
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 16, fontWeight: 800, color: C9.text }, children: s.title }),
18782
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C9.sub, marginTop: 2, marginBottom: 12 }, children: s.subtitle }),
19005
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 16, fontWeight: 800, color: C10.text }, children: s.title }),
19006
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C10.sub, marginTop: 2, marginBottom: 12 }, children: s.subtitle }),
18783
19007
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
18784
19008
  /* @__PURE__ */ jsxRuntime.jsx(
18785
19009
  "input",
@@ -18796,9 +19020,9 @@ function ContentBriefPanel({ locale }) {
18796
19020
  padding: "8px 12px",
18797
19021
  fontSize: 13,
18798
19022
  borderRadius: 8,
18799
- border: `1px solid ${C9.border}`,
18800
- backgroundColor: C9.bg,
18801
- color: C9.text
19023
+ border: `1px solid ${C10.border}`,
19024
+ backgroundColor: C10.bg,
19025
+ color: C10.text
18802
19026
  }
18803
19027
  }
18804
19028
  ),
@@ -18811,8 +19035,8 @@ function ContentBriefPanel({ locale }) {
18811
19035
  style: {
18812
19036
  padding: "8px 14px",
18813
19037
  borderRadius: 8,
18814
- border: `1px solid ${C9.violet}`,
18815
- backgroundColor: C9.violet,
19038
+ border: `1px solid ${C10.violet}`,
19039
+ backgroundColor: C10.violet,
18816
19040
  color: "#fff",
18817
19041
  fontSize: 12,
18818
19042
  fontWeight: 700,
@@ -18823,12 +19047,12 @@ function ContentBriefPanel({ locale }) {
18823
19047
  }
18824
19048
  )
18825
19049
  ] }),
18826
- error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: C9.red, fontSize: 13, fontWeight: 600, marginTop: 10 }, children: error }),
19050
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: C10.red, fontSize: 13, fontWeight: 600, marginTop: 10 }, children: error }),
18827
19051
  brief && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 8 }, children: [
18828
- brief.recommendedWordCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, color: C9.sub, marginTop: 10 }, children: [
19052
+ brief.recommendedWordCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, color: C10.sub, marginTop: 10 }, children: [
18829
19053
  s.words,
18830
19054
  ": ",
18831
- /* @__PURE__ */ jsxRuntime.jsxs("b", { style: { color: C9.text }, children: [
19055
+ /* @__PURE__ */ jsxRuntime.jsxs("b", { style: { color: C10.text }, children: [
18832
19056
  "~",
18833
19057
  brief.recommendedWordCount,
18834
19058
  " ",
@@ -18837,7 +19061,7 @@ function ContentBriefPanel({ locale }) {
18837
19061
  ] }),
18838
19062
  brief.outline.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18839
19063
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: h4, children: s.outline }),
18840
- /* @__PURE__ */ jsxRuntime.jsx("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 13, color: C9.text, lineHeight: 1.6 }, children: brief.outline.map((o, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { style: { marginLeft: o.level === "h3" ? 18 : 0, color: o.level === "h3" ? C9.sub : C9.text, fontWeight: o.level === "h2" ? 700 : 400 }, children: o.text }, i)) })
19064
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 13, color: C10.text, lineHeight: 1.6 }, children: brief.outline.map((o, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { style: { marginLeft: o.level === "h3" ? 18 : 0, color: o.level === "h3" ? C10.sub : C10.text, fontWeight: o.level === "h2" ? 700 : 400 }, children: o.text }, i)) })
18841
19065
  ] }),
18842
19066
  brief.entities.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18843
19067
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: h4, children: s.entities }),
@@ -18845,7 +19069,7 @@ function ContentBriefPanel({ locale }) {
18845
19069
  ] }),
18846
19070
  brief.questions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18847
19071
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: h4, children: s.questions }),
18848
- /* @__PURE__ */ jsxRuntime.jsx("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 13, color: C9.text, lineHeight: 1.6 }, children: brief.questions.map((q, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: q }, i)) })
19072
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 13, color: C10.text, lineHeight: 1.6 }, children: brief.questions.map((q, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: q }, i)) })
18849
19073
  ] }),
18850
19074
  brief.internalLinkIdeas.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18851
19075
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: h4, children: s.links }),
@@ -18853,7 +19077,7 @@ function ContentBriefPanel({ locale }) {
18853
19077
  ] }),
18854
19078
  brief.notes.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18855
19079
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: h4, children: s.notes }),
18856
- /* @__PURE__ */ jsxRuntime.jsx("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 12, color: C9.sub, lineHeight: 1.6 }, children: brief.notes.map((n, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: n }, i)) })
19080
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 12, color: C10.sub, lineHeight: 1.6 }, children: brief.notes.map((n, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: n }, i)) })
18857
19081
  ] })
18858
19082
  ] })
18859
19083
  ] });
@@ -19995,7 +20219,7 @@ var controlBtnStyle = {
19995
20219
  cursor: "pointer",
19996
20220
  lineHeight: 1.4
19997
20221
  };
19998
- var C10 = {
20222
+ var C11 = {
19999
20223
  cyan: "#00E5FF",
20000
20224
  black: "#000",
20001
20225
  green: "#22c55e",
@@ -20010,10 +20234,10 @@ var C10 = {
20010
20234
  var TITLE_MIN = 30;
20011
20235
  var TITLE_MAX = 60;
20012
20236
  function getCharColor(len) {
20013
- if (len === 0) return C10.textSecondary;
20014
- if (len >= TITLE_MIN && len <= TITLE_MAX) return C10.green;
20015
- if (len > 0 && len < TITLE_MIN) return C10.orange;
20016
- return C10.red;
20237
+ if (len === 0) return C11.textSecondary;
20238
+ if (len >= TITLE_MIN && len <= TITLE_MAX) return C11.green;
20239
+ if (len > 0 && len < TITLE_MIN) return C11.orange;
20240
+ return C11.red;
20017
20241
  }
20018
20242
  function getProgressPercent(len) {
20019
20243
  if (len === 0) return 0;
@@ -20021,9 +20245,9 @@ function getProgressPercent(len) {
20021
20245
  }
20022
20246
  function getProgressColor(len) {
20023
20247
  if (len === 0) return "var(--theme-elevation-200, #e5e7eb)";
20024
- if (len >= TITLE_MIN && len <= TITLE_MAX) return C10.green;
20025
- if (len < TITLE_MIN) return C10.orange;
20026
- return C10.red;
20248
+ if (len >= TITLE_MIN && len <= TITLE_MAX) return C11.green;
20249
+ if (len < TITLE_MIN) return C11.orange;
20250
+ return C11.red;
20027
20251
  }
20028
20252
  function MetaTitleField({
20029
20253
  path,
@@ -20094,7 +20318,7 @@ function MetaTitleField({
20094
20318
  style: {
20095
20319
  fontSize: 13,
20096
20320
  fontWeight: 700,
20097
- color: C10.textPrimary
20321
+ color: C11.textPrimary
20098
20322
  },
20099
20323
  children: t.metaTitle.label
20100
20324
  }
@@ -20134,9 +20358,9 @@ function MetaTitleField({
20134
20358
  fontSize: 14,
20135
20359
  fontFamily: "inherit",
20136
20360
  borderRadius: 8,
20137
- border: `2px solid ${C10.border}`,
20138
- backgroundColor: C10.surfaceBg,
20139
- color: C10.textPrimary,
20361
+ border: `2px solid ${C11.border}`,
20362
+ backgroundColor: C11.surfaceBg,
20363
+ color: C11.textPrimary,
20140
20364
  outline: "none",
20141
20365
  boxShadow: "2px 2px 0 0 var(--theme-border-color, rgba(0,0,0,1))"
20142
20366
  }
@@ -20154,9 +20378,9 @@ function MetaTitleField({
20154
20378
  gap: 5,
20155
20379
  padding: "8px 14px",
20156
20380
  borderRadius: 8,
20157
- border: `2px solid ${C10.border}`,
20158
- backgroundColor: loading ? C10.surface50 : C10.cyan,
20159
- color: loading ? C10.textSecondary : C10.black,
20381
+ border: `2px solid ${C11.border}`,
20382
+ backgroundColor: loading ? C11.surface50 : C11.cyan,
20383
+ color: loading ? C11.textSecondary : C11.black,
20160
20384
  fontWeight: 800,
20161
20385
  fontSize: 11,
20162
20386
  textTransform: "uppercase",
@@ -20203,7 +20427,7 @@ function MetaTitleField({
20203
20427
  justifyContent: "space-between",
20204
20428
  marginTop: 4,
20205
20429
  fontSize: 10,
20206
- color: C10.textSecondary
20430
+ color: C11.textSecondary
20207
20431
  },
20208
20432
  children: [
20209
20433
  /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
@@ -20237,9 +20461,9 @@ function MetaTitleField({
20237
20461
  borderRadius: 6,
20238
20462
  fontSize: 11,
20239
20463
  fontWeight: 600,
20240
- color: C10.red,
20464
+ color: C11.red,
20241
20465
  backgroundColor: "rgba(239,68,68,0.08)",
20242
- border: `1px solid ${C10.red}`
20466
+ border: `1px solid ${C11.red}`
20243
20467
  },
20244
20468
  children: error
20245
20469
  }
@@ -20248,7 +20472,7 @@ function MetaTitleField({
20248
20472
  }
20249
20473
  );
20250
20474
  }
20251
- var C11 = {
20475
+ var C12 = {
20252
20476
  cyan: "#00E5FF",
20253
20477
  black: "#000",
20254
20478
  green: "#22c55e",
@@ -20263,10 +20487,10 @@ var C11 = {
20263
20487
  var DESC_MIN = 120;
20264
20488
  var DESC_MAX = 160;
20265
20489
  function getCharColor2(len) {
20266
- if (len === 0) return C11.textSecondary;
20267
- if (len >= DESC_MIN && len <= DESC_MAX) return C11.green;
20268
- if (len > 0 && len < DESC_MIN) return C11.orange;
20269
- return C11.red;
20490
+ if (len === 0) return C12.textSecondary;
20491
+ if (len >= DESC_MIN && len <= DESC_MAX) return C12.green;
20492
+ if (len > 0 && len < DESC_MIN) return C12.orange;
20493
+ return C12.red;
20270
20494
  }
20271
20495
  function getProgressPercent2(len) {
20272
20496
  if (len === 0) return 0;
@@ -20274,9 +20498,9 @@ function getProgressPercent2(len) {
20274
20498
  }
20275
20499
  function getProgressColor2(len) {
20276
20500
  if (len === 0) return "var(--theme-elevation-200, #e5e7eb)";
20277
- if (len >= DESC_MIN && len <= DESC_MAX) return C11.green;
20278
- if (len < DESC_MIN) return C11.orange;
20279
- return C11.red;
20501
+ if (len >= DESC_MIN && len <= DESC_MAX) return C12.green;
20502
+ if (len < DESC_MIN) return C12.orange;
20503
+ return C12.red;
20280
20504
  }
20281
20505
  function MetaDescriptionField({
20282
20506
  path,
@@ -20347,7 +20571,7 @@ function MetaDescriptionField({
20347
20571
  style: {
20348
20572
  fontSize: 13,
20349
20573
  fontWeight: 700,
20350
- color: C11.textPrimary
20574
+ color: C12.textPrimary
20351
20575
  },
20352
20576
  children: t.metaDescription.label
20353
20577
  }
@@ -20387,9 +20611,9 @@ function MetaDescriptionField({
20387
20611
  fontSize: 14,
20388
20612
  fontFamily: "inherit",
20389
20613
  borderRadius: 8,
20390
- border: `2px solid ${C11.border}`,
20391
- backgroundColor: C11.surfaceBg,
20392
- color: C11.textPrimary,
20614
+ border: `2px solid ${C12.border}`,
20615
+ backgroundColor: C12.surfaceBg,
20616
+ color: C12.textPrimary,
20393
20617
  outline: "none",
20394
20618
  resize: "vertical",
20395
20619
  lineHeight: 1.5,
@@ -20409,9 +20633,9 @@ function MetaDescriptionField({
20409
20633
  gap: 5,
20410
20634
  padding: "8px 14px",
20411
20635
  borderRadius: 8,
20412
- border: `2px solid ${C11.border}`,
20413
- backgroundColor: loading ? C11.surface50 : C11.cyan,
20414
- color: loading ? C11.textSecondary : C11.black,
20636
+ border: `2px solid ${C12.border}`,
20637
+ backgroundColor: loading ? C12.surface50 : C12.cyan,
20638
+ color: loading ? C12.textSecondary : C12.black,
20415
20639
  fontWeight: 800,
20416
20640
  fontSize: 11,
20417
20641
  textTransform: "uppercase",
@@ -20459,7 +20683,7 @@ function MetaDescriptionField({
20459
20683
  justifyContent: "space-between",
20460
20684
  marginTop: 4,
20461
20685
  fontSize: 10,
20462
- color: C11.textSecondary
20686
+ color: C12.textSecondary
20463
20687
  },
20464
20688
  children: [
20465
20689
  /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
@@ -20493,9 +20717,9 @@ function MetaDescriptionField({
20493
20717
  borderRadius: 6,
20494
20718
  fontSize: 11,
20495
20719
  fontWeight: 600,
20496
- color: C11.red,
20720
+ color: C12.red,
20497
20721
  backgroundColor: "rgba(239,68,68,0.08)",
20498
- border: `1px solid ${C11.red}`
20722
+ border: `1px solid ${C12.red}`
20499
20723
  },
20500
20724
  children: error
20501
20725
  }
@@ -20504,7 +20728,7 @@ function MetaDescriptionField({
20504
20728
  }
20505
20729
  );
20506
20730
  }
20507
- var C12 = {
20731
+ var C13 = {
20508
20732
  cyan: "#00E5FF",
20509
20733
  black: "#000",
20510
20734
  white: "#fff",
@@ -20581,8 +20805,8 @@ function MetaImageField({
20581
20805
  gap: 10,
20582
20806
  padding: "10px 14px",
20583
20807
  borderRadius: 8,
20584
- border: `2px solid ${C12.border}`,
20585
- backgroundColor: C12.surfaceBg,
20808
+ border: `2px solid ${C13.border}`,
20809
+ backgroundColor: C13.surfaceBg,
20586
20810
  boxShadow: "2px 2px 0 0 var(--theme-border-color, rgba(0,0,0,1))"
20587
20811
  },
20588
20812
  children: [
@@ -20601,7 +20825,7 @@ function MetaImageField({
20601
20825
  fontWeight: 900,
20602
20826
  backgroundColor: hasImage ? "rgba(34,197,94,0.15)" : "rgba(255,138,0,0.15)",
20603
20827
  color: hasImage ? "#16a34a" : "#d97706",
20604
- border: `1px solid ${hasImage ? C12.green : C12.orange}`
20828
+ border: `1px solid ${hasImage ? C13.green : C13.orange}`
20605
20829
  },
20606
20830
  children: hasImage ? "\u2713" : "!"
20607
20831
  }
@@ -20613,7 +20837,7 @@ function MetaImageField({
20613
20837
  style: {
20614
20838
  fontSize: 12,
20615
20839
  fontWeight: 700,
20616
- color: C12.textPrimary
20840
+ color: C13.textPrimary
20617
20841
  },
20618
20842
  children: t.metaImage.label
20619
20843
  }
@@ -20623,7 +20847,7 @@ function MetaImageField({
20623
20847
  {
20624
20848
  style: {
20625
20849
  fontSize: 10,
20626
- color: C12.textSecondary,
20850
+ color: C13.textSecondary,
20627
20851
  lineHeight: 1.4
20628
20852
  },
20629
20853
  children: hasImage ? t.metaImage.imageSet : t.metaImage.noImage
@@ -20643,9 +20867,9 @@ function MetaImageField({
20643
20867
  gap: 5,
20644
20868
  padding: "8px 14px",
20645
20869
  borderRadius: 8,
20646
- border: `2px solid ${C12.border}`,
20647
- backgroundColor: loading ? C12.surface50 : success ? C12.green : C12.cyan,
20648
- color: loading ? C12.textSecondary : success ? C12.white : C12.black,
20870
+ border: `2px solid ${C13.border}`,
20871
+ backgroundColor: loading ? C13.surface50 : success ? C13.green : C13.cyan,
20872
+ color: loading ? C13.textSecondary : success ? C13.white : C13.black,
20649
20873
  fontWeight: 800,
20650
20874
  fontSize: 11,
20651
20875
  textTransform: "uppercase",
@@ -20672,9 +20896,9 @@ function MetaImageField({
20672
20896
  borderRadius: 6,
20673
20897
  fontSize: 11,
20674
20898
  fontWeight: 600,
20675
- color: C12.red,
20899
+ color: C13.red,
20676
20900
  backgroundColor: "rgba(239,68,68,0.08)",
20677
- border: `1px solid ${C12.red}`
20901
+ border: `1px solid ${C13.red}`
20678
20902
  },
20679
20903
  children: error
20680
20904
  }
@@ -20683,7 +20907,7 @@ function MetaImageField({
20683
20907
  }
20684
20908
  );
20685
20909
  }
20686
- var C13 = {
20910
+ var C14 = {
20687
20911
  black: "#000",
20688
20912
  white: "#fff",
20689
20913
  green: "#22c55e",
@@ -20697,15 +20921,15 @@ var C13 = {
20697
20921
  function getCompletenessColor(count) {
20698
20922
  switch (count) {
20699
20923
  case 0:
20700
- return C13.red;
20924
+ return C14.red;
20701
20925
  case 1:
20702
- return C13.orange;
20926
+ return C14.orange;
20703
20927
  case 2:
20704
- return C13.yellow;
20928
+ return C14.yellow;
20705
20929
  case 3:
20706
- return C13.green;
20930
+ return C14.green;
20707
20931
  default:
20708
- return C13.textSecondary;
20932
+ return C14.textSecondary;
20709
20933
  }
20710
20934
  }
20711
20935
  function getCompletenessLabel(count, ov) {
@@ -20763,8 +20987,8 @@ function OverviewField({
20763
20987
  fontFamily: "var(--font-body, Inter, system-ui, sans-serif)",
20764
20988
  padding: "12px 14px",
20765
20989
  borderRadius: 10,
20766
- border: `2px solid ${C13.border}`,
20767
- backgroundColor: C13.surfaceBg,
20990
+ border: `2px solid ${C14.border}`,
20991
+ backgroundColor: C14.surfaceBg,
20768
20992
  boxShadow: "3px 3px 0 0 var(--theme-border-color, rgba(0,0,0,1))",
20769
20993
  marginBottom: 12
20770
20994
  },
@@ -20787,7 +21011,7 @@ function OverviewField({
20787
21011
  fontWeight: 800,
20788
21012
  textTransform: "uppercase",
20789
21013
  letterSpacing: "0.04em",
20790
- color: C13.textPrimary
21014
+ color: C14.textPrimary
20791
21015
  },
20792
21016
  children: t.overview.metaCompleteness
20793
21017
  }
@@ -20802,8 +21026,8 @@ function OverviewField({
20802
21026
  fontSize: 11,
20803
21027
  fontWeight: 800,
20804
21028
  backgroundColor: completenessColor,
20805
- color: completenessColor === C13.yellow ? C13.black : C13.white,
20806
- border: `2px solid ${C13.border}`,
21029
+ color: completenessColor === C14.yellow ? C14.black : C14.white,
21030
+ border: `2px solid ${C14.border}`,
20807
21031
  textTransform: "uppercase",
20808
21032
  letterSpacing: "0.03em"
20809
21033
  },
@@ -20901,7 +21125,7 @@ function OverviewField({
20901
21125
  style: {
20902
21126
  fontSize: 12,
20903
21127
  fontWeight: 600,
20904
- color: item.filled ? C13.textPrimary : C13.textSecondary
21128
+ color: item.filled ? C14.textPrimary : C14.textSecondary
20905
21129
  },
20906
21130
  children: item.label
20907
21131
  }
@@ -20913,7 +21137,7 @@ function OverviewField({
20913
21137
  marginLeft: "auto",
20914
21138
  fontSize: 10,
20915
21139
  fontWeight: 700,
20916
- color: item.filled ? C13.green : C13.red,
21140
+ color: item.filled ? C14.green : C14.red,
20917
21141
  textTransform: "uppercase",
20918
21142
  letterSpacing: "0.03em"
20919
21143
  },
@@ -20930,7 +21154,7 @@ function OverviewField({
20930
21154
  }
20931
21155
  );
20932
21156
  }
20933
- var C14 = {
21157
+ var C15 = {
20934
21158
  cyan: "#00E5FF",
20935
21159
  black: "#000",
20936
21160
  white: "#fff",
@@ -20949,10 +21173,10 @@ var G = {
20949
21173
  descGrey: "#4d5156",
20950
21174
  faviconBg: "#e8eaed"};
20951
21175
  function charCountColor2(len, min, max) {
20952
- if (len >= min && len <= max) return C14.green;
20953
- if (len > 0 && len < min) return C14.orange;
20954
- if (len > max) return C14.red;
20955
- return C14.textSecondary;
21176
+ if (len >= min && len <= max) return C15.green;
21177
+ if (len > 0 && len < min) return C15.orange;
21178
+ if (len > max) return C15.red;
21179
+ return C15.textSecondary;
20956
21180
  }
20957
21181
  function truncateText(text, maxChars) {
20958
21182
  if (text.length <= maxChars) return text;
@@ -21007,8 +21231,8 @@ function SerpPreview({
21007
21231
  padding: "10px 12px",
21008
21232
  cursor: "pointer",
21009
21233
  borderRadius: 8,
21010
- border: `2px solid ${C14.border}`,
21011
- backgroundColor: C14.surface50,
21234
+ border: `2px solid ${C15.border}`,
21235
+ backgroundColor: C15.surface50,
21012
21236
  userSelect: "none"
21013
21237
  },
21014
21238
  children: [
@@ -21023,7 +21247,7 @@ function SerpPreview({
21023
21247
  fontWeight: 800,
21024
21248
  textTransform: "uppercase",
21025
21249
  letterSpacing: "0.04em",
21026
- color: C14.textPrimary
21250
+ color: C15.textPrimary
21027
21251
  },
21028
21252
  children: [
21029
21253
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -21055,7 +21279,7 @@ function SerpPreview({
21055
21279
  transition: "transform 0.2s",
21056
21280
  display: "inline-block",
21057
21281
  transform: open ? "rotate(90deg)" : "none",
21058
- color: C14.textSecondary
21282
+ color: C15.textSecondary
21059
21283
  },
21060
21284
  children: "\u25B6"
21061
21285
  }
@@ -21088,10 +21312,10 @@ function SerpPreview({
21088
21312
  "div",
21089
21313
  {
21090
21314
  style: {
21091
- backgroundColor: C14.white,
21092
- border: `2px solid ${C14.border}`,
21315
+ backgroundColor: C15.white,
21316
+ border: `2px solid ${C15.border}`,
21093
21317
  borderRadius: 12,
21094
- boxShadow: `3px 3px 0 0 ${C14.border}`,
21318
+ boxShadow: `3px 3px 0 0 ${C15.border}`,
21095
21319
  padding: isDesktop ? 20 : 14,
21096
21320
  maxWidth: isDesktop ? 650 : 380,
21097
21321
  overflow: "hidden"
@@ -21154,7 +21378,7 @@ function SerpPreview({
21154
21378
  style: {
21155
21379
  fontSize: 14,
21156
21380
  fontWeight: 400,
21157
- color: C14.black,
21381
+ color: C15.black,
21158
21382
  lineHeight: 1.3,
21159
21383
  whiteSpace: "nowrap",
21160
21384
  overflow: "hidden",
@@ -21218,7 +21442,7 @@ function SerpPreview({
21218
21442
  "span",
21219
21443
  {
21220
21444
  style: {
21221
- color: C14.textSecondary,
21445
+ color: C15.textSecondary,
21222
21446
  fontStyle: "italic",
21223
21447
  fontSize: titleFontSize - 2
21224
21448
  },
@@ -21247,7 +21471,7 @@ function SerpPreview({
21247
21471
  "span",
21248
21472
  {
21249
21473
  style: {
21250
- color: C14.textSecondary,
21474
+ color: C15.textSecondary,
21251
21475
  fontStyle: "italic",
21252
21476
  fontSize: descFontSize - 1
21253
21477
  },
@@ -21280,7 +21504,7 @@ function SerpPreview({
21280
21504
  fontSize: 11
21281
21505
  },
21282
21506
  children: [
21283
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C14.textSecondary, fontWeight: 600 }, children: t.serpPreview.previewTitle }),
21507
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C15.textSecondary, fontWeight: 600 }, children: t.serpPreview.previewTitle }),
21284
21508
  /* @__PURE__ */ jsxRuntime.jsxs(
21285
21509
  "span",
21286
21510
  {
@@ -21309,7 +21533,7 @@ function SerpPreview({
21309
21533
  fontSize: 11
21310
21534
  },
21311
21535
  children: [
21312
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C14.textSecondary, fontWeight: 600 }, children: t.serpPreview.previewDescription }),
21536
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C15.textSecondary, fontWeight: 600 }, children: t.serpPreview.previewDescription }),
21313
21537
  /* @__PURE__ */ jsxRuntime.jsxs(
21314
21538
  "span",
21315
21539
  {
@@ -21338,14 +21562,14 @@ function SerpPreview({
21338
21562
  fontSize: 11
21339
21563
  },
21340
21564
  children: [
21341
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C14.textSecondary, fontWeight: 600 }, children: t.serpPreview.url }),
21565
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C15.textSecondary, fontWeight: 600 }, children: t.serpPreview.url }),
21342
21566
  /* @__PURE__ */ jsxRuntime.jsxs(
21343
21567
  "span",
21344
21568
  {
21345
21569
  style: {
21346
21570
  fontWeight: 700,
21347
21571
  fontVariantNumeric: "tabular-nums",
21348
- color: fullUrl.length <= 75 ? C14.green : C14.red
21572
+ color: fullUrl.length <= 75 ? C15.green : C15.red
21349
21573
  },
21350
21574
  children: [
21351
21575
  fullUrl.length,
@@ -21380,13 +21604,13 @@ function DeviceButton({
21380
21604
  gap: 5,
21381
21605
  padding: "4px 12px",
21382
21606
  borderRadius: 6,
21383
- border: `2px solid ${C14.border}`,
21607
+ border: `2px solid ${C15.border}`,
21384
21608
  fontSize: 11,
21385
21609
  fontWeight: 700,
21386
21610
  cursor: "pointer",
21387
- backgroundColor: active ? C14.cyan : C14.surfaceBg,
21388
- color: active ? C14.black : C14.textPrimary,
21389
- boxShadow: active ? `2px 2px 0 0 ${C14.border}` : "none",
21611
+ backgroundColor: active ? C15.cyan : C15.surfaceBg,
21612
+ color: active ? C15.black : C15.textPrimary,
21613
+ boxShadow: active ? `2px 2px 0 0 ${C15.border}` : "none",
21390
21614
  transition: "background-color 0.15s"
21391
21615
  },
21392
21616
  children: [