@consilioweb/payload-seo-analyzer 1.9.0 → 1.10.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
@@ -15910,7 +15910,7 @@ function getSchemaTypes(t) {
15910
15910
  }
15911
15911
  };
15912
15912
  }
15913
- function buildJsonLd(type, values) {
15913
+ function buildJsonLd2(type, values) {
15914
15914
  switch (type) {
15915
15915
  case "LocalBusiness": {
15916
15916
  const result = {
@@ -16191,7 +16191,7 @@ function SchemaBuilderView() {
16191
16191
  [arrayName]: (prev[arrayName] || []).filter((_, i) => i !== index)
16192
16192
  }));
16193
16193
  }, []);
16194
- const jsonLd = React4.useMemo(() => buildJsonLd(selectedType, values), [selectedType, values]);
16194
+ const jsonLd = React4.useMemo(() => buildJsonLd2(selectedType, values), [selectedType, values]);
16195
16195
  const jsonString = React4.useMemo(() => JSON.stringify(jsonLd, null, 2), [jsonLd]);
16196
16196
  const scriptTag = React4.useMemo(
16197
16197
  () => `<script type="application/ld+json">
@@ -16968,6 +16968,573 @@ function GscPanel({ locale }) {
16968
16968
  ] })
16969
16969
  ] });
16970
16970
  }
16971
+ var C6 = {
16972
+ text: "var(--theme-text, #1a1a1a)",
16973
+ sub: "var(--theme-elevation-600, #6b7280)",
16974
+ card: "var(--theme-elevation-50, #f9fafb)",
16975
+ border: "var(--theme-elevation-200, #e5e7eb)",
16976
+ green: "#22c55e",
16977
+ red: "#ef4444",
16978
+ blue: "#3b82f6"
16979
+ };
16980
+ var S3 = {
16981
+ fr: {
16982
+ title: "Suivi de positions (rank tracking)",
16983
+ subtitle: "Historique quotidien des positions Google (via Search Console) et mouvements dans le temps.",
16984
+ needGsc: "Connectez Google Search Console ci-dessus pour activer le suivi de positions.",
16985
+ snapshot: "Relever maintenant",
16986
+ snapshotting: "Relev\xE9 en cours\u2026",
16987
+ noData: "Pas encore de donn\xE9es. Le relev\xE9 tourne automatiquement chaque jour ; cliquez \xAB Relever maintenant \xBB pour d\xE9marrer.",
16988
+ lastSnapshot: "Dernier relev\xE9",
16989
+ query: "Requ\xEAte",
16990
+ position: "Position",
16991
+ change: "\xC9volution",
16992
+ clicks: "Clics",
16993
+ impressions: "Impr.",
16994
+ stable: "stable",
16995
+ newQ: "nouveau",
16996
+ countLabel: "requ\xEAtes suivies"
16997
+ },
16998
+ en: {
16999
+ title: "Rank tracking",
17000
+ subtitle: "Daily Google position history (via Search Console) and movement over time.",
17001
+ needGsc: "Connect Google Search Console above to enable rank tracking.",
17002
+ snapshot: "Snapshot now",
17003
+ snapshotting: "Snapshotting\u2026",
17004
+ noData: 'No data yet. The snapshot runs automatically every day; click "Snapshot now" to start.',
17005
+ lastSnapshot: "Last snapshot",
17006
+ query: "Query",
17007
+ position: "Position",
17008
+ change: "Change",
17009
+ clicks: "Clicks",
17010
+ impressions: "Impr.",
17011
+ stable: "stable",
17012
+ newQ: "new",
17013
+ countLabel: "tracked queries"
17014
+ }
17015
+ };
17016
+ function RankTrackingPanel({ locale }) {
17017
+ const s = S3[locale] ?? S3.fr;
17018
+ const [movers, setMovers] = React4.useState(null);
17019
+ const [lastSnapshot, setLastSnapshot] = React4.useState(null);
17020
+ const [loading, setLoading] = React4.useState(true);
17021
+ const [busy, setBusy] = React4.useState(false);
17022
+ const [error, setError] = React4.useState(null);
17023
+ const [notConnected, setNotConnected] = React4.useState(false);
17024
+ const load = React4.useCallback(async () => {
17025
+ setLoading(true);
17026
+ setError(null);
17027
+ try {
17028
+ const res = await fetch("/api/seo-plugin/rank-history", { credentials: "include", cache: "no-store" });
17029
+ if (res.status === 403 || res.status === 409) {
17030
+ setNotConnected(true);
17031
+ setMovers(null);
17032
+ return;
17033
+ }
17034
+ const json = await res.json();
17035
+ if (!res.ok) {
17036
+ setError(json.error || `Error ${res.status}`);
17037
+ return;
17038
+ }
17039
+ setMovers(json.movers || []);
17040
+ setLastSnapshot(json.lastSnapshot || null);
17041
+ } catch (e) {
17042
+ setError(e instanceof Error ? e.message : "Network error");
17043
+ } finally {
17044
+ setLoading(false);
17045
+ }
17046
+ }, []);
17047
+ React4.useEffect(() => {
17048
+ void load();
17049
+ }, [load]);
17050
+ const snapshotNow = async () => {
17051
+ setBusy(true);
17052
+ setError(null);
17053
+ try {
17054
+ const res = await fetch("/api/seo-plugin/rank-snapshot", { method: "POST", credentials: "include" });
17055
+ const json = await res.json();
17056
+ if (res.status === 409) {
17057
+ setNotConnected(true);
17058
+ return;
17059
+ }
17060
+ if (!res.ok) {
17061
+ setError(json.error || json.reason || `Error ${res.status}`);
17062
+ return;
17063
+ }
17064
+ await load();
17065
+ } catch (e) {
17066
+ setError(e instanceof Error ? e.message : "Network error");
17067
+ } finally {
17068
+ setBusy(false);
17069
+ }
17070
+ };
17071
+ const card = {
17072
+ padding: 16,
17073
+ borderRadius: 12,
17074
+ border: `1px solid ${C6.border}`,
17075
+ backgroundColor: C6.card,
17076
+ marginBottom: 20
17077
+ };
17078
+ const btn = {
17079
+ padding: "8px 12px",
17080
+ borderRadius: 8,
17081
+ border: `1px solid ${C6.blue}`,
17082
+ backgroundColor: C6.blue,
17083
+ color: "#fff",
17084
+ fontSize: 12,
17085
+ fontWeight: 700,
17086
+ cursor: busy ? "wait" : "pointer",
17087
+ opacity: busy ? 0.6 : 1
17088
+ };
17089
+ const renderDelta = (m) => {
17090
+ if (m.previousPosition === null) {
17091
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C6.sub, fontSize: 11 }, children: s.newQ });
17092
+ }
17093
+ if (Math.abs(m.delta) < 0.1) {
17094
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: C6.sub, fontSize: 11 }, children: [
17095
+ "\u2014 ",
17096
+ s.stable
17097
+ ] });
17098
+ }
17099
+ const up = m.delta > 0;
17100
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: up ? C6.green : C6.red, fontWeight: 700, fontSize: 12 }, children: [
17101
+ up ? "\u25B2" : "\u25BC",
17102
+ " ",
17103
+ Math.abs(m.delta).toFixed(1)
17104
+ ] });
17105
+ };
17106
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: card, children: [
17107
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8, flexWrap: "wrap" }, children: [
17108
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
17109
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 16, fontWeight: 800, color: C6.text }, children: s.title }),
17110
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C6.sub, marginTop: 2 }, children: s.subtitle })
17111
+ ] }),
17112
+ !notConnected && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: snapshotNow, disabled: busy, style: btn, children: busy ? s.snapshotting : s.snapshot })
17113
+ ] }),
17114
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: C6.red, fontSize: 13, fontWeight: 600, marginTop: 10 }, children: error }),
17115
+ notConnected && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C6.sub }, children: s.needGsc }),
17116
+ !notConnected && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 12 }, children: [
17117
+ lastSnapshot && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 11, color: C6.sub, marginBottom: 8 }, children: [
17118
+ s.lastSnapshot,
17119
+ ": ",
17120
+ new Date(lastSnapshot).toLocaleString(locale),
17121
+ movers ? ` \xB7 ${movers.length} ${s.countLabel}` : ""
17122
+ ] }),
17123
+ loading && !movers && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, color: C6.sub }, children: "\u2026" }),
17124
+ movers && movers.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, color: C6.sub }, children: s.noData }),
17125
+ movers && movers.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { overflowX: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsxs("table", { style: { width: "100%", borderCollapse: "collapse", fontSize: 12 }, children: [
17126
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { style: { textAlign: "left", color: C6.sub }, children: [
17127
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: { padding: "6px 8px" }, children: s.query }),
17128
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: { padding: "6px 8px", textAlign: "right" }, children: s.position }),
17129
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: { padding: "6px 8px", textAlign: "right" }, children: s.change }),
17130
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: { padding: "6px 8px", textAlign: "right" }, children: s.clicks }),
17131
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: { padding: "6px 8px", textAlign: "right" }, children: s.impressions })
17132
+ ] }) }),
17133
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: movers.slice(0, 100).map((m, i) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { style: { borderTop: `1px solid ${C6.border}`, color: C6.text }, children: [
17134
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "6px 8px", maxWidth: 320, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: m.query }),
17135
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "6px 8px", textAlign: "right", fontWeight: 700 }, children: m.position.toFixed(1) }),
17136
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "6px 8px", textAlign: "right" }, children: renderDelta(m) }),
17137
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "6px 8px", textAlign: "right" }, children: m.clicks }),
17138
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "6px 8px", textAlign: "right" }, children: m.impressions })
17139
+ ] }, i)) })
17140
+ ] }) })
17141
+ ] })
17142
+ ] });
17143
+ }
17144
+ var C7 = {
17145
+ text: "var(--theme-text, #1a1a1a)",
17146
+ sub: "var(--theme-elevation-600, #6b7280)",
17147
+ card: "var(--theme-elevation-50, #f9fafb)",
17148
+ border: "var(--theme-elevation-200, #e5e7eb)",
17149
+ green: "#22c55e",
17150
+ red: "#ef4444",
17151
+ amber: "#f59e0b",
17152
+ blue: "#3b82f6"
17153
+ };
17154
+ var S4 = {
17155
+ fr: {
17156
+ title: "Monitoring & alertes",
17157
+ subtitle: "Digest p\xE9riodique : r\xE9gressions de score, nouveaux 404, chutes de position (webhook / email).",
17158
+ notConfigured: "Aucun canal configur\xE9. D\xE9finissez SEO_ALERT_WEBHOOK_URL et/ou SEO_ALERT_EMAIL c\xF4t\xE9 serveur, puis activez features.alerts.",
17159
+ webhook: "Webhook",
17160
+ email: "Email",
17161
+ configured: "configur\xE9",
17162
+ missing: "absent",
17163
+ preview: "Aper\xE7u",
17164
+ sendNow: "Envoyer maintenant",
17165
+ sending: "Envoi\u2026",
17166
+ loading: "Chargement\u2026",
17167
+ noIssues: "Aucun probl\xE8me d\xE9tect\xE9 sur la p\xE9riode. \u{1F389}",
17168
+ scoreReg: "R\xE9gressions de score",
17169
+ notFound: "Nouveaux 404",
17170
+ rankDrops: "Chutes de position",
17171
+ sent: "Digest envoy\xE9",
17172
+ nothingToSend: "Rien \xE0 envoyer (aucun probl\xE8me).",
17173
+ issues: "probl\xE8me(s)"
17174
+ },
17175
+ en: {
17176
+ title: "Monitoring & alerts",
17177
+ subtitle: "Periodic digest: score regressions, new 404s, ranking drops (webhook / email).",
17178
+ notConfigured: "No channel configured. Set SEO_ALERT_WEBHOOK_URL and/or SEO_ALERT_EMAIL on the server, then enable features.alerts.",
17179
+ webhook: "Webhook",
17180
+ email: "Email",
17181
+ configured: "configured",
17182
+ missing: "missing",
17183
+ preview: "Preview",
17184
+ sendNow: "Send now",
17185
+ sending: "Sending\u2026",
17186
+ loading: "Loading\u2026",
17187
+ noIssues: "No issues for the period. \u{1F389}",
17188
+ scoreReg: "Score regressions",
17189
+ notFound: "New 404s",
17190
+ rankDrops: "Ranking drops",
17191
+ sent: "Digest sent",
17192
+ nothingToSend: "Nothing to send (no issues).",
17193
+ issues: "issue(s)"
17194
+ }
17195
+ };
17196
+ function AlertsPanel({ locale }) {
17197
+ const s = S4[locale] ?? S4.fr;
17198
+ const [digest, setDigest] = React4.useState(null);
17199
+ const [config, setConfig] = React4.useState(null);
17200
+ const [loading, setLoading] = React4.useState(true);
17201
+ const [busy, setBusy] = React4.useState(false);
17202
+ const [error, setError] = React4.useState(null);
17203
+ const [notice, setNotice] = React4.useState(null);
17204
+ const load = React4.useCallback(async () => {
17205
+ setLoading(true);
17206
+ setError(null);
17207
+ try {
17208
+ const res = await fetch("/api/seo-plugin/alerts-digest", { credentials: "include", cache: "no-store" });
17209
+ if (res.status === 404 || res.status === 403) {
17210
+ setConfig({ webhookConfigured: false, emailConfigured: false, scoreDrop: 0, positionDrop: 0, windowHours: 0 });
17211
+ setDigest(null);
17212
+ return;
17213
+ }
17214
+ const json = await res.json();
17215
+ if (!res.ok) {
17216
+ setError(json.error || `Error ${res.status}`);
17217
+ return;
17218
+ }
17219
+ setDigest(json.digest);
17220
+ setConfig(json.config);
17221
+ } catch (e) {
17222
+ setError(e instanceof Error ? e.message : "Network error");
17223
+ } finally {
17224
+ setLoading(false);
17225
+ }
17226
+ }, []);
17227
+ React4.useEffect(() => {
17228
+ void load();
17229
+ }, [load]);
17230
+ const sendNow = async () => {
17231
+ setBusy(true);
17232
+ setError(null);
17233
+ setNotice(null);
17234
+ try {
17235
+ const res = await fetch("/api/seo-plugin/alerts-run", { method: "POST", credentials: "include" });
17236
+ const json = await res.json();
17237
+ if (!res.ok) {
17238
+ setError(json.error || `Error ${res.status}`);
17239
+ return;
17240
+ }
17241
+ setNotice(json.delivery?.sent ? s.sent : s.nothingToSend);
17242
+ if (json.digest) setDigest(json.digest);
17243
+ } catch (e) {
17244
+ setError(e instanceof Error ? e.message : "Network error");
17245
+ } finally {
17246
+ setBusy(false);
17247
+ }
17248
+ };
17249
+ const card = {
17250
+ padding: 16,
17251
+ borderRadius: 12,
17252
+ border: `1px solid ${C7.border}`,
17253
+ backgroundColor: C7.card,
17254
+ marginBottom: 20
17255
+ };
17256
+ const btn = {
17257
+ padding: "8px 12px",
17258
+ borderRadius: 8,
17259
+ border: `1px solid ${C7.blue}`,
17260
+ backgroundColor: C7.blue,
17261
+ color: "#fff",
17262
+ fontSize: 12,
17263
+ fontWeight: 700,
17264
+ cursor: busy ? "wait" : "pointer",
17265
+ opacity: busy ? 0.6 : 1
17266
+ };
17267
+ const chip = (ok, label) => ({
17268
+ fontSize: 11,
17269
+ fontWeight: 700,
17270
+ padding: "3px 8px",
17271
+ borderRadius: 999,
17272
+ color: "#fff",
17273
+ backgroundColor: ok ? C7.green : C7.sub,
17274
+ marginRight: 6
17275
+ });
17276
+ const hasChannel = config && (config.webhookConfigured || config.emailConfigured);
17277
+ const list = (title, rows) => rows.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 10 }, children: [
17278
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, fontWeight: 700, color: C7.text, marginBottom: 4 }, children: [
17279
+ title,
17280
+ " ",
17281
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: C7.amber }, children: [
17282
+ "(",
17283
+ rows.length,
17284
+ ")"
17285
+ ] })
17286
+ ] }),
17287
+ /* @__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)) })
17288
+ ] }) : null;
17289
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: card, children: [
17290
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8, flexWrap: "wrap" }, children: [
17291
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
17292
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 16, fontWeight: 800, color: C7.text }, children: s.title }),
17293
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C7.sub, marginTop: 2 }, children: s.subtitle })
17294
+ ] }),
17295
+ hasChannel && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: sendNow, disabled: busy, style: btn, children: busy ? s.sending : s.sendNow })
17296
+ ] }),
17297
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: C7.red, fontSize: 13, fontWeight: 600, marginTop: 10 }, children: error }),
17298
+ notice && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: C7.green, fontSize: 13, fontWeight: 600, marginTop: 10 }, children: notice }),
17299
+ config && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 12 }, children: [
17300
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: chip(config.webhookConfigured, s.webhook), children: [
17301
+ s.webhook,
17302
+ ": ",
17303
+ config.webhookConfigured ? s.configured : s.missing
17304
+ ] }),
17305
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: chip(config.emailConfigured, s.email), children: [
17306
+ s.email,
17307
+ ": ",
17308
+ config.emailConfigured ? s.configured : s.missing
17309
+ ] })
17310
+ ] }),
17311
+ !loading && !hasChannel && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C7.sub }, children: s.notConfigured }),
17312
+ loading && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C7.sub }, children: s.loading }),
17313
+ digest && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 8 }, children: [
17314
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, color: C7.sub, marginTop: 6 }, children: [
17315
+ digest.totalIssues,
17316
+ " ",
17317
+ s.issues
17318
+ ] }),
17319
+ digest.totalIssues === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 8, fontSize: 13, color: C7.sub }, children: s.noIssues }),
17320
+ list(
17321
+ s.scoreReg,
17322
+ digest.scoreRegressions.map((r) => `${r.collection}/${r.documentId} \u2014 ${r.from} \u2192 ${r.to} (\u2212${r.drop})`)
17323
+ ),
17324
+ list(s.notFound, digest.newNotFound.map((n) => `${n.url} \u2014 ${n.count}\xD7`)),
17325
+ list(s.rankDrops, digest.rankDrops.map((d) => `\u201C${d.query}\u201D \u2014 #${d.from} \u2192 #${d.to} (\u25BC${d.drop})`))
17326
+ ] })
17327
+ ] });
17328
+ }
17329
+ var C8 = {
17330
+ text: "var(--theme-text, #1a1a1a)",
17331
+ sub: "var(--theme-elevation-600, #6b7280)",
17332
+ card: "var(--theme-elevation-50, #f9fafb)",
17333
+ bg: "var(--theme-elevation-0, #fff)",
17334
+ border: "var(--theme-elevation-200, #e5e7eb)",
17335
+ green: "#22c55e",
17336
+ red: "#ef4444",
17337
+ violet: "#7c3aed"
17338
+ };
17339
+ var S5 = {
17340
+ fr: {
17341
+ title: "Alt-text IA des images",
17342
+ subtitle: "G\xE9n\xE8re l'attribut alt des images qui n'en ont pas (Claude vision), pour l'accessibilit\xE9 et le SEO.",
17343
+ none: "Toutes les images ont un alt. \u{1F389}",
17344
+ forbidden: "R\xE9serv\xE9 aux administrateurs.",
17345
+ disabled: "Fonction IA d\xE9sactiv\xE9e (features.aiFeatures).",
17346
+ missing: "image(s) sans alt",
17347
+ generate: "G\xE9n\xE9rer",
17348
+ generating: "\u2026",
17349
+ apply: "Appliquer",
17350
+ applied: "Appliqu\xE9 \u2713",
17351
+ noKey: "Cl\xE9 API Claude requise (ANTHROPIC_API_KEY).",
17352
+ loading: "Chargement\u2026",
17353
+ refresh: "Rafra\xEEchir"
17354
+ },
17355
+ en: {
17356
+ title: "AI image alt-text",
17357
+ subtitle: "Generate alt text for images that lack one (Claude vision), for accessibility and SEO.",
17358
+ none: "All images have alt text. \u{1F389}",
17359
+ forbidden: "Admins only.",
17360
+ disabled: "AI feature disabled (features.aiFeatures).",
17361
+ missing: "image(s) without alt",
17362
+ generate: "Generate",
17363
+ generating: "\u2026",
17364
+ apply: "Apply",
17365
+ applied: "Applied \u2713",
17366
+ noKey: "Claude API key required (ANTHROPIC_API_KEY).",
17367
+ loading: "Loading\u2026",
17368
+ refresh: "Refresh"
17369
+ }
17370
+ };
17371
+ function AltTextPanel({ locale }) {
17372
+ const s = S5[locale] ?? S5.fr;
17373
+ const [items, setItems] = React4.useState(null);
17374
+ const [collection, setCollection] = React4.useState("media");
17375
+ const [missingCount, setMissingCount] = React4.useState(0);
17376
+ const [loading, setLoading] = React4.useState(true);
17377
+ const [state, setState] = React4.useState({});
17378
+ const [status, setStatus] = React4.useState("ok");
17379
+ const load = React4.useCallback(async () => {
17380
+ setLoading(true);
17381
+ try {
17382
+ const res = await fetch("/api/seo-plugin/alt-text-audit", { credentials: "include", cache: "no-store" });
17383
+ if (res.status === 404) {
17384
+ setStatus("disabled");
17385
+ return;
17386
+ }
17387
+ if (res.status === 403) {
17388
+ setStatus("forbidden");
17389
+ return;
17390
+ }
17391
+ const json = await res.json();
17392
+ setStatus("ok");
17393
+ setItems(json.items || []);
17394
+ setMissingCount(json.missingCount || 0);
17395
+ setCollection(json.collection || "media");
17396
+ } catch {
17397
+ setItems([]);
17398
+ } finally {
17399
+ setLoading(false);
17400
+ }
17401
+ }, []);
17402
+ React4.useEffect(() => {
17403
+ void load();
17404
+ }, [load]);
17405
+ const setRow = (id, patch) => setState((prev) => ({ ...prev, [id]: { ...prev[id], ...patch } }));
17406
+ const generate = async (item) => {
17407
+ setRow(item.id, { busy: true, error: void 0 });
17408
+ try {
17409
+ const res = await fetch("/api/seo-plugin/ai-alt-text", {
17410
+ method: "POST",
17411
+ credentials: "include",
17412
+ headers: { "Content-Type": "application/json" },
17413
+ body: JSON.stringify({ collection, id: item.id, apply: false })
17414
+ });
17415
+ const json = await res.json();
17416
+ if (!res.ok) {
17417
+ setRow(item.id, { busy: false, error: json.code === "no_api_key" ? s.noKey : json.error || `Error ${res.status}` });
17418
+ return;
17419
+ }
17420
+ setRow(item.id, { busy: false, alt: json.alt });
17421
+ } catch (e) {
17422
+ setRow(item.id, { busy: false, error: e instanceof Error ? e.message : "Network error" });
17423
+ }
17424
+ };
17425
+ const apply = async (item) => {
17426
+ const alt = state[item.id]?.alt;
17427
+ if (!alt) return;
17428
+ setRow(item.id, { busy: true, error: void 0 });
17429
+ try {
17430
+ const res = await fetch("/api/seo-plugin/ai-alt-text", {
17431
+ method: "POST",
17432
+ credentials: "include",
17433
+ headers: { "Content-Type": "application/json" },
17434
+ body: JSON.stringify({ collection, id: item.id, apply: true, altText: alt })
17435
+ });
17436
+ const json = await res.json();
17437
+ if (!res.ok) {
17438
+ setRow(item.id, { busy: false, error: json.error || `Error ${res.status}` });
17439
+ return;
17440
+ }
17441
+ setRow(item.id, { busy: false, applied: true });
17442
+ } catch (e) {
17443
+ setRow(item.id, { busy: false, error: e instanceof Error ? e.message : "Network error" });
17444
+ }
17445
+ };
17446
+ const card = {
17447
+ padding: 16,
17448
+ borderRadius: 12,
17449
+ border: `1px solid ${C8.border}`,
17450
+ backgroundColor: C8.card,
17451
+ marginBottom: 20
17452
+ };
17453
+ const btn = (bg) => ({
17454
+ padding: "6px 10px",
17455
+ borderRadius: 6,
17456
+ border: `1px solid ${bg}`,
17457
+ backgroundColor: bg,
17458
+ color: "#fff",
17459
+ fontSize: 11,
17460
+ fontWeight: 700,
17461
+ cursor: "pointer"
17462
+ });
17463
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: card, children: [
17464
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8, flexWrap: "wrap" }, children: [
17465
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
17466
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 16, fontWeight: 800, color: C8.text }, children: s.title }),
17467
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C8.sub, marginTop: 2 }, children: s.subtitle })
17468
+ ] }),
17469
+ status === "ok" && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void load(), style: btn(C8.sub), children: s.refresh })
17470
+ ] }),
17471
+ status === "forbidden" && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C8.sub }, children: s.forbidden }),
17472
+ status === "disabled" && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C8.sub }, children: s.disabled }),
17473
+ status === "ok" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 12 }, children: [
17474
+ loading && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, color: C8.sub }, children: s.loading }),
17475
+ !loading && items && items.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, color: C8.sub }, children: s.none }),
17476
+ !loading && items && items.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
17477
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, color: C8.sub, marginBottom: 10 }, children: [
17478
+ missingCount,
17479
+ " ",
17480
+ s.missing
17481
+ ] }),
17482
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: items.map((item) => {
17483
+ const rs = state[item.id] || {};
17484
+ return /* @__PURE__ */ jsxRuntime.jsxs(
17485
+ "div",
17486
+ {
17487
+ style: {
17488
+ display: "flex",
17489
+ gap: 12,
17490
+ alignItems: "center",
17491
+ padding: 8,
17492
+ borderRadius: 8,
17493
+ border: `1px solid ${C8.border}`,
17494
+ backgroundColor: C8.bg
17495
+ },
17496
+ children: [
17497
+ /* @__PURE__ */ jsxRuntime.jsx(
17498
+ "img",
17499
+ {
17500
+ src: item.url,
17501
+ alt: "",
17502
+ style: { width: 48, height: 48, objectFit: "cover", borderRadius: 6, flexShrink: 0, border: `1px solid ${C8.border}` }
17503
+ }
17504
+ ),
17505
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
17506
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: C8.sub, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: item.filename }),
17507
+ rs.alt !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
17508
+ "input",
17509
+ {
17510
+ value: rs.alt,
17511
+ onChange: (e) => setRow(item.id, { alt: e.target.value }),
17512
+ disabled: rs.applied,
17513
+ maxLength: 125,
17514
+ style: {
17515
+ width: "100%",
17516
+ marginTop: 4,
17517
+ padding: "4px 8px",
17518
+ fontSize: 12,
17519
+ borderRadius: 6,
17520
+ border: `1px solid ${C8.border}`,
17521
+ backgroundColor: C8.bg,
17522
+ color: C8.text
17523
+ }
17524
+ }
17525
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C8.sub, marginTop: 4, fontStyle: "italic" }, children: "\u2014" }),
17526
+ rs.error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: C8.red, marginTop: 2 }, children: rs.error })
17527
+ ] }),
17528
+ /* @__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 }) })
17529
+ ]
17530
+ },
17531
+ item.id
17532
+ );
17533
+ }) })
17534
+ ] })
17535
+ ] })
17536
+ ] });
17537
+ }
16971
17538
  var V8 = {
16972
17539
  text: "var(--theme-text, #1a1a1a)",
16973
17540
  textSecondary: "var(--theme-elevation-600, #6b7280)",
@@ -17382,6 +17949,9 @@ function PerformanceView() {
17382
17949
  ),
17383
17950
  /* @__PURE__ */ jsxRuntime.jsx(CoreWebVitalsPanel, { locale }),
17384
17951
  /* @__PURE__ */ jsxRuntime.jsx(GscPanel, { locale }),
17952
+ /* @__PURE__ */ jsxRuntime.jsx(RankTrackingPanel, { locale }),
17953
+ /* @__PURE__ */ jsxRuntime.jsx(AlertsPanel, { locale }),
17954
+ /* @__PURE__ */ jsxRuntime.jsx(AltTextPanel, { locale }),
17385
17955
  showImport && /* @__PURE__ */ jsxRuntime.jsxs(
17386
17956
  "div",
17387
17957
  {
@@ -19041,7 +19611,7 @@ var controlBtnStyle = {
19041
19611
  cursor: "pointer",
19042
19612
  lineHeight: 1.4
19043
19613
  };
19044
- var C6 = {
19614
+ var C9 = {
19045
19615
  cyan: "#00E5FF",
19046
19616
  black: "#000",
19047
19617
  green: "#22c55e",
@@ -19056,10 +19626,10 @@ var C6 = {
19056
19626
  var TITLE_MIN = 30;
19057
19627
  var TITLE_MAX = 60;
19058
19628
  function getCharColor(len) {
19059
- if (len === 0) return C6.textSecondary;
19060
- if (len >= TITLE_MIN && len <= TITLE_MAX) return C6.green;
19061
- if (len > 0 && len < TITLE_MIN) return C6.orange;
19062
- return C6.red;
19629
+ if (len === 0) return C9.textSecondary;
19630
+ if (len >= TITLE_MIN && len <= TITLE_MAX) return C9.green;
19631
+ if (len > 0 && len < TITLE_MIN) return C9.orange;
19632
+ return C9.red;
19063
19633
  }
19064
19634
  function getProgressPercent(len) {
19065
19635
  if (len === 0) return 0;
@@ -19067,9 +19637,9 @@ function getProgressPercent(len) {
19067
19637
  }
19068
19638
  function getProgressColor(len) {
19069
19639
  if (len === 0) return "var(--theme-elevation-200, #e5e7eb)";
19070
- if (len >= TITLE_MIN && len <= TITLE_MAX) return C6.green;
19071
- if (len < TITLE_MIN) return C6.orange;
19072
- return C6.red;
19640
+ if (len >= TITLE_MIN && len <= TITLE_MAX) return C9.green;
19641
+ if (len < TITLE_MIN) return C9.orange;
19642
+ return C9.red;
19073
19643
  }
19074
19644
  function MetaTitleField({
19075
19645
  path,
@@ -19140,7 +19710,7 @@ function MetaTitleField({
19140
19710
  style: {
19141
19711
  fontSize: 13,
19142
19712
  fontWeight: 700,
19143
- color: C6.textPrimary
19713
+ color: C9.textPrimary
19144
19714
  },
19145
19715
  children: t.metaTitle.label
19146
19716
  }
@@ -19180,9 +19750,9 @@ function MetaTitleField({
19180
19750
  fontSize: 14,
19181
19751
  fontFamily: "inherit",
19182
19752
  borderRadius: 8,
19183
- border: `2px solid ${C6.border}`,
19184
- backgroundColor: C6.surfaceBg,
19185
- color: C6.textPrimary,
19753
+ border: `2px solid ${C9.border}`,
19754
+ backgroundColor: C9.surfaceBg,
19755
+ color: C9.textPrimary,
19186
19756
  outline: "none",
19187
19757
  boxShadow: "2px 2px 0 0 var(--theme-border-color, rgba(0,0,0,1))"
19188
19758
  }
@@ -19200,9 +19770,9 @@ function MetaTitleField({
19200
19770
  gap: 5,
19201
19771
  padding: "8px 14px",
19202
19772
  borderRadius: 8,
19203
- border: `2px solid ${C6.border}`,
19204
- backgroundColor: loading ? C6.surface50 : C6.cyan,
19205
- color: loading ? C6.textSecondary : C6.black,
19773
+ border: `2px solid ${C9.border}`,
19774
+ backgroundColor: loading ? C9.surface50 : C9.cyan,
19775
+ color: loading ? C9.textSecondary : C9.black,
19206
19776
  fontWeight: 800,
19207
19777
  fontSize: 11,
19208
19778
  textTransform: "uppercase",
@@ -19249,7 +19819,7 @@ function MetaTitleField({
19249
19819
  justifyContent: "space-between",
19250
19820
  marginTop: 4,
19251
19821
  fontSize: 10,
19252
- color: C6.textSecondary
19822
+ color: C9.textSecondary
19253
19823
  },
19254
19824
  children: [
19255
19825
  /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
@@ -19283,9 +19853,9 @@ function MetaTitleField({
19283
19853
  borderRadius: 6,
19284
19854
  fontSize: 11,
19285
19855
  fontWeight: 600,
19286
- color: C6.red,
19856
+ color: C9.red,
19287
19857
  backgroundColor: "rgba(239,68,68,0.08)",
19288
- border: `1px solid ${C6.red}`
19858
+ border: `1px solid ${C9.red}`
19289
19859
  },
19290
19860
  children: error
19291
19861
  }
@@ -19294,7 +19864,7 @@ function MetaTitleField({
19294
19864
  }
19295
19865
  );
19296
19866
  }
19297
- var C7 = {
19867
+ var C10 = {
19298
19868
  cyan: "#00E5FF",
19299
19869
  black: "#000",
19300
19870
  green: "#22c55e",
@@ -19309,10 +19879,10 @@ var C7 = {
19309
19879
  var DESC_MIN = 120;
19310
19880
  var DESC_MAX = 160;
19311
19881
  function getCharColor2(len) {
19312
- if (len === 0) return C7.textSecondary;
19313
- if (len >= DESC_MIN && len <= DESC_MAX) return C7.green;
19314
- if (len > 0 && len < DESC_MIN) return C7.orange;
19315
- return C7.red;
19882
+ if (len === 0) return C10.textSecondary;
19883
+ if (len >= DESC_MIN && len <= DESC_MAX) return C10.green;
19884
+ if (len > 0 && len < DESC_MIN) return C10.orange;
19885
+ return C10.red;
19316
19886
  }
19317
19887
  function getProgressPercent2(len) {
19318
19888
  if (len === 0) return 0;
@@ -19320,9 +19890,9 @@ function getProgressPercent2(len) {
19320
19890
  }
19321
19891
  function getProgressColor2(len) {
19322
19892
  if (len === 0) return "var(--theme-elevation-200, #e5e7eb)";
19323
- if (len >= DESC_MIN && len <= DESC_MAX) return C7.green;
19324
- if (len < DESC_MIN) return C7.orange;
19325
- return C7.red;
19893
+ if (len >= DESC_MIN && len <= DESC_MAX) return C10.green;
19894
+ if (len < DESC_MIN) return C10.orange;
19895
+ return C10.red;
19326
19896
  }
19327
19897
  function MetaDescriptionField({
19328
19898
  path,
@@ -19393,7 +19963,7 @@ function MetaDescriptionField({
19393
19963
  style: {
19394
19964
  fontSize: 13,
19395
19965
  fontWeight: 700,
19396
- color: C7.textPrimary
19966
+ color: C10.textPrimary
19397
19967
  },
19398
19968
  children: t.metaDescription.label
19399
19969
  }
@@ -19433,9 +20003,9 @@ function MetaDescriptionField({
19433
20003
  fontSize: 14,
19434
20004
  fontFamily: "inherit",
19435
20005
  borderRadius: 8,
19436
- border: `2px solid ${C7.border}`,
19437
- backgroundColor: C7.surfaceBg,
19438
- color: C7.textPrimary,
20006
+ border: `2px solid ${C10.border}`,
20007
+ backgroundColor: C10.surfaceBg,
20008
+ color: C10.textPrimary,
19439
20009
  outline: "none",
19440
20010
  resize: "vertical",
19441
20011
  lineHeight: 1.5,
@@ -19455,9 +20025,9 @@ function MetaDescriptionField({
19455
20025
  gap: 5,
19456
20026
  padding: "8px 14px",
19457
20027
  borderRadius: 8,
19458
- border: `2px solid ${C7.border}`,
19459
- backgroundColor: loading ? C7.surface50 : C7.cyan,
19460
- color: loading ? C7.textSecondary : C7.black,
20028
+ border: `2px solid ${C10.border}`,
20029
+ backgroundColor: loading ? C10.surface50 : C10.cyan,
20030
+ color: loading ? C10.textSecondary : C10.black,
19461
20031
  fontWeight: 800,
19462
20032
  fontSize: 11,
19463
20033
  textTransform: "uppercase",
@@ -19505,7 +20075,7 @@ function MetaDescriptionField({
19505
20075
  justifyContent: "space-between",
19506
20076
  marginTop: 4,
19507
20077
  fontSize: 10,
19508
- color: C7.textSecondary
20078
+ color: C10.textSecondary
19509
20079
  },
19510
20080
  children: [
19511
20081
  /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
@@ -19539,9 +20109,9 @@ function MetaDescriptionField({
19539
20109
  borderRadius: 6,
19540
20110
  fontSize: 11,
19541
20111
  fontWeight: 600,
19542
- color: C7.red,
20112
+ color: C10.red,
19543
20113
  backgroundColor: "rgba(239,68,68,0.08)",
19544
- border: `1px solid ${C7.red}`
20114
+ border: `1px solid ${C10.red}`
19545
20115
  },
19546
20116
  children: error
19547
20117
  }
@@ -19550,7 +20120,7 @@ function MetaDescriptionField({
19550
20120
  }
19551
20121
  );
19552
20122
  }
19553
- var C8 = {
20123
+ var C11 = {
19554
20124
  cyan: "#00E5FF",
19555
20125
  black: "#000",
19556
20126
  white: "#fff",
@@ -19627,8 +20197,8 @@ function MetaImageField({
19627
20197
  gap: 10,
19628
20198
  padding: "10px 14px",
19629
20199
  borderRadius: 8,
19630
- border: `2px solid ${C8.border}`,
19631
- backgroundColor: C8.surfaceBg,
20200
+ border: `2px solid ${C11.border}`,
20201
+ backgroundColor: C11.surfaceBg,
19632
20202
  boxShadow: "2px 2px 0 0 var(--theme-border-color, rgba(0,0,0,1))"
19633
20203
  },
19634
20204
  children: [
@@ -19647,7 +20217,7 @@ function MetaImageField({
19647
20217
  fontWeight: 900,
19648
20218
  backgroundColor: hasImage ? "rgba(34,197,94,0.15)" : "rgba(255,138,0,0.15)",
19649
20219
  color: hasImage ? "#16a34a" : "#d97706",
19650
- border: `1px solid ${hasImage ? C8.green : C8.orange}`
20220
+ border: `1px solid ${hasImage ? C11.green : C11.orange}`
19651
20221
  },
19652
20222
  children: hasImage ? "\u2713" : "!"
19653
20223
  }
@@ -19659,7 +20229,7 @@ function MetaImageField({
19659
20229
  style: {
19660
20230
  fontSize: 12,
19661
20231
  fontWeight: 700,
19662
- color: C8.textPrimary
20232
+ color: C11.textPrimary
19663
20233
  },
19664
20234
  children: t.metaImage.label
19665
20235
  }
@@ -19669,7 +20239,7 @@ function MetaImageField({
19669
20239
  {
19670
20240
  style: {
19671
20241
  fontSize: 10,
19672
- color: C8.textSecondary,
20242
+ color: C11.textSecondary,
19673
20243
  lineHeight: 1.4
19674
20244
  },
19675
20245
  children: hasImage ? t.metaImage.imageSet : t.metaImage.noImage
@@ -19689,9 +20259,9 @@ function MetaImageField({
19689
20259
  gap: 5,
19690
20260
  padding: "8px 14px",
19691
20261
  borderRadius: 8,
19692
- border: `2px solid ${C8.border}`,
19693
- backgroundColor: loading ? C8.surface50 : success ? C8.green : C8.cyan,
19694
- color: loading ? C8.textSecondary : success ? C8.white : C8.black,
20262
+ border: `2px solid ${C11.border}`,
20263
+ backgroundColor: loading ? C11.surface50 : success ? C11.green : C11.cyan,
20264
+ color: loading ? C11.textSecondary : success ? C11.white : C11.black,
19695
20265
  fontWeight: 800,
19696
20266
  fontSize: 11,
19697
20267
  textTransform: "uppercase",
@@ -19718,9 +20288,9 @@ function MetaImageField({
19718
20288
  borderRadius: 6,
19719
20289
  fontSize: 11,
19720
20290
  fontWeight: 600,
19721
- color: C8.red,
20291
+ color: C11.red,
19722
20292
  backgroundColor: "rgba(239,68,68,0.08)",
19723
- border: `1px solid ${C8.red}`
20293
+ border: `1px solid ${C11.red}`
19724
20294
  },
19725
20295
  children: error
19726
20296
  }
@@ -19729,7 +20299,7 @@ function MetaImageField({
19729
20299
  }
19730
20300
  );
19731
20301
  }
19732
- var C9 = {
20302
+ var C12 = {
19733
20303
  black: "#000",
19734
20304
  white: "#fff",
19735
20305
  green: "#22c55e",
@@ -19743,15 +20313,15 @@ var C9 = {
19743
20313
  function getCompletenessColor(count) {
19744
20314
  switch (count) {
19745
20315
  case 0:
19746
- return C9.red;
20316
+ return C12.red;
19747
20317
  case 1:
19748
- return C9.orange;
20318
+ return C12.orange;
19749
20319
  case 2:
19750
- return C9.yellow;
20320
+ return C12.yellow;
19751
20321
  case 3:
19752
- return C9.green;
20322
+ return C12.green;
19753
20323
  default:
19754
- return C9.textSecondary;
20324
+ return C12.textSecondary;
19755
20325
  }
19756
20326
  }
19757
20327
  function getCompletenessLabel(count, ov) {
@@ -19809,8 +20379,8 @@ function OverviewField({
19809
20379
  fontFamily: "var(--font-body, Inter, system-ui, sans-serif)",
19810
20380
  padding: "12px 14px",
19811
20381
  borderRadius: 10,
19812
- border: `2px solid ${C9.border}`,
19813
- backgroundColor: C9.surfaceBg,
20382
+ border: `2px solid ${C12.border}`,
20383
+ backgroundColor: C12.surfaceBg,
19814
20384
  boxShadow: "3px 3px 0 0 var(--theme-border-color, rgba(0,0,0,1))",
19815
20385
  marginBottom: 12
19816
20386
  },
@@ -19833,7 +20403,7 @@ function OverviewField({
19833
20403
  fontWeight: 800,
19834
20404
  textTransform: "uppercase",
19835
20405
  letterSpacing: "0.04em",
19836
- color: C9.textPrimary
20406
+ color: C12.textPrimary
19837
20407
  },
19838
20408
  children: t.overview.metaCompleteness
19839
20409
  }
@@ -19848,8 +20418,8 @@ function OverviewField({
19848
20418
  fontSize: 11,
19849
20419
  fontWeight: 800,
19850
20420
  backgroundColor: completenessColor,
19851
- color: completenessColor === C9.yellow ? C9.black : C9.white,
19852
- border: `2px solid ${C9.border}`,
20421
+ color: completenessColor === C12.yellow ? C12.black : C12.white,
20422
+ border: `2px solid ${C12.border}`,
19853
20423
  textTransform: "uppercase",
19854
20424
  letterSpacing: "0.03em"
19855
20425
  },
@@ -19947,7 +20517,7 @@ function OverviewField({
19947
20517
  style: {
19948
20518
  fontSize: 12,
19949
20519
  fontWeight: 600,
19950
- color: item.filled ? C9.textPrimary : C9.textSecondary
20520
+ color: item.filled ? C12.textPrimary : C12.textSecondary
19951
20521
  },
19952
20522
  children: item.label
19953
20523
  }
@@ -19959,7 +20529,7 @@ function OverviewField({
19959
20529
  marginLeft: "auto",
19960
20530
  fontSize: 10,
19961
20531
  fontWeight: 700,
19962
- color: item.filled ? C9.green : C9.red,
20532
+ color: item.filled ? C12.green : C12.red,
19963
20533
  textTransform: "uppercase",
19964
20534
  letterSpacing: "0.03em"
19965
20535
  },
@@ -19976,7 +20546,7 @@ function OverviewField({
19976
20546
  }
19977
20547
  );
19978
20548
  }
19979
- var C10 = {
20549
+ var C13 = {
19980
20550
  cyan: "#00E5FF",
19981
20551
  black: "#000",
19982
20552
  white: "#fff",
@@ -19995,10 +20565,10 @@ var G = {
19995
20565
  descGrey: "#4d5156",
19996
20566
  faviconBg: "#e8eaed"};
19997
20567
  function charCountColor2(len, min, max) {
19998
- if (len >= min && len <= max) return C10.green;
19999
- if (len > 0 && len < min) return C10.orange;
20000
- if (len > max) return C10.red;
20001
- return C10.textSecondary;
20568
+ if (len >= min && len <= max) return C13.green;
20569
+ if (len > 0 && len < min) return C13.orange;
20570
+ if (len > max) return C13.red;
20571
+ return C13.textSecondary;
20002
20572
  }
20003
20573
  function truncateText(text, maxChars) {
20004
20574
  if (text.length <= maxChars) return text;
@@ -20053,8 +20623,8 @@ function SerpPreview({
20053
20623
  padding: "10px 12px",
20054
20624
  cursor: "pointer",
20055
20625
  borderRadius: 8,
20056
- border: `2px solid ${C10.border}`,
20057
- backgroundColor: C10.surface50,
20626
+ border: `2px solid ${C13.border}`,
20627
+ backgroundColor: C13.surface50,
20058
20628
  userSelect: "none"
20059
20629
  },
20060
20630
  children: [
@@ -20069,7 +20639,7 @@ function SerpPreview({
20069
20639
  fontWeight: 800,
20070
20640
  textTransform: "uppercase",
20071
20641
  letterSpacing: "0.04em",
20072
- color: C10.textPrimary
20642
+ color: C13.textPrimary
20073
20643
  },
20074
20644
  children: [
20075
20645
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -20101,7 +20671,7 @@ function SerpPreview({
20101
20671
  transition: "transform 0.2s",
20102
20672
  display: "inline-block",
20103
20673
  transform: open ? "rotate(90deg)" : "none",
20104
- color: C10.textSecondary
20674
+ color: C13.textSecondary
20105
20675
  },
20106
20676
  children: "\u25B6"
20107
20677
  }
@@ -20134,10 +20704,10 @@ function SerpPreview({
20134
20704
  "div",
20135
20705
  {
20136
20706
  style: {
20137
- backgroundColor: C10.white,
20138
- border: `2px solid ${C10.border}`,
20707
+ backgroundColor: C13.white,
20708
+ border: `2px solid ${C13.border}`,
20139
20709
  borderRadius: 12,
20140
- boxShadow: `3px 3px 0 0 ${C10.border}`,
20710
+ boxShadow: `3px 3px 0 0 ${C13.border}`,
20141
20711
  padding: isDesktop ? 20 : 14,
20142
20712
  maxWidth: isDesktop ? 650 : 380,
20143
20713
  overflow: "hidden"
@@ -20200,7 +20770,7 @@ function SerpPreview({
20200
20770
  style: {
20201
20771
  fontSize: 14,
20202
20772
  fontWeight: 400,
20203
- color: C10.black,
20773
+ color: C13.black,
20204
20774
  lineHeight: 1.3,
20205
20775
  whiteSpace: "nowrap",
20206
20776
  overflow: "hidden",
@@ -20264,7 +20834,7 @@ function SerpPreview({
20264
20834
  "span",
20265
20835
  {
20266
20836
  style: {
20267
- color: C10.textSecondary,
20837
+ color: C13.textSecondary,
20268
20838
  fontStyle: "italic",
20269
20839
  fontSize: titleFontSize - 2
20270
20840
  },
@@ -20293,7 +20863,7 @@ function SerpPreview({
20293
20863
  "span",
20294
20864
  {
20295
20865
  style: {
20296
- color: C10.textSecondary,
20866
+ color: C13.textSecondary,
20297
20867
  fontStyle: "italic",
20298
20868
  fontSize: descFontSize - 1
20299
20869
  },
@@ -20326,7 +20896,7 @@ function SerpPreview({
20326
20896
  fontSize: 11
20327
20897
  },
20328
20898
  children: [
20329
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C10.textSecondary, fontWeight: 600 }, children: t.serpPreview.previewTitle }),
20899
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C13.textSecondary, fontWeight: 600 }, children: t.serpPreview.previewTitle }),
20330
20900
  /* @__PURE__ */ jsxRuntime.jsxs(
20331
20901
  "span",
20332
20902
  {
@@ -20355,7 +20925,7 @@ function SerpPreview({
20355
20925
  fontSize: 11
20356
20926
  },
20357
20927
  children: [
20358
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C10.textSecondary, fontWeight: 600 }, children: t.serpPreview.previewDescription }),
20928
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C13.textSecondary, fontWeight: 600 }, children: t.serpPreview.previewDescription }),
20359
20929
  /* @__PURE__ */ jsxRuntime.jsxs(
20360
20930
  "span",
20361
20931
  {
@@ -20384,14 +20954,14 @@ function SerpPreview({
20384
20954
  fontSize: 11
20385
20955
  },
20386
20956
  children: [
20387
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C10.textSecondary, fontWeight: 600 }, children: t.serpPreview.url }),
20957
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C13.textSecondary, fontWeight: 600 }, children: t.serpPreview.url }),
20388
20958
  /* @__PURE__ */ jsxRuntime.jsxs(
20389
20959
  "span",
20390
20960
  {
20391
20961
  style: {
20392
20962
  fontWeight: 700,
20393
20963
  fontVariantNumeric: "tabular-nums",
20394
- color: fullUrl.length <= 75 ? C10.green : C10.red
20964
+ color: fullUrl.length <= 75 ? C13.green : C13.red
20395
20965
  },
20396
20966
  children: [
20397
20967
  fullUrl.length,
@@ -20426,13 +20996,13 @@ function DeviceButton({
20426
20996
  gap: 5,
20427
20997
  padding: "4px 12px",
20428
20998
  borderRadius: 6,
20429
- border: `2px solid ${C10.border}`,
20999
+ border: `2px solid ${C13.border}`,
20430
21000
  fontSize: 11,
20431
21001
  fontWeight: 700,
20432
21002
  cursor: "pointer",
20433
- backgroundColor: active ? C10.cyan : C10.surfaceBg,
20434
- color: active ? C10.black : C10.textPrimary,
20435
- boxShadow: active ? `2px 2px 0 0 ${C10.border}` : "none",
21003
+ backgroundColor: active ? C13.cyan : C13.surfaceBg,
21004
+ color: active ? C13.black : C13.textPrimary,
21005
+ boxShadow: active ? `2px 2px 0 0 ${C13.border}` : "none",
20436
21006
  transition: "background-color 0.15s"
20437
21007
  },
20438
21008
  children: [