@consilioweb/payload-seo-analyzer 1.8.1 → 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
@@ -1058,6 +1058,8 @@ var fr = {
1058
1058
  },
1059
1059
  seoView: {
1060
1060
  loadingAudit: "Chargement de l'audit SEO...",
1061
+ buildingAudit: "G\xE9n\xE9ration de l'audit SEO en cours\u2026 (calcul\xE9 en arri\xE8re-plan pour ne pas surcharger le serveur, cela peut prendre un moment sur un gros site)",
1062
+ buildTimeout: "La g\xE9n\xE9ration de l'audit prend plus de temps que pr\xE9vu. R\xE9essayez dans quelques instants.",
1061
1063
  errorSaving: "Erreur lors de la sauvegarde",
1062
1064
  auditTitle: "Audit SEO",
1063
1065
  pagesAnalyzed: "pages analys\xE9es",
@@ -1500,7 +1502,19 @@ var fr = {
1500
1502
  generateMeta: "G\xE9n\xE9rer les meta",
1501
1503
  metaTitle: "Meta Title",
1502
1504
  metaDescription: "Meta Description",
1503
- emptyValue: "(vide)"
1505
+ emptyValue: "(vide)",
1506
+ optimizeWithAi: "Optimiser avec l'IA",
1507
+ optimizeIntro: "L'IA analyse la page et propose des meta optimis\xE9es (titre, description, mot-cl\xE9). V\xE9rifiez puis appliquez.",
1508
+ optimizeRunning: "Analyse en cours\u2026",
1509
+ applyAll: "Appliquer",
1510
+ applied: "Appliqu\xE9",
1511
+ whyChanges: "Pourquoi ces changements",
1512
+ labelCurrent: "Actuel",
1513
+ labelSuggested: "Sugg\xE9r\xE9",
1514
+ labelFocusKeyword: "Mot-cl\xE9 cible",
1515
+ heuristicNote: "Suggestions heuristiques (cl\xE9 API Claude non configur\xE9e).",
1516
+ applySaveHint: "Champs remplis \u2014 pensez \xE0 enregistrer le document.",
1517
+ noMetaChange: "Aucun changement propos\xE9."
1504
1518
  },
1505
1519
  scoreHistory: {
1506
1520
  loading: "Chargement de l'historique...",
@@ -1636,6 +1650,8 @@ var en = {
1636
1650
  },
1637
1651
  seoView: {
1638
1652
  loadingAudit: "Loading SEO audit...",
1653
+ buildingAudit: "Building the SEO audit\u2026 (computed in the background to avoid overloading the server \u2014 this can take a moment on a large site)",
1654
+ buildTimeout: "The audit is taking longer than expected. Please try again in a moment.",
1639
1655
  errorSaving: "Error during save",
1640
1656
  auditTitle: "SEO Audit",
1641
1657
  pagesAnalyzed: "pages analyzed",
@@ -2078,7 +2094,19 @@ var en = {
2078
2094
  generateMeta: "Generate meta",
2079
2095
  metaTitle: "Meta Title",
2080
2096
  metaDescription: "Meta Description",
2081
- emptyValue: "(empty)"
2097
+ emptyValue: "(empty)",
2098
+ optimizeWithAi: "Optimize with AI",
2099
+ optimizeIntro: "AI analyzes the page and proposes optimized meta tags (title, description, keyword). Review, then apply.",
2100
+ optimizeRunning: "Analyzing\u2026",
2101
+ applyAll: "Apply",
2102
+ applied: "Applied",
2103
+ whyChanges: "Why these changes",
2104
+ labelCurrent: "Current",
2105
+ labelSuggested: "Suggested",
2106
+ labelFocusKeyword: "Focus keyword",
2107
+ heuristicNote: "Heuristic suggestions (Claude API key not configured).",
2108
+ applySaveHint: "Fields filled \u2014 remember to save the document.",
2109
+ noMetaChange: "No changes proposed."
2082
2110
  },
2083
2111
  scoreHistory: {
2084
2112
  loading: "Loading history...",
@@ -6484,9 +6512,11 @@ var C2 = {
6484
6512
  white: "#fff",
6485
6513
  green: "#22c55e",
6486
6514
  red: "#ef4444",
6515
+ bg: "#fafafa",
6487
6516
  textPrimary: "var(--theme-text, #1a1a1a)",
6488
6517
  textSecondary: "var(--theme-elevation-600, #6b7280)",
6489
6518
  border: "var(--theme-border-color, #000)",
6519
+ inputBg: "var(--theme-input-bg, #fff)",
6490
6520
  surfaceBg: "var(--theme-elevation-0, #fff)",
6491
6521
  surface50: "var(--theme-elevation-50, #f9fafb)"
6492
6522
  };
@@ -6986,10 +7016,48 @@ function useInternalLinkSuggestions(documentId, collection, textContent) {
6986
7016
  }, [textContent, documentId, collection]);
6987
7017
  return { suggestions, loading };
6988
7018
  }
7019
+ function AiDiffRow({
7020
+ label,
7021
+ current,
7022
+ suggested,
7023
+ labelCurrent,
7024
+ labelSuggested,
7025
+ emptyValue,
7026
+ C: colors
7027
+ }) {
7028
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: 10 }, children: [
7029
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 10, fontWeight: 700, color: colors.textSecondary, textTransform: "uppercase", marginBottom: 4 }, children: label }),
7030
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 11, color: colors.textSecondary, marginBottom: 3 }, children: [
7031
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontWeight: 700 }, children: [
7032
+ labelCurrent,
7033
+ ": "
7034
+ ] }),
7035
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { textDecoration: current ? "line-through" : "none", opacity: 0.7 }, children: current || emptyValue })
7036
+ ] }),
7037
+ /* @__PURE__ */ jsxRuntime.jsxs(
7038
+ "div",
7039
+ {
7040
+ style: {
7041
+ padding: "6px 10px",
7042
+ borderRadius: 6,
7043
+ border: `1px solid var(--theme-elevation-200, #e5e7eb)`,
7044
+ backgroundColor: colors.surface50,
7045
+ fontSize: 12,
7046
+ color: colors.textPrimary,
7047
+ lineHeight: 1.5
7048
+ },
7049
+ children: [
7050
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 10, fontWeight: 700, color: colors.green, textTransform: "uppercase", marginRight: 6 }, children: labelSuggested }),
7051
+ suggested || emptyValue
7052
+ ]
7053
+ }
7054
+ )
7055
+ ] });
7056
+ }
6989
7057
  var SeoAnalyzer = () => {
6990
7058
  const locale = useSeoLocale();
6991
7059
  const t = getDashboardT(locale);
6992
- const [formFields] = ui.useAllFormFields();
7060
+ const [formFields, dispatchFields] = ui.useAllFormFields();
6993
7061
  const initialScoreRef = React4.useRef(null);
6994
7062
  const [suggestionsOpen, setSuggestionsOpen] = React4.useState(true);
6995
7063
  const [cannibalizationExpanded, setCannibalizationExpanded] = React4.useState(false);
@@ -6998,6 +7066,10 @@ var SeoAnalyzer = () => {
6998
7066
  const [aiGenerating, setAiGenerating] = React4.useState(false);
6999
7067
  const [aiResult, setAiResult] = React4.useState(null);
7000
7068
  const [aiCopied, setAiCopied] = React4.useState(null);
7069
+ const [aiOptimizing, setAiOptimizing] = React4.useState(false);
7070
+ const [aiOptimizeResult, setAiOptimizeResult] = React4.useState(null);
7071
+ const [aiOptimizeApplied, setAiOptimizeApplied] = React4.useState(false);
7072
+ const [aiOptimizeError, setAiOptimizeError] = React4.useState(false);
7001
7073
  const getFieldValue = React4.useCallback(
7002
7074
  (path) => {
7003
7075
  if (!formFields) return void 0;
@@ -7725,6 +7797,145 @@ var SeoAnalyzer = () => {
7725
7797
  }
7726
7798
  )
7727
7799
  ] }),
7800
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: 12 }, children: [
7801
+ /* @__PURE__ */ jsxRuntime.jsx(
7802
+ "button",
7803
+ {
7804
+ type: "button",
7805
+ disabled: aiOptimizing || !documentId,
7806
+ title: !documentId ? t.seoAnalyzer.applySaveHint : void 0,
7807
+ onClick: async () => {
7808
+ setAiOptimizing(true);
7809
+ setAiOptimizeResult(null);
7810
+ setAiOptimizeApplied(false);
7811
+ setAiOptimizeError(false);
7812
+ try {
7813
+ const res = await fetch("/api/seo-plugin/ai-optimize", {
7814
+ method: "POST",
7815
+ credentials: "include",
7816
+ headers: { "Content-Type": "application/json" },
7817
+ body: JSON.stringify({ collection: currentCollection, id: documentId })
7818
+ });
7819
+ if (res.ok) {
7820
+ setAiOptimizeResult(await res.json());
7821
+ } else {
7822
+ setAiOptimizeError(true);
7823
+ }
7824
+ } catch {
7825
+ setAiOptimizeError(true);
7826
+ }
7827
+ setAiOptimizing(false);
7828
+ },
7829
+ style: {
7830
+ display: "flex",
7831
+ alignItems: "center",
7832
+ gap: 6,
7833
+ width: "100%",
7834
+ padding: "10px 14px",
7835
+ borderRadius: 8,
7836
+ border: `2px solid ${C2.border}`,
7837
+ backgroundColor: "#7c3aed",
7838
+ color: "#fff",
7839
+ fontWeight: 800,
7840
+ fontSize: 12,
7841
+ cursor: aiOptimizing || !documentId ? "not-allowed" : "pointer",
7842
+ opacity: aiOptimizing || !documentId ? 0.6 : 1,
7843
+ textTransform: "uppercase",
7844
+ letterSpacing: "0.04em",
7845
+ justifyContent: "center",
7846
+ boxShadow: "2px 2px 0 0 var(--theme-border-color, rgba(0,0,0,1))"
7847
+ },
7848
+ children: aiOptimizing ? t.seoAnalyzer.optimizeRunning : `\u2728 ${t.seoAnalyzer.optimizeWithAi}`
7849
+ }
7850
+ ),
7851
+ aiOptimizeError && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 8, padding: "8px 12px", borderRadius: 6, fontSize: 11, color: C2.white, backgroundColor: C2.red }, children: t.common.loadingError }),
7852
+ aiOptimizeResult && /* @__PURE__ */ jsxRuntime.jsxs(
7853
+ "div",
7854
+ {
7855
+ style: {
7856
+ marginTop: 8,
7857
+ padding: "12px 14px",
7858
+ borderRadius: 8,
7859
+ border: `2px solid ${C2.border}`,
7860
+ backgroundColor: C2.surfaceBg
7861
+ },
7862
+ children: [
7863
+ aiOptimizeResult.method === "heuristic" && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 10, color: C2.textSecondary, marginBottom: 8, fontStyle: "italic" }, children: t.seoAnalyzer.heuristicNote }),
7864
+ /* @__PURE__ */ jsxRuntime.jsx(
7865
+ AiDiffRow,
7866
+ {
7867
+ label: t.seoAnalyzer.metaTitle,
7868
+ current: aiOptimizeResult.current.metaTitle,
7869
+ suggested: aiOptimizeResult.suggestions.metaTitle,
7870
+ labelCurrent: t.seoAnalyzer.labelCurrent,
7871
+ labelSuggested: t.seoAnalyzer.labelSuggested,
7872
+ emptyValue: t.seoAnalyzer.emptyValue,
7873
+ C: C2
7874
+ }
7875
+ ),
7876
+ /* @__PURE__ */ jsxRuntime.jsx(
7877
+ AiDiffRow,
7878
+ {
7879
+ label: t.seoAnalyzer.metaDescription,
7880
+ current: aiOptimizeResult.current.metaDescription,
7881
+ suggested: aiOptimizeResult.suggestions.metaDescription,
7882
+ labelCurrent: t.seoAnalyzer.labelCurrent,
7883
+ labelSuggested: t.seoAnalyzer.labelSuggested,
7884
+ emptyValue: t.seoAnalyzer.emptyValue,
7885
+ C: C2
7886
+ }
7887
+ ),
7888
+ aiOptimizeResult.suggestions.focusKeyword && aiOptimizeResult.suggestions.focusKeyword !== aiOptimizeResult.current.focusKeyword && /* @__PURE__ */ jsxRuntime.jsx(
7889
+ AiDiffRow,
7890
+ {
7891
+ label: t.seoAnalyzer.labelFocusKeyword,
7892
+ current: aiOptimizeResult.current.focusKeyword,
7893
+ suggested: aiOptimizeResult.suggestions.focusKeyword,
7894
+ labelCurrent: t.seoAnalyzer.labelCurrent,
7895
+ labelSuggested: t.seoAnalyzer.labelSuggested,
7896
+ emptyValue: t.seoAnalyzer.emptyValue,
7897
+ C: C2
7898
+ }
7899
+ ),
7900
+ aiOptimizeResult.suggestions.rationale.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 4, marginBottom: 10 }, children: [
7901
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 10, fontWeight: 700, color: C2.textSecondary, textTransform: "uppercase", marginBottom: 4 }, children: t.seoAnalyzer.whyChanges }),
7902
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { style: { margin: 0, paddingLeft: 16, fontSize: 11, color: C2.textPrimary, lineHeight: 1.5 }, children: aiOptimizeResult.suggestions.rationale.map((r, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: r }, i)) })
7903
+ ] }),
7904
+ /* @__PURE__ */ jsxRuntime.jsx(
7905
+ "button",
7906
+ {
7907
+ type: "button",
7908
+ disabled: aiOptimizeApplied,
7909
+ onClick: () => {
7910
+ const sug = aiOptimizeResult.suggestions;
7911
+ if (sug.metaTitle) dispatchFields({ type: "UPDATE", path: "meta.title", value: sug.metaTitle });
7912
+ if (sug.metaDescription) dispatchFields({ type: "UPDATE", path: "meta.description", value: sug.metaDescription });
7913
+ if (sug.focusKeyword && sug.focusKeyword !== aiOptimizeResult.current.focusKeyword) {
7914
+ dispatchFields({ type: "UPDATE", path: "focusKeyword", value: sug.focusKeyword });
7915
+ }
7916
+ setAiOptimizeApplied(true);
7917
+ },
7918
+ style: {
7919
+ width: "100%",
7920
+ padding: "9px 14px",
7921
+ borderRadius: 6,
7922
+ border: `2px solid ${C2.border}`,
7923
+ backgroundColor: aiOptimizeApplied ? C2.green : C2.cyan,
7924
+ color: aiOptimizeApplied ? C2.white : C2.black,
7925
+ fontWeight: 800,
7926
+ fontSize: 11,
7927
+ textTransform: "uppercase",
7928
+ letterSpacing: "0.04em",
7929
+ cursor: aiOptimizeApplied ? "default" : "pointer"
7930
+ },
7931
+ children: aiOptimizeApplied ? `\u2713 ${t.seoAnalyzer.applied}` : t.seoAnalyzer.applyAll
7932
+ }
7933
+ ),
7934
+ aiOptimizeApplied && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 6, fontSize: 10, color: C2.textSecondary, textAlign: "center" }, children: t.seoAnalyzer.applySaveHint })
7935
+ ]
7936
+ }
7937
+ )
7938
+ ] }),
7728
7939
  suggestions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
7729
7940
  "div",
7730
7941
  {
@@ -9064,6 +9275,7 @@ function SeoView() {
9064
9275
  const [items, setItems] = React4.useState([]);
9065
9276
  const [stats, setStats] = React4.useState(null);
9066
9277
  const [loading, setLoading] = React4.useState(true);
9278
+ const [building, setBuilding] = React4.useState(false);
9067
9279
  const [error, setError] = React4.useState(null);
9068
9280
  const [filter, setFilter] = React4.useState("all");
9069
9281
  const [scoreFilter, setScoreFilter] = React4.useState("all");
@@ -9080,9 +9292,22 @@ function SeoView() {
9080
9292
  const fetchAudit = React4.useCallback(async (forceRefresh = false) => {
9081
9293
  setLoading(true);
9082
9294
  setError(null);
9295
+ setBuilding(false);
9083
9296
  try {
9084
- const url = forceRefresh ? "/api/seo-plugin/audit?nocache=1" : "/api/seo-plugin/audit";
9085
- const res = await fetch(url, { credentials: "include", cache: "no-store" });
9297
+ const base = "/api/seo-plugin/audit";
9298
+ let res = await fetch(forceRefresh ? `${base}?nocache=1` : base, {
9299
+ credentials: "include",
9300
+ cache: "no-store"
9301
+ });
9302
+ let attempts = 0;
9303
+ const MAX_POLLS = 90;
9304
+ while (res.status === 202 && attempts < MAX_POLLS) {
9305
+ setBuilding(true);
9306
+ await new Promise((r) => setTimeout(r, 3e3));
9307
+ res = await fetch(base, { credentials: "include", cache: "no-store" });
9308
+ attempts++;
9309
+ }
9310
+ if (res.status === 202) throw new Error(t.seoView.buildTimeout);
9086
9311
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
9087
9312
  const data = await res.json();
9088
9313
  setItems(data.results || []);
@@ -9090,6 +9315,7 @@ function SeoView() {
9090
9315
  } catch (e) {
9091
9316
  setError(e instanceof Error ? e.message : t.common.loadingError);
9092
9317
  }
9318
+ setBuilding(false);
9093
9319
  setLoading(false);
9094
9320
  }, [t]);
9095
9321
  React4.useEffect(() => {
@@ -9531,7 +9757,7 @@ function SeoView() {
9531
9757
  fontSize: 14,
9532
9758
  fontFamily: "var(--font-body, system-ui)"
9533
9759
  },
9534
- children: t.seoView.loadingAudit
9760
+ children: building ? t.seoView.buildingAudit : t.seoView.loadingAudit
9535
9761
  }
9536
9762
  );
9537
9763
  }
@@ -15684,7 +15910,7 @@ function getSchemaTypes(t) {
15684
15910
  }
15685
15911
  };
15686
15912
  }
15687
- function buildJsonLd(type, values) {
15913
+ function buildJsonLd2(type, values) {
15688
15914
  switch (type) {
15689
15915
  case "LocalBusiness": {
15690
15916
  const result = {
@@ -15965,7 +16191,7 @@ function SchemaBuilderView() {
15965
16191
  [arrayName]: (prev[arrayName] || []).filter((_, i) => i !== index)
15966
16192
  }));
15967
16193
  }, []);
15968
- const jsonLd = React4.useMemo(() => buildJsonLd(selectedType, values), [selectedType, values]);
16194
+ const jsonLd = React4.useMemo(() => buildJsonLd2(selectedType, values), [selectedType, values]);
15969
16195
  const jsonString = React4.useMemo(() => JSON.stringify(jsonLd, null, 2), [jsonLd]);
15970
16196
  const scriptTag = React4.useMemo(
15971
16197
  () => `<script type="application/ld+json">
@@ -16742,6 +16968,573 @@ function GscPanel({ locale }) {
16742
16968
  ] })
16743
16969
  ] });
16744
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
+ }
16745
17538
  var V8 = {
16746
17539
  text: "var(--theme-text, #1a1a1a)",
16747
17540
  textSecondary: "var(--theme-elevation-600, #6b7280)",
@@ -17156,6 +17949,9 @@ function PerformanceView() {
17156
17949
  ),
17157
17950
  /* @__PURE__ */ jsxRuntime.jsx(CoreWebVitalsPanel, { locale }),
17158
17951
  /* @__PURE__ */ jsxRuntime.jsx(GscPanel, { locale }),
17952
+ /* @__PURE__ */ jsxRuntime.jsx(RankTrackingPanel, { locale }),
17953
+ /* @__PURE__ */ jsxRuntime.jsx(AlertsPanel, { locale }),
17954
+ /* @__PURE__ */ jsxRuntime.jsx(AltTextPanel, { locale }),
17159
17955
  showImport && /* @__PURE__ */ jsxRuntime.jsxs(
17160
17956
  "div",
17161
17957
  {
@@ -18815,7 +19611,7 @@ var controlBtnStyle = {
18815
19611
  cursor: "pointer",
18816
19612
  lineHeight: 1.4
18817
19613
  };
18818
- var C6 = {
19614
+ var C9 = {
18819
19615
  cyan: "#00E5FF",
18820
19616
  black: "#000",
18821
19617
  green: "#22c55e",
@@ -18830,10 +19626,10 @@ var C6 = {
18830
19626
  var TITLE_MIN = 30;
18831
19627
  var TITLE_MAX = 60;
18832
19628
  function getCharColor(len) {
18833
- if (len === 0) return C6.textSecondary;
18834
- if (len >= TITLE_MIN && len <= TITLE_MAX) return C6.green;
18835
- if (len > 0 && len < TITLE_MIN) return C6.orange;
18836
- 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;
18837
19633
  }
18838
19634
  function getProgressPercent(len) {
18839
19635
  if (len === 0) return 0;
@@ -18841,9 +19637,9 @@ function getProgressPercent(len) {
18841
19637
  }
18842
19638
  function getProgressColor(len) {
18843
19639
  if (len === 0) return "var(--theme-elevation-200, #e5e7eb)";
18844
- if (len >= TITLE_MIN && len <= TITLE_MAX) return C6.green;
18845
- if (len < TITLE_MIN) return C6.orange;
18846
- 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;
18847
19643
  }
18848
19644
  function MetaTitleField({
18849
19645
  path,
@@ -18914,7 +19710,7 @@ function MetaTitleField({
18914
19710
  style: {
18915
19711
  fontSize: 13,
18916
19712
  fontWeight: 700,
18917
- color: C6.textPrimary
19713
+ color: C9.textPrimary
18918
19714
  },
18919
19715
  children: t.metaTitle.label
18920
19716
  }
@@ -18954,9 +19750,9 @@ function MetaTitleField({
18954
19750
  fontSize: 14,
18955
19751
  fontFamily: "inherit",
18956
19752
  borderRadius: 8,
18957
- border: `2px solid ${C6.border}`,
18958
- backgroundColor: C6.surfaceBg,
18959
- color: C6.textPrimary,
19753
+ border: `2px solid ${C9.border}`,
19754
+ backgroundColor: C9.surfaceBg,
19755
+ color: C9.textPrimary,
18960
19756
  outline: "none",
18961
19757
  boxShadow: "2px 2px 0 0 var(--theme-border-color, rgba(0,0,0,1))"
18962
19758
  }
@@ -18974,9 +19770,9 @@ function MetaTitleField({
18974
19770
  gap: 5,
18975
19771
  padding: "8px 14px",
18976
19772
  borderRadius: 8,
18977
- border: `2px solid ${C6.border}`,
18978
- backgroundColor: loading ? C6.surface50 : C6.cyan,
18979
- 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,
18980
19776
  fontWeight: 800,
18981
19777
  fontSize: 11,
18982
19778
  textTransform: "uppercase",
@@ -19023,7 +19819,7 @@ function MetaTitleField({
19023
19819
  justifyContent: "space-between",
19024
19820
  marginTop: 4,
19025
19821
  fontSize: 10,
19026
- color: C6.textSecondary
19822
+ color: C9.textSecondary
19027
19823
  },
19028
19824
  children: [
19029
19825
  /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
@@ -19057,9 +19853,9 @@ function MetaTitleField({
19057
19853
  borderRadius: 6,
19058
19854
  fontSize: 11,
19059
19855
  fontWeight: 600,
19060
- color: C6.red,
19856
+ color: C9.red,
19061
19857
  backgroundColor: "rgba(239,68,68,0.08)",
19062
- border: `1px solid ${C6.red}`
19858
+ border: `1px solid ${C9.red}`
19063
19859
  },
19064
19860
  children: error
19065
19861
  }
@@ -19068,7 +19864,7 @@ function MetaTitleField({
19068
19864
  }
19069
19865
  );
19070
19866
  }
19071
- var C7 = {
19867
+ var C10 = {
19072
19868
  cyan: "#00E5FF",
19073
19869
  black: "#000",
19074
19870
  green: "#22c55e",
@@ -19083,10 +19879,10 @@ var C7 = {
19083
19879
  var DESC_MIN = 120;
19084
19880
  var DESC_MAX = 160;
19085
19881
  function getCharColor2(len) {
19086
- if (len === 0) return C7.textSecondary;
19087
- if (len >= DESC_MIN && len <= DESC_MAX) return C7.green;
19088
- if (len > 0 && len < DESC_MIN) return C7.orange;
19089
- 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;
19090
19886
  }
19091
19887
  function getProgressPercent2(len) {
19092
19888
  if (len === 0) return 0;
@@ -19094,9 +19890,9 @@ function getProgressPercent2(len) {
19094
19890
  }
19095
19891
  function getProgressColor2(len) {
19096
19892
  if (len === 0) return "var(--theme-elevation-200, #e5e7eb)";
19097
- if (len >= DESC_MIN && len <= DESC_MAX) return C7.green;
19098
- if (len < DESC_MIN) return C7.orange;
19099
- 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;
19100
19896
  }
19101
19897
  function MetaDescriptionField({
19102
19898
  path,
@@ -19167,7 +19963,7 @@ function MetaDescriptionField({
19167
19963
  style: {
19168
19964
  fontSize: 13,
19169
19965
  fontWeight: 700,
19170
- color: C7.textPrimary
19966
+ color: C10.textPrimary
19171
19967
  },
19172
19968
  children: t.metaDescription.label
19173
19969
  }
@@ -19207,9 +20003,9 @@ function MetaDescriptionField({
19207
20003
  fontSize: 14,
19208
20004
  fontFamily: "inherit",
19209
20005
  borderRadius: 8,
19210
- border: `2px solid ${C7.border}`,
19211
- backgroundColor: C7.surfaceBg,
19212
- color: C7.textPrimary,
20006
+ border: `2px solid ${C10.border}`,
20007
+ backgroundColor: C10.surfaceBg,
20008
+ color: C10.textPrimary,
19213
20009
  outline: "none",
19214
20010
  resize: "vertical",
19215
20011
  lineHeight: 1.5,
@@ -19229,9 +20025,9 @@ function MetaDescriptionField({
19229
20025
  gap: 5,
19230
20026
  padding: "8px 14px",
19231
20027
  borderRadius: 8,
19232
- border: `2px solid ${C7.border}`,
19233
- backgroundColor: loading ? C7.surface50 : C7.cyan,
19234
- 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,
19235
20031
  fontWeight: 800,
19236
20032
  fontSize: 11,
19237
20033
  textTransform: "uppercase",
@@ -19279,7 +20075,7 @@ function MetaDescriptionField({
19279
20075
  justifyContent: "space-between",
19280
20076
  marginTop: 4,
19281
20077
  fontSize: 10,
19282
- color: C7.textSecondary
20078
+ color: C10.textSecondary
19283
20079
  },
19284
20080
  children: [
19285
20081
  /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
@@ -19313,9 +20109,9 @@ function MetaDescriptionField({
19313
20109
  borderRadius: 6,
19314
20110
  fontSize: 11,
19315
20111
  fontWeight: 600,
19316
- color: C7.red,
20112
+ color: C10.red,
19317
20113
  backgroundColor: "rgba(239,68,68,0.08)",
19318
- border: `1px solid ${C7.red}`
20114
+ border: `1px solid ${C10.red}`
19319
20115
  },
19320
20116
  children: error
19321
20117
  }
@@ -19324,7 +20120,7 @@ function MetaDescriptionField({
19324
20120
  }
19325
20121
  );
19326
20122
  }
19327
- var C8 = {
20123
+ var C11 = {
19328
20124
  cyan: "#00E5FF",
19329
20125
  black: "#000",
19330
20126
  white: "#fff",
@@ -19401,8 +20197,8 @@ function MetaImageField({
19401
20197
  gap: 10,
19402
20198
  padding: "10px 14px",
19403
20199
  borderRadius: 8,
19404
- border: `2px solid ${C8.border}`,
19405
- backgroundColor: C8.surfaceBg,
20200
+ border: `2px solid ${C11.border}`,
20201
+ backgroundColor: C11.surfaceBg,
19406
20202
  boxShadow: "2px 2px 0 0 var(--theme-border-color, rgba(0,0,0,1))"
19407
20203
  },
19408
20204
  children: [
@@ -19421,7 +20217,7 @@ function MetaImageField({
19421
20217
  fontWeight: 900,
19422
20218
  backgroundColor: hasImage ? "rgba(34,197,94,0.15)" : "rgba(255,138,0,0.15)",
19423
20219
  color: hasImage ? "#16a34a" : "#d97706",
19424
- border: `1px solid ${hasImage ? C8.green : C8.orange}`
20220
+ border: `1px solid ${hasImage ? C11.green : C11.orange}`
19425
20221
  },
19426
20222
  children: hasImage ? "\u2713" : "!"
19427
20223
  }
@@ -19433,7 +20229,7 @@ function MetaImageField({
19433
20229
  style: {
19434
20230
  fontSize: 12,
19435
20231
  fontWeight: 700,
19436
- color: C8.textPrimary
20232
+ color: C11.textPrimary
19437
20233
  },
19438
20234
  children: t.metaImage.label
19439
20235
  }
@@ -19443,7 +20239,7 @@ function MetaImageField({
19443
20239
  {
19444
20240
  style: {
19445
20241
  fontSize: 10,
19446
- color: C8.textSecondary,
20242
+ color: C11.textSecondary,
19447
20243
  lineHeight: 1.4
19448
20244
  },
19449
20245
  children: hasImage ? t.metaImage.imageSet : t.metaImage.noImage
@@ -19463,9 +20259,9 @@ function MetaImageField({
19463
20259
  gap: 5,
19464
20260
  padding: "8px 14px",
19465
20261
  borderRadius: 8,
19466
- border: `2px solid ${C8.border}`,
19467
- backgroundColor: loading ? C8.surface50 : success ? C8.green : C8.cyan,
19468
- 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,
19469
20265
  fontWeight: 800,
19470
20266
  fontSize: 11,
19471
20267
  textTransform: "uppercase",
@@ -19492,9 +20288,9 @@ function MetaImageField({
19492
20288
  borderRadius: 6,
19493
20289
  fontSize: 11,
19494
20290
  fontWeight: 600,
19495
- color: C8.red,
20291
+ color: C11.red,
19496
20292
  backgroundColor: "rgba(239,68,68,0.08)",
19497
- border: `1px solid ${C8.red}`
20293
+ border: `1px solid ${C11.red}`
19498
20294
  },
19499
20295
  children: error
19500
20296
  }
@@ -19503,7 +20299,7 @@ function MetaImageField({
19503
20299
  }
19504
20300
  );
19505
20301
  }
19506
- var C9 = {
20302
+ var C12 = {
19507
20303
  black: "#000",
19508
20304
  white: "#fff",
19509
20305
  green: "#22c55e",
@@ -19517,15 +20313,15 @@ var C9 = {
19517
20313
  function getCompletenessColor(count) {
19518
20314
  switch (count) {
19519
20315
  case 0:
19520
- return C9.red;
20316
+ return C12.red;
19521
20317
  case 1:
19522
- return C9.orange;
20318
+ return C12.orange;
19523
20319
  case 2:
19524
- return C9.yellow;
20320
+ return C12.yellow;
19525
20321
  case 3:
19526
- return C9.green;
20322
+ return C12.green;
19527
20323
  default:
19528
- return C9.textSecondary;
20324
+ return C12.textSecondary;
19529
20325
  }
19530
20326
  }
19531
20327
  function getCompletenessLabel(count, ov) {
@@ -19583,8 +20379,8 @@ function OverviewField({
19583
20379
  fontFamily: "var(--font-body, Inter, system-ui, sans-serif)",
19584
20380
  padding: "12px 14px",
19585
20381
  borderRadius: 10,
19586
- border: `2px solid ${C9.border}`,
19587
- backgroundColor: C9.surfaceBg,
20382
+ border: `2px solid ${C12.border}`,
20383
+ backgroundColor: C12.surfaceBg,
19588
20384
  boxShadow: "3px 3px 0 0 var(--theme-border-color, rgba(0,0,0,1))",
19589
20385
  marginBottom: 12
19590
20386
  },
@@ -19607,7 +20403,7 @@ function OverviewField({
19607
20403
  fontWeight: 800,
19608
20404
  textTransform: "uppercase",
19609
20405
  letterSpacing: "0.04em",
19610
- color: C9.textPrimary
20406
+ color: C12.textPrimary
19611
20407
  },
19612
20408
  children: t.overview.metaCompleteness
19613
20409
  }
@@ -19622,8 +20418,8 @@ function OverviewField({
19622
20418
  fontSize: 11,
19623
20419
  fontWeight: 800,
19624
20420
  backgroundColor: completenessColor,
19625
- color: completenessColor === C9.yellow ? C9.black : C9.white,
19626
- border: `2px solid ${C9.border}`,
20421
+ color: completenessColor === C12.yellow ? C12.black : C12.white,
20422
+ border: `2px solid ${C12.border}`,
19627
20423
  textTransform: "uppercase",
19628
20424
  letterSpacing: "0.03em"
19629
20425
  },
@@ -19721,7 +20517,7 @@ function OverviewField({
19721
20517
  style: {
19722
20518
  fontSize: 12,
19723
20519
  fontWeight: 600,
19724
- color: item.filled ? C9.textPrimary : C9.textSecondary
20520
+ color: item.filled ? C12.textPrimary : C12.textSecondary
19725
20521
  },
19726
20522
  children: item.label
19727
20523
  }
@@ -19733,7 +20529,7 @@ function OverviewField({
19733
20529
  marginLeft: "auto",
19734
20530
  fontSize: 10,
19735
20531
  fontWeight: 700,
19736
- color: item.filled ? C9.green : C9.red,
20532
+ color: item.filled ? C12.green : C12.red,
19737
20533
  textTransform: "uppercase",
19738
20534
  letterSpacing: "0.03em"
19739
20535
  },
@@ -19750,7 +20546,7 @@ function OverviewField({
19750
20546
  }
19751
20547
  );
19752
20548
  }
19753
- var C10 = {
20549
+ var C13 = {
19754
20550
  cyan: "#00E5FF",
19755
20551
  black: "#000",
19756
20552
  white: "#fff",
@@ -19769,10 +20565,10 @@ var G = {
19769
20565
  descGrey: "#4d5156",
19770
20566
  faviconBg: "#e8eaed"};
19771
20567
  function charCountColor2(len, min, max) {
19772
- if (len >= min && len <= max) return C10.green;
19773
- if (len > 0 && len < min) return C10.orange;
19774
- if (len > max) return C10.red;
19775
- 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;
19776
20572
  }
19777
20573
  function truncateText(text, maxChars) {
19778
20574
  if (text.length <= maxChars) return text;
@@ -19827,8 +20623,8 @@ function SerpPreview({
19827
20623
  padding: "10px 12px",
19828
20624
  cursor: "pointer",
19829
20625
  borderRadius: 8,
19830
- border: `2px solid ${C10.border}`,
19831
- backgroundColor: C10.surface50,
20626
+ border: `2px solid ${C13.border}`,
20627
+ backgroundColor: C13.surface50,
19832
20628
  userSelect: "none"
19833
20629
  },
19834
20630
  children: [
@@ -19843,7 +20639,7 @@ function SerpPreview({
19843
20639
  fontWeight: 800,
19844
20640
  textTransform: "uppercase",
19845
20641
  letterSpacing: "0.04em",
19846
- color: C10.textPrimary
20642
+ color: C13.textPrimary
19847
20643
  },
19848
20644
  children: [
19849
20645
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -19875,7 +20671,7 @@ function SerpPreview({
19875
20671
  transition: "transform 0.2s",
19876
20672
  display: "inline-block",
19877
20673
  transform: open ? "rotate(90deg)" : "none",
19878
- color: C10.textSecondary
20674
+ color: C13.textSecondary
19879
20675
  },
19880
20676
  children: "\u25B6"
19881
20677
  }
@@ -19908,10 +20704,10 @@ function SerpPreview({
19908
20704
  "div",
19909
20705
  {
19910
20706
  style: {
19911
- backgroundColor: C10.white,
19912
- border: `2px solid ${C10.border}`,
20707
+ backgroundColor: C13.white,
20708
+ border: `2px solid ${C13.border}`,
19913
20709
  borderRadius: 12,
19914
- boxShadow: `3px 3px 0 0 ${C10.border}`,
20710
+ boxShadow: `3px 3px 0 0 ${C13.border}`,
19915
20711
  padding: isDesktop ? 20 : 14,
19916
20712
  maxWidth: isDesktop ? 650 : 380,
19917
20713
  overflow: "hidden"
@@ -19974,7 +20770,7 @@ function SerpPreview({
19974
20770
  style: {
19975
20771
  fontSize: 14,
19976
20772
  fontWeight: 400,
19977
- color: C10.black,
20773
+ color: C13.black,
19978
20774
  lineHeight: 1.3,
19979
20775
  whiteSpace: "nowrap",
19980
20776
  overflow: "hidden",
@@ -20038,7 +20834,7 @@ function SerpPreview({
20038
20834
  "span",
20039
20835
  {
20040
20836
  style: {
20041
- color: C10.textSecondary,
20837
+ color: C13.textSecondary,
20042
20838
  fontStyle: "italic",
20043
20839
  fontSize: titleFontSize - 2
20044
20840
  },
@@ -20067,7 +20863,7 @@ function SerpPreview({
20067
20863
  "span",
20068
20864
  {
20069
20865
  style: {
20070
- color: C10.textSecondary,
20866
+ color: C13.textSecondary,
20071
20867
  fontStyle: "italic",
20072
20868
  fontSize: descFontSize - 1
20073
20869
  },
@@ -20100,7 +20896,7 @@ function SerpPreview({
20100
20896
  fontSize: 11
20101
20897
  },
20102
20898
  children: [
20103
- /* @__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 }),
20104
20900
  /* @__PURE__ */ jsxRuntime.jsxs(
20105
20901
  "span",
20106
20902
  {
@@ -20129,7 +20925,7 @@ function SerpPreview({
20129
20925
  fontSize: 11
20130
20926
  },
20131
20927
  children: [
20132
- /* @__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 }),
20133
20929
  /* @__PURE__ */ jsxRuntime.jsxs(
20134
20930
  "span",
20135
20931
  {
@@ -20158,14 +20954,14 @@ function SerpPreview({
20158
20954
  fontSize: 11
20159
20955
  },
20160
20956
  children: [
20161
- /* @__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 }),
20162
20958
  /* @__PURE__ */ jsxRuntime.jsxs(
20163
20959
  "span",
20164
20960
  {
20165
20961
  style: {
20166
20962
  fontWeight: 700,
20167
20963
  fontVariantNumeric: "tabular-nums",
20168
- color: fullUrl.length <= 75 ? C10.green : C10.red
20964
+ color: fullUrl.length <= 75 ? C13.green : C13.red
20169
20965
  },
20170
20966
  children: [
20171
20967
  fullUrl.length,
@@ -20200,13 +20996,13 @@ function DeviceButton({
20200
20996
  gap: 5,
20201
20997
  padding: "4px 12px",
20202
20998
  borderRadius: 6,
20203
- border: `2px solid ${C10.border}`,
20999
+ border: `2px solid ${C13.border}`,
20204
21000
  fontSize: 11,
20205
21001
  fontWeight: 700,
20206
21002
  cursor: "pointer",
20207
- backgroundColor: active ? C10.cyan : C10.surfaceBg,
20208
- color: active ? C10.black : C10.textPrimary,
20209
- 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",
20210
21006
  transition: "background-color 0.15s"
20211
21007
  },
20212
21008
  children: [