paneltir 0.8.0 → 0.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/index.js CHANGED
@@ -1,11 +1,14 @@
1
1
  // src/version.ts
2
- var PANELTIR_VERSION = "0.8.0";
3
- var PANELTIR_FINGERPRINT = "sha256:a252ef2a015240e0e8463c0ebb0ef7a8af80ad7ade66f2c48e71657500d506d5";
4
- var PANELTIR_FILE_COUNT = 153;
2
+ var PANELTIR_VERSION = "0.10.0";
3
+ var PANELTIR_FINGERPRINT = "sha256:4de7ef7076563e4c3118ac16b645737a44c4c0675115d9a9d7bbff562d5ecb74";
4
+ var PANELTIR_FILE_COUNT = 163;
5
+ var PANELTIR_TEMPLATE_HASH = "sha256:7f9accd11920a0c189dd683bdb96635a606960afeca71e02c2a26a0257acefd8";
5
6
  var paneltirBuild = {
6
7
  version: PANELTIR_VERSION,
7
8
  fingerprint: PANELTIR_FINGERPRINT,
8
9
  fileCount: PANELTIR_FILE_COUNT,
10
+ /** What `init` stamps, and what a gate is compared against. */
11
+ templateHash: PANELTIR_TEMPLATE_HASH,
9
12
  /** The tag this build came from, ready to compare or to link. */
10
13
  tag: `v${PANELTIR_VERSION}`,
11
14
  /** Short form, for a footer that has one line to spare. */
@@ -667,9 +670,9 @@ function GuideTour({ notes, dismissed, onDismiss }) {
667
670
  useEffect4(() => {
668
671
  setReady(true);
669
672
  }, []);
670
- if (!ready && !controlled) return null;
673
+ if (!ready) return null;
671
674
  void version;
672
- const isDone = controlled ? (id) => dismissed.includes(id) : (id) => readDismissed(id);
675
+ const isDone = controlled ? (id) => dismissed.includes(id) || readDismissed(id) : (id) => readDismissed(id);
673
676
  const remaining = notes.filter((note) => !isDone(note.id));
674
677
  const current = remaining[0];
675
678
  if (!current) return null;
@@ -679,7 +682,7 @@ function GuideTour({ notes, dismissed, onDismiss }) {
679
682
  ...current,
680
683
  key: current.id,
681
684
  step: { index: notes.length - remaining.length + 1, total: notes.length },
682
- remember: !controlled,
685
+ remember: true,
683
686
  onDismissed: () => {
684
687
  onDismiss?.(current.id);
685
688
  setVersion((v) => v + 1);
@@ -720,9 +723,9 @@ function NotificationBell({ notifications, labels, seen: given, onSeen }) {
720
723
  const [open, setOpen] = useState3(false);
721
724
  const root = useRef4(null);
722
725
  useEffect5(() => {
723
- if (!controlled) setStored(readSeen());
724
- }, [controlled]);
725
- const seen = controlled ? new Set(given) : stored;
726
+ setStored(readSeen());
727
+ }, []);
728
+ const seen = stored === null ? controlled ? new Set(given) : null : controlled ? /* @__PURE__ */ new Set([...given, ...stored]) : stored;
726
729
  useEffect5(() => {
727
730
  if (!open) return;
728
731
  const onDown = (e) => {
@@ -740,10 +743,7 @@ function NotificationBell({ notifications, labels, seen: given, onSeen }) {
740
743
  }, [open]);
741
744
  const markSeen = useCallback3(
742
745
  (ids) => {
743
- if (controlled) {
744
- onSeen?.(ids);
745
- return;
746
- }
746
+ if (controlled) onSeen?.(ids);
747
747
  setStored((current) => {
748
748
  const next = new Set(current ?? []);
749
749
  for (const id of ids) next.add(id);
@@ -913,6 +913,89 @@ function SetupGuide({ requirements, readyMessage, labels }) {
913
913
  ] });
914
914
  }
915
915
 
916
+ // src/components/Setup/SetupWizard.tsx
917
+ import { useState as useState5 } from "react";
918
+
919
+ // src/components/Setup/wizard.ts
920
+ function wizardStep(requirements) {
921
+ const total = requirements.length;
922
+ const done = requirements.filter((requirement) => requirement.status === "ok");
923
+ const unknown = requirements.some((requirement) => requirement.status === "unknown");
924
+ const at = requirements.findIndex((requirement) => requirement.status !== "ok");
925
+ if (at === -1) {
926
+ return { current: null, index: 0, total, done, ready: total > 0, unknown: false };
927
+ }
928
+ return {
929
+ current: requirements[at],
930
+ index: at + 1,
931
+ total,
932
+ done,
933
+ ready: false,
934
+ unknown
935
+ };
936
+ }
937
+ function isFirstRun(board) {
938
+ return (board.cards?.length ?? 0) === 0 && (board.runs?.length ?? 0) === 0;
939
+ }
940
+
941
+ // src/components/Setup/SetupWizard.tsx
942
+ import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
943
+ function SetupWizard({ requirements, labels, onCheck, onClose }) {
944
+ const step = wizardStep(requirements);
945
+ const [checking, setChecking] = useState5(false);
946
+ const [checked, setChecked] = useState5(false);
947
+ const [copied, setCopied] = useState5(false);
948
+ async function check() {
949
+ setChecking(true);
950
+ try {
951
+ await onCheck();
952
+ setChecked(true);
953
+ } finally {
954
+ setChecking(false);
955
+ }
956
+ }
957
+ async function copyPrompt() {
958
+ try {
959
+ await navigator.clipboard.writeText(labels.stuckPrompt);
960
+ setCopied(true);
961
+ window.setTimeout(() => setCopied(false), 2e3);
962
+ } catch {
963
+ }
964
+ }
965
+ return /* @__PURE__ */ jsxs14("section", { className: "pt-wizard", "aria-labelledby": "pt-wizard-title", children: [
966
+ /* @__PURE__ */ jsxs14("header", { className: "pt-wizard__head", children: [
967
+ /* @__PURE__ */ jsx16("h2", { className: "pt-h2", id: "pt-wizard-title", children: labels.title }),
968
+ step.current && /* @__PURE__ */ jsx16("p", { className: "pt-wizard__progress", children: labels.progress(step.index, step.total) })
969
+ ] }),
970
+ step.current ? /* @__PURE__ */ jsxs14("div", { className: "pt-wizard__step", children: [
971
+ /* @__PURE__ */ jsx16("p", { className: "pt-wizard__now", children: labels.nowDo }),
972
+ /* @__PURE__ */ jsx16("h3", { className: "pt-wizard__label", children: step.current.label }),
973
+ step.current.variable && /* @__PURE__ */ jsx16("p", { className: "pt-wizard__var", children: step.current.variable }),
974
+ step.current.enables && /* @__PURE__ */ jsx16("p", { className: "pt-wizard__enables", children: step.current.enables }),
975
+ step.current.fix && /* @__PURE__ */ jsx16("div", { className: "pt-wizard__fix", children: step.current.fix }),
976
+ /* @__PURE__ */ jsxs14("div", { className: "pt-wizard__actions", children: [
977
+ /* @__PURE__ */ jsx16("button", { type: "button", className: "pt-btn pt-btn--primary", onClick: check, disabled: checking, children: checking ? labels.checking : labels.check }),
978
+ checked && !checking && /* @__PURE__ */ jsx16("p", { className: "pt-wizard__said", children: step.unknown ? labels.cannotTell : labels.stillMissing })
979
+ ] })
980
+ ] }) : /* @__PURE__ */ jsxs14("div", { className: "pt-wizard__step pt-wizard__step--done", children: [
981
+ /* @__PURE__ */ jsx16("h3", { className: "pt-wizard__label", children: labels.readyTitle }),
982
+ /* @__PURE__ */ jsx16("p", { className: "pt-wizard__enables", children: labels.readyBody }),
983
+ /* @__PURE__ */ jsx16("ol", { className: "pt-wizard__verify", children: labels.verify.map((line) => /* @__PURE__ */ jsx16("li", { children: line }, line)) })
984
+ ] }),
985
+ step.done.length > 0 && /* @__PURE__ */ jsxs14("div", { className: "pt-wizard__done", children: [
986
+ /* @__PURE__ */ jsx16("p", { className: "pt-wizard__done-title", children: labels.doneTitle }),
987
+ /* @__PURE__ */ jsx16("ul", { children: step.done.map((requirement) => /* @__PURE__ */ jsx16("li", { children: requirement.label }, requirement.id)) })
988
+ ] }),
989
+ /* @__PURE__ */ jsxs14("div", { className: "pt-wizard__stuck", children: [
990
+ /* @__PURE__ */ jsx16("p", { className: "pt-wizard__done-title", children: labels.stuckTitle }),
991
+ /* @__PURE__ */ jsx16("p", { className: "pt-wizard__enables", children: labels.stuckBody }),
992
+ /* @__PURE__ */ jsx16("pre", { className: "pt-wizard__prompt", children: labels.stuckPrompt }),
993
+ /* @__PURE__ */ jsx16("button", { type: "button", className: "pt-btn pt-btn--sm", onClick: copyPrompt, children: copied ? labels.copied : labels.copy })
994
+ ] }),
995
+ onClose && /* @__PURE__ */ jsx16("div", { className: "pt-wizard__actions", children: /* @__PURE__ */ jsx16("button", { type: "button", className: "pt-btn pt-btn--sm", onClick: onClose, children: labels.close }) })
996
+ ] });
997
+ }
998
+
916
999
  // src/hooks/useDelegatedClick.ts
917
1000
  import { useEffect as useEffect7 } from "react";
918
1001
  function useDelegatedClick(attribute, handler) {
@@ -932,9 +1015,9 @@ function useDelegatedClick(attribute, handler) {
932
1015
  }
933
1016
 
934
1017
  // src/hooks/useMediaQuery.ts
935
- import { useEffect as useEffect8, useState as useState5 } from "react";
1018
+ import { useEffect as useEffect8, useState as useState6 } from "react";
936
1019
  function useMediaQuery(query) {
937
- const [matches, setMatches] = useState5(() => typeof window !== "undefined" ? window.matchMedia(query).matches : false);
1020
+ const [matches, setMatches] = useState6(() => typeof window !== "undefined" ? window.matchMedia(query).matches : false);
938
1021
  useEffect8(() => {
939
1022
  const mql = window.matchMedia(query);
940
1023
  const handler = () => setMatches(mql.matches);
@@ -1300,10 +1383,34 @@ function isCard(value) {
1300
1383
  }
1301
1384
 
1302
1385
  // src/panel/PanelApp.tsx
1303
- import React12, { useCallback as useCallback5, useEffect as useEffect9, useMemo as useMemo5, useState as useState9 } from "react";
1386
+ import React13, { useCallback as useCallback5, useEffect as useEffect9, useMemo as useMemo5, useState as useState10 } from "react";
1304
1387
 
1305
1388
  // src/panel/updates.ts
1306
1389
  var REGISTRY_URL = "https://registry.npmjs.org/paneltir/latest";
1390
+ function readNotes(value) {
1391
+ if (typeof value !== "object" || value === null) return void 0;
1392
+ const candidate = value;
1393
+ if (typeof candidate.version !== "string" || typeof candidate.date !== "string") return void 0;
1394
+ if (!Array.isArray(candidate.entries) || candidate.entries.length === 0) return void 0;
1395
+ const kinds = /* @__PURE__ */ new Set(["breaking", "feature", "fix", "chore"]);
1396
+ const entries = [];
1397
+ for (const raw of candidate.entries) {
1398
+ if (typeof raw !== "object" || raw === null) return void 0;
1399
+ const item = raw;
1400
+ const text2 = item.text;
1401
+ if (typeof item.kind !== "string" || !kinds.has(item.kind)) return void 0;
1402
+ if (typeof text2?.en !== "string" || typeof text2?.es !== "string") return void 0;
1403
+ entries.push({ kind: item.kind, text: { en: text2.en, es: text2.es } });
1404
+ }
1405
+ return { version: candidate.version, date: candidate.date, entries };
1406
+ }
1407
+ function releaseShape(notes) {
1408
+ if (!notes?.entries.length) return null;
1409
+ for (const kind of ["breaking", "feature", "fix", "chore"]) {
1410
+ if (notes.entries.some((entry) => entry.kind === kind)) return kind;
1411
+ }
1412
+ return null;
1413
+ }
1307
1414
  function isNewer(candidate, current) {
1308
1415
  const parts = (value) => value.trim().replace(/^v/, "").split(/[-+]/)[0].split(".").map((piece) => Number.parseInt(piece, 10));
1309
1416
  const left = parts(candidate);
@@ -1323,7 +1430,7 @@ async function checkForUpdate(current, fetchImpl = fetch) {
1323
1430
  const body = await response.json();
1324
1431
  const latest = typeof body.version === "string" ? body.version : null;
1325
1432
  if (!latest) return null;
1326
- return { current, latest, behind: isNewer(latest, current) };
1433
+ return { current, latest, behind: isNewer(latest, current), notes: readNotes(body.paneltirRelease) };
1327
1434
  } catch {
1328
1435
  return null;
1329
1436
  }
@@ -1358,9 +1465,30 @@ var PRESET_PANEL_THEMES = Object.fromEntries(
1358
1465
  { label: PRESET_LABEL[name], tokens: THEME_PRESETS[name], form: PRESET_FORM[name], note: PRESET_NOTE[name] }
1359
1466
  ])
1360
1467
  );
1468
+ function offeredThemes(themes, extraThemes) {
1469
+ if (themes) return themes;
1470
+ if (!extraThemes) return PRESET_PANEL_THEMES;
1471
+ const offered = { ...extraThemes };
1472
+ for (const [name, preset] of Object.entries(PRESET_PANEL_THEMES)) {
1473
+ if (!(name in offered)) offered[name] = preset;
1474
+ }
1475
+ return offered;
1476
+ }
1477
+
1478
+ // src/gate/stamp.ts
1479
+ function gateStatus(stamp, installed) {
1480
+ const reading = { verdict: "unstamped", installed: installed.version };
1481
+ if (typeof stamp !== "object" || stamp === null) return reading;
1482
+ const candidate = stamp;
1483
+ if (typeof candidate.templateHash !== "string" || candidate.templateHash === "") return reading;
1484
+ if (typeof candidate.version === "string" && candidate.version) reading.copiedFrom = candidate.version;
1485
+ if (typeof installed.templateHash !== "string" || installed.templateHash === "") return reading;
1486
+ reading.verdict = candidate.templateHash === installed.templateHash ? "current" : "behind";
1487
+ return reading;
1488
+ }
1361
1489
 
1362
1490
  // src/panel/AnalysisView.tsx
1363
- import { useMemo as useMemo3, useState as useState6 } from "react";
1491
+ import { useMemo as useMemo3, useState as useState7 } from "react";
1364
1492
 
1365
1493
  // src/panel/i18n.ts
1366
1494
  var STORAGE_KEY = "paneltir:lang";
@@ -1398,6 +1526,17 @@ var UI = {
1398
1526
  updateAsOrder: "Write it as an order, not a suggestion",
1399
1527
  updateAsOrderHow: "This does not update anything on its own \u2014 the panel cannot run npm. It decides whether the card it writes asks for the update or instructs it.",
1400
1528
  notifUpdate: "A newer Paneltir has been published",
1529
+ releaseTitle: (version) => `What v${version} changes`,
1530
+ releaseDate: (date) => `Published ${date}`,
1531
+ releaseShape: {
1532
+ breaking: "Contains a change that can break things",
1533
+ feature: "New things, and fixes",
1534
+ fix: "Small fixes",
1535
+ chore: "Housekeeping"
1536
+ },
1537
+ releaseKind: { breaking: "Breaking", feature: "New", fix: "Fix", chore: "Chore" },
1538
+ releaseClose: "Close",
1539
+ releaseNone: "This version was published without notes.",
1401
1540
  updateCardTitle: (version) => `Update Paneltir to v${version}`,
1402
1541
  updateCardBody: (version) => `Run \`npm install paneltir@${version}\` in this project, then check the panel still builds and renders. The version in use is reported by \`paneltirBuild\`, so it can be confirmed rather than assumed.`,
1403
1542
  cardDetail: "Card",
@@ -1475,11 +1614,36 @@ var UI = {
1475
1614
  needTokenEnables: "Lets Save commit the board back to the repository. Without it everything else works and Save fails.",
1476
1615
  needRepo: "The repository to write to",
1477
1616
  needRepoEnables: "Which repository the board is committed to. There is no default on purpose: writing to the wrong one is worse than not writing.",
1617
+ needGate: "The gate this project copied",
1618
+ needGateEnables: "The sign-in, the session and the write-back are files this project owns, copied once and never updated with the library. When one of them is older than the package, the panel does not look misconfigured \u2014 it looks broken.",
1619
+ fixGate: "The gate is older than the installed kit. See what changed before replacing anything:",
1478
1620
  fixTokenCreate: "On GitHub, make a fine-grained personal access token.",
1479
1621
  fixTokenScope: "Give it Contents: read and write, on this repository only \u2014 nothing else, and no other repository.",
1480
1622
  fixTokenPaste: "Paste it into the hosting project as GH_TOKEN. Never into the repository: a token in a commit is a token to revoke.",
1481
1623
  fixTokenRedeploy: "Redeploy. Environment variables are read at deploy time, so a running deployment will not see a new one.",
1482
1624
  fixRepo: "Set PANEL_REPO in the hosting project to this project\u2019s owner/repo, then redeploy.",
1625
+ wizardTitle: "Setting this panel up",
1626
+ wizardProgress: (index, total) => `Step ${index} of ${total}`,
1627
+ wizardNowDo: "Do this next",
1628
+ wizardCheck: "Check it now",
1629
+ wizardChecking: "Asking the server\u2026",
1630
+ wizardStillMissing: "Still not there. If you have just added it, redeploy \u2014 a running deployment does not see a new variable.",
1631
+ wizardCannotTell: "The panel could not ask its own server, so it cannot say either way. That is a different problem from a missing variable, and worth fixing first.",
1632
+ wizardDoneTitle: "Already in place",
1633
+ wizardReadyTitle: "That is everything.",
1634
+ wizardReadyBody: "Saves will commit to the repository from now on. Two things are worth trying before you trust the door:",
1635
+ wizardVerify: [
1636
+ "Open /admin signed out. It should land on the sign-in screen, not on the panel.",
1637
+ "Signed out, ask for the panel\u2019s own JavaScript bundle. It should answer 401. A page that is protected while its bundle is not leaves the board readable by anyone who opens the HTML."
1638
+ ],
1639
+ wizardClose: "Close",
1640
+ wizardStuckTitle: "If any of this is unclear",
1641
+ wizardStuckBody: "This project has a Claude of its own, and `paneltir init` wrote it a guide covering exactly this. Paste the line below into a session in this repository and it will walk you through it, in whatever detail you need.",
1642
+ wizardStuckPrompt: "Read .claude/skills/panel/SKILL.md and set up the Paneltir panel with me: tell me each environment variable it needs, what it is for, where in this project to put it, and check the ones already set.",
1643
+ wizardCopy: "Copy the prompt",
1644
+ wizardCopied: "Copied",
1645
+ wizardOpen: "Walk me through it",
1646
+ wizardBanner: "This panel is not finished being set up: saving will fail until it is.",
1483
1647
  demoTourWelcomeTitle: "A real panel, and nothing is saved yet",
1484
1648
  demoTourWelcomeBody: "Everything here works. Move things, open things, break things \u2014 nothing is written anywhere yet, so nothing you do can damage anything.",
1485
1649
  demoTourBoardTitle: "Drag a card, then open one",
@@ -1554,6 +1718,20 @@ var UI = {
1554
1718
  strategy: "The paths open to it, the one chosen, and what is worth doing next.",
1555
1719
  market: "Who this is for, and who else is already there."
1556
1720
  },
1721
+ analysisRedo: "Ask for this again",
1722
+ analysisRedoAsked: "Asked for. It lands as a card, and the next session does the work.",
1723
+ analysisRedoTitle: {
1724
+ board: "Read the board again and say what it adds up to",
1725
+ project: "Revisit what this is for and how it is measured",
1726
+ strategy: "Work the strategy again and propose what is next",
1727
+ market: "A fresh market report"
1728
+ },
1729
+ analysisRedoBody: {
1730
+ board: "The board has moved since this was last read. Go through the cards, say what they now add up to, and write the questions worth asking that nobody has asked yet.",
1731
+ project: "Look again at the goals, the constraints and the metrics. Say which no longer match what the project has become, and propose the change rather than making it.",
1732
+ strategy: "Look at the strategies on record, whether the chosen one is still the right one, and what is worth doing next. Propose; the choice stays the owner\u2019s.",
1733
+ market: "Research the market again: who this is for, who else is there now, and what has changed since the last report. Write it into the Market screen."
1734
+ },
1557
1735
  analysisAnswered: (answered, total) => `${answered} of ${total} answered`,
1558
1736
  analysisAllDecided: "Every question on this screen has an answer.",
1559
1737
  choicesTitle: "Standing answers",
@@ -1672,6 +1850,17 @@ var UI = {
1672
1850
  updateAsOrder: "Escribirla como orden, no como sugerencia",
1673
1851
  updateAsOrderHow: "Esto no actualiza nada por su cuenta \u2014 el panel no puede ejecutar npm. Decide si la tarjeta que escribe pide la actualizaci\xF3n o la manda.",
1674
1852
  notifUpdate: "Se ha publicado un Paneltir m\xE1s nuevo",
1853
+ releaseTitle: (version) => `Qu\xE9 cambia la v${version}`,
1854
+ releaseDate: (date) => `Publicada el ${date}`,
1855
+ releaseShape: {
1856
+ breaking: "Trae un cambio que puede romper cosas",
1857
+ feature: "Novedades, y correcciones",
1858
+ fix: "Correcciones menores",
1859
+ chore: "Mantenimiento"
1860
+ },
1861
+ releaseKind: { breaking: "Rompe", feature: "Nuevo", fix: "Arreglo", chore: "Interno" },
1862
+ releaseClose: "Cerrar",
1863
+ releaseNone: "Esta versi\xF3n se public\xF3 sin notas.",
1675
1864
  updateCardTitle: (version) => `Actualizar Paneltir a la v${version}`,
1676
1865
  updateCardBody: (version) => `Ejecuta \`npm install paneltir@${version}\` en este proyecto y comprueba que el panel sigue construy\xE9ndose y dibuj\xE1ndose. La versi\xF3n en uso la reporta \`paneltirBuild\`, as\xED que se puede confirmar en vez de darla por hecha.`,
1677
1866
  cardDetail: "Tarjeta",
@@ -1749,11 +1938,36 @@ var UI = {
1749
1938
  needTokenEnables: "Permite que Guardar confirme el tablero en el repositorio. Sin \xE9l todo lo dem\xE1s funciona y Guardar falla.",
1750
1939
  needRepo: "El repositorio donde escribir",
1751
1940
  needRepoEnables: "En qu\xE9 repositorio se confirma el tablero. No hay valor por defecto a prop\xF3sito: escribir en el equivocado es peor que no escribir.",
1941
+ needGate: "La puerta que copi\xF3 este proyecto",
1942
+ needGateEnables: "El acceso, la sesi\xF3n y la escritura de vuelta son archivos de este proyecto, copiados una vez y que no se actualizan con la librer\xEDa. Cuando uno se queda m\xE1s viejo que el paquete, el panel no parece mal configurado: parece roto.",
1943
+ fixGate: "La puerta es m\xE1s vieja que el kit instalado. Mira qu\xE9 cambi\xF3 antes de reemplazar nada:",
1752
1944
  fixTokenCreate: "En GitHub, crea un token de acceso personal de tipo fine-grained.",
1753
1945
  fixTokenScope: "Dale Contents: read and write, solo sobre este repositorio \u2014 nada m\xE1s, y ning\xFAn otro repositorio.",
1754
1946
  fixTokenPaste: "P\xE9galo en el proyecto de hosting como GH_TOKEN. Nunca en el repositorio: un token en un commit es un token que hay que revocar.",
1755
1947
  fixTokenRedeploy: "Vuelve a desplegar. Las variables de entorno se leen al desplegar, as\xED que un despliegue en marcha no ver\xE1 una nueva.",
1756
1948
  fixRepo: "Pon PANEL_REPO en el proyecto de hosting con el owner/repo de este proyecto, y vuelve a desplegar.",
1949
+ wizardTitle: "Poniendo en marcha este panel",
1950
+ wizardProgress: (index, total) => `Paso ${index} de ${total}`,
1951
+ wizardNowDo: "Haz esto ahora",
1952
+ wizardCheck: "Compru\xE9balo ya",
1953
+ wizardChecking: "Preguntando al servidor\u2026",
1954
+ wizardStillMissing: "Sigue sin estar. Si acabas de ponerlo, vuelve a desplegar \u2014 un despliegue en marcha no ve una variable nueva.",
1955
+ wizardCannotTell: "El panel no pudo preguntarle a su propio servidor, as\xED que no puede decir ni que s\xED ni que no. \xC9se es otro problema distinto a que falte una variable, y merece arreglarse antes.",
1956
+ wizardDoneTitle: "Ya est\xE1 puesto",
1957
+ wizardReadyTitle: "Eso es todo.",
1958
+ wizardReadyBody: "A partir de ahora los guardados se confirman en el repositorio. Dos cosas merecen probarse antes de fiarte de la puerta:",
1959
+ wizardVerify: [
1960
+ "Abre /admin sin sesi\xF3n. Debe llevarte a la pantalla de entrada, no al panel.",
1961
+ "Sin sesi\xF3n, pide el bundle de JavaScript del propio panel. Debe responder 401. Una p\xE1gina protegida cuyo bundle no lo est\xE1 deja el tablero legible para cualquiera que abra el HTML."
1962
+ ],
1963
+ wizardClose: "Cerrar",
1964
+ wizardStuckTitle: "Si algo de esto no queda claro",
1965
+ wizardStuckBody: "Este proyecto tiene su propio Claude, y `paneltir init` le dej\xF3 escrita una gu\xEDa que cubre justo esto. Pega la l\xEDnea de abajo en una sesi\xF3n dentro de este repositorio y te lo ir\xE1 explicando con el detalle que necesites.",
1966
+ wizardStuckPrompt: "Lee .claude/skills/panel/SKILL.md y pon en marcha conmigo el panel de Paneltir: dime cada variable de entorno que necesita, para qu\xE9 sirve, d\xF3nde ponerla en este proyecto, y comprueba las que ya est\xE1n.",
1967
+ wizardCopy: "Copiar el texto",
1968
+ wizardCopied: "Copiado",
1969
+ wizardOpen: "Gu\xEDame paso a paso",
1970
+ wizardBanner: "A este panel le falta terminar de configurarse: guardar fallar\xE1 hasta que lo est\xE9.",
1757
1971
  demoTourWelcomeTitle: "Un panel de verdad, y a\xFAn no se guarda nada",
1758
1972
  demoTourWelcomeBody: "Aqu\xED funciona todo: la empresa de transporte es inventada, el panel no. Mueve cosas, abre cosas, r\xF3mpelas \u2014 no puedes estropear nada.",
1759
1973
  demoTourBoardTitle: "Arrastra una tarjeta, y luego abre una",
@@ -1828,6 +2042,20 @@ var UI = {
1828
2042
  strategy: "Los caminos abiertos, el elegido, y lo que merece la pena hacer ahora.",
1829
2043
  market: "Para qui\xE9n es esto, y qui\xE9n m\xE1s est\xE1 ya ah\xED."
1830
2044
  },
2045
+ analysisRedo: "Pedirlo otra vez",
2046
+ analysisRedoAsked: "Pedido. Cae como tarjeta, y la siguiente sesi\xF3n hace el trabajo.",
2047
+ analysisRedoTitle: {
2048
+ board: "Leer el tablero otra vez y decir qu\xE9 suma",
2049
+ project: "Revisar para qu\xE9 es esto y c\xF3mo se mide",
2050
+ strategy: "Trabajar la estrategia otra vez y proponer qu\xE9 sigue",
2051
+ market: "Un informe de mercado nuevo"
2052
+ },
2053
+ analysisRedoBody: {
2054
+ board: "El tablero se ha movido desde la \xFAltima lectura. Repasa las tarjetas, di qu\xE9 suman ahora, y escribe las preguntas que merecen respuesta y nadie ha hecho.",
2055
+ project: "Mira otra vez los objetivos, las restricciones y las m\xE9tricas. Di cu\xE1les ya no encajan con lo que el proyecto ha llegado a ser, y prop\xF3n el cambio en vez de hacerlo.",
2056
+ strategy: "Mira las estrategias registradas, si la elegida sigue siendo la buena, y qu\xE9 merece la pena hacer ahora. Prop\xF3n; la elecci\xF3n sigue siendo del due\xF1o.",
2057
+ market: "Investiga el mercado otra vez: para qui\xE9n es esto, qui\xE9n m\xE1s est\xE1 ahora, y qu\xE9 ha cambiado desde el \xFAltimo informe. Escr\xEDbelo en la pantalla de Mercado."
2058
+ },
1831
2059
  analysisAnswered: (answered, total) => `${answered} de ${total} contestadas`,
1832
2060
  analysisAllDecided: "Todas las preguntas de esta pantalla tienen respuesta.",
1833
2061
  choicesTitle: "Respuestas fijas",
@@ -1930,7 +2158,7 @@ var UI = {
1930
2158
  };
1931
2159
 
1932
2160
  // src/panel/AnalysisView.tsx
1933
- import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
2161
+ import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
1934
2162
  var SUGGESTION_STATUSES = ["new", "doing", "done", "dismissed"];
1935
2163
  function MetricTile({ metric, lang, ui }) {
1936
2164
  const { latest, delta, against } = trendOf(metric);
@@ -1939,23 +2167,23 @@ function MetricTile({ metric, lang, ui }) {
1939
2167
  const height = 34;
1940
2168
  const path = points.map((point) => `${(point.x * width).toFixed(1)},${(point.y * (height - 6) + 3).toFixed(1)}`);
1941
2169
  const last = points[points.length - 1];
1942
- return /* @__PURE__ */ jsxs14("article", { className: "pt-metric", children: [
1943
- /* @__PURE__ */ jsx16("p", { className: "pt-metric__label", children: text(metric.label, lang) }),
1944
- /* @__PURE__ */ jsxs14("p", { className: "pt-metric__value", children: [
2170
+ return /* @__PURE__ */ jsxs15("article", { className: "pt-metric", children: [
2171
+ /* @__PURE__ */ jsx17("p", { className: "pt-metric__label", children: text(metric.label, lang) }),
2172
+ /* @__PURE__ */ jsxs15("p", { className: "pt-metric__value", children: [
1945
2173
  latest ? latest.value : "\u2014",
1946
- /* @__PURE__ */ jsx16("span", { className: "pt-metric__unit", children: metric.unit })
2174
+ /* @__PURE__ */ jsx17("span", { className: "pt-metric__unit", children: metric.unit })
1947
2175
  ] }),
1948
- delta !== null && /* @__PURE__ */ jsxs14("p", { className: `pt-metric__delta${against ? " is-against" : " is-with"}`, children: [
2176
+ delta !== null && /* @__PURE__ */ jsxs15("p", { className: `pt-metric__delta${against ? " is-against" : " is-with"}`, children: [
1949
2177
  delta > 0 ? "\u25B2" : delta < 0 ? "\u25BC" : "\u25A0",
1950
2178
  " ",
1951
2179
  delta > 0 ? "+" : "",
1952
2180
  delta,
1953
- /* @__PURE__ */ jsxs14("span", { className: "pt-metric__since", children: [
2181
+ /* @__PURE__ */ jsxs15("span", { className: "pt-metric__since", children: [
1954
2182
  " \xB7 ",
1955
2183
  against ? ui.metricAgainst : ui.metricWith
1956
2184
  ] })
1957
2185
  ] }),
1958
- points.length > 1 && /* @__PURE__ */ jsxs14(
2186
+ points.length > 1 && /* @__PURE__ */ jsxs15(
1959
2187
  "svg",
1960
2188
  {
1961
2189
  className: "pt-metric__spark",
@@ -1965,12 +2193,12 @@ function MetricTile({ metric, lang, ui }) {
1965
2193
  role: "img",
1966
2194
  "aria-label": `${text(metric.label, lang)}: ${metric.readings.map((r) => `${r.date} ${r.value}`).join(", ")}`,
1967
2195
  children: [
1968
- /* @__PURE__ */ jsx16("polyline", { points: path.join(" "), fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" }),
1969
- last && /* @__PURE__ */ jsx16("circle", { cx: last.x * width, cy: last.y * (height - 6) + 3, r: "3.5", className: "pt-metric__point" })
2196
+ /* @__PURE__ */ jsx17("polyline", { points: path.join(" "), fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" }),
2197
+ last && /* @__PURE__ */ jsx17("circle", { cx: last.x * width, cy: last.y * (height - 6) + 3, r: "3.5", className: "pt-metric__point" })
1970
2198
  ]
1971
2199
  }
1972
2200
  ),
1973
- latest?.note && /* @__PURE__ */ jsx16("p", { className: "pt-metric__note", children: text(latest.note, lang) })
2201
+ latest?.note && /* @__PURE__ */ jsx17("p", { className: "pt-metric__note", children: text(latest.note, lang) })
1974
2202
  ] });
1975
2203
  }
1976
2204
  function ChoiceCard({
@@ -1981,11 +2209,11 @@ function ChoiceCard({
1981
2209
  onDecide
1982
2210
  }) {
1983
2211
  const answered = choice.options.find((option) => option.id === choice.value);
1984
- return /* @__PURE__ */ jsxs14("article", { className: `pt-choice${answered ? " is-decided" : ""}`, children: [
1985
- /* @__PURE__ */ jsx16("p", { className: "pt-choice__state", children: answered ? ui.choiceDecidedAt(choice.decidedAt ?? "") : ui.choiceOpen }),
1986
- /* @__PURE__ */ jsx16("p", { className: "pt-choice__question", children: text(choice.question, lang) }),
1987
- choice.why && /* @__PURE__ */ jsx16("p", { className: "pt-choice__why", children: text(choice.why, lang) }),
1988
- /* @__PURE__ */ jsx16("div", { className: "pt-panel-row pt-choice__options", children: choice.options.map((option) => /* @__PURE__ */ jsx16(
2212
+ return /* @__PURE__ */ jsxs15("article", { className: `pt-choice${answered ? " is-decided" : ""}`, children: [
2213
+ /* @__PURE__ */ jsx17("p", { className: "pt-choice__state", children: answered ? ui.choiceDecidedAt(choice.decidedAt ?? "") : ui.choiceOpen }),
2214
+ /* @__PURE__ */ jsx17("p", { className: "pt-choice__question", children: text(choice.question, lang) }),
2215
+ choice.why && /* @__PURE__ */ jsx17("p", { className: "pt-choice__why", children: text(choice.why, lang) }),
2216
+ /* @__PURE__ */ jsx17("div", { className: "pt-panel-row pt-choice__options", children: choice.options.map((option) => /* @__PURE__ */ jsx17(
1989
2217
  FilterChip,
1990
2218
  {
1991
2219
  label: text(option.label, lang),
@@ -1994,8 +2222,8 @@ function ChoiceCard({
1994
2222
  },
1995
2223
  option.id
1996
2224
  )) }),
1997
- answered?.detail && /* @__PURE__ */ jsx16("p", { className: "pt-choice__detail", children: text(answered.detail, lang) }),
1998
- answered && /* @__PURE__ */ jsx16(
2225
+ answered?.detail && /* @__PURE__ */ jsx17("p", { className: "pt-choice__detail", children: text(answered.detail, lang) }),
2226
+ answered && /* @__PURE__ */ jsx17(
1999
2227
  "button",
2000
2228
  {
2001
2229
  type: "button",
@@ -2014,10 +2242,10 @@ function Choices({
2014
2242
  onDecide
2015
2243
  }) {
2016
2244
  const choices = analysis.choices?.[section] ?? [];
2017
- return /* @__PURE__ */ jsxs14("section", { children: [
2018
- /* @__PURE__ */ jsx16("h3", { className: "pt-cap__title", children: ui.choicesTitle }),
2019
- /* @__PURE__ */ jsx16("p", { className: "pt-sub", children: ui.choicesIntro }),
2020
- choices.length === 0 ? /* @__PURE__ */ jsx16("p", { className: "pt-analysis__empty", children: ui.choicesNone }) : /* @__PURE__ */ jsx16("div", { className: "pt-choice-grid", children: choices.map((choice) => /* @__PURE__ */ jsx16(
2245
+ return /* @__PURE__ */ jsxs15("section", { children: [
2246
+ /* @__PURE__ */ jsx17("h3", { className: "pt-cap__title", children: ui.choicesTitle }),
2247
+ /* @__PURE__ */ jsx17("p", { className: "pt-sub", children: ui.choicesIntro }),
2248
+ choices.length === 0 ? /* @__PURE__ */ jsx17("p", { className: "pt-analysis__empty", children: ui.choicesNone }) : /* @__PURE__ */ jsx17("div", { className: "pt-choice-grid", children: choices.map((choice) => /* @__PURE__ */ jsx17(
2021
2249
  ChoiceCard,
2022
2250
  {
2023
2251
  section,
@@ -2040,26 +2268,28 @@ function AnalysisView({
2040
2268
  onChooseStrategy,
2041
2269
  onSuggestionStatus,
2042
2270
  onDecide,
2043
- onOpenCard
2271
+ onOpenCard,
2272
+ onRequestReport
2044
2273
  }) {
2045
2274
  const t = (value) => text(value, lang);
2046
- const [section, setSection] = useState6("board");
2275
+ const [section, setSection] = useState7("board");
2047
2276
  const facts = useMemo3(() => boardFacts(cards, columns, today2), [cards, columns, today2]);
2048
2277
  const answers = useMemo3(() => decided(analysis), [analysis]);
2049
2278
  const open = useMemo3(() => undecided(analysis), [analysis]);
2050
2279
  const total = answers.length + open.length;
2051
2280
  const here = analysis.choices?.[section] ?? [];
2052
2281
  const answeredHere = here.filter((choice) => choice.options.some((option) => option.id === choice.value)).length;
2053
- return /* @__PURE__ */ jsxs14("div", { className: "pt-panel-page pt-panel-section pt-analysis", children: [
2054
- /* @__PURE__ */ jsxs14("section", { children: [
2055
- /* @__PURE__ */ jsx16("p", { className: "pt-eyebrow", children: ui.analysisEyebrow }),
2056
- /* @__PURE__ */ jsx16("h2", { className: "pt-h2", children: ui.analysisSections[section] }),
2057
- /* @__PURE__ */ jsx16("p", { className: "pt-sub", children: ui.analysisSectionHints[section] }),
2058
- /* @__PURE__ */ jsx16("nav", { className: "pt-analysis__nav", "aria-label": ui.analysis, children: ANALYSIS_SECTIONS.map((id) => {
2282
+ return /* @__PURE__ */ jsxs15("div", { className: "pt-panel-page pt-panel-section pt-analysis", children: [
2283
+ /* @__PURE__ */ jsxs15("section", { children: [
2284
+ /* @__PURE__ */ jsx17("p", { className: "pt-eyebrow", children: ui.analysisEyebrow }),
2285
+ /* @__PURE__ */ jsx17("h2", { className: "pt-h2", children: ui.analysisSections[section] }),
2286
+ /* @__PURE__ */ jsx17("p", { className: "pt-sub", children: ui.analysisSectionHints[section] }),
2287
+ onRequestReport && /* @__PURE__ */ jsx17("p", { className: "pt-panel-row", children: /* @__PURE__ */ jsx17("button", { type: "button", className: "pt-btn pt-btn--sm", onClick: () => onRequestReport(section), children: ui.analysisRedo }) }),
2288
+ /* @__PURE__ */ jsx17("nav", { className: "pt-analysis__nav", "aria-label": ui.analysis, children: ANALYSIS_SECTIONS.map((id) => {
2059
2289
  const count = (analysis.choices?.[id] ?? []).filter(
2060
2290
  (choice) => !choice.options.some((option) => option.id === choice.value)
2061
2291
  ).length;
2062
- return /* @__PURE__ */ jsxs14(
2292
+ return /* @__PURE__ */ jsxs15(
2063
2293
  "button",
2064
2294
  {
2065
2295
  type: "button",
@@ -2068,110 +2298,110 @@ function AnalysisView({
2068
2298
  onClick: () => setSection(id),
2069
2299
  children: [
2070
2300
  ui.analysisSections[id],
2071
- count > 0 && /* @__PURE__ */ jsx16("span", { className: "pt-analysis__open", "aria-hidden": "true", children: count })
2301
+ count > 0 && /* @__PURE__ */ jsx17("span", { className: "pt-analysis__open", "aria-hidden": "true", children: count })
2072
2302
  ]
2073
2303
  },
2074
2304
  id
2075
2305
  );
2076
2306
  }) }),
2077
- here.length > 0 && /* @__PURE__ */ jsxs14("p", { className: "pt-analysis__stage", children: [
2307
+ here.length > 0 && /* @__PURE__ */ jsxs15("p", { className: "pt-analysis__stage", children: [
2078
2308
  ui.analysisAnswered(answeredHere, here.length),
2079
- answeredHere === here.length && /* @__PURE__ */ jsxs14(Fragment3, { children: [
2309
+ answeredHere === here.length && /* @__PURE__ */ jsxs15(Fragment3, { children: [
2080
2310
  " \xB7 ",
2081
2311
  ui.analysisAllDecided
2082
2312
  ] })
2083
2313
  ] })
2084
2314
  ] }),
2085
- section === "board" && /* @__PURE__ */ jsxs14(Fragment3, { children: [
2086
- /* @__PURE__ */ jsxs14("section", { children: [
2087
- /* @__PURE__ */ jsx16("h3", { className: "pt-cap__title", children: ui.boardFactsTitle }),
2088
- /* @__PURE__ */ jsx16("p", { className: "pt-sub", children: ui.boardFactsIntro }),
2089
- /* @__PURE__ */ jsx16("div", { className: "pt-fact-grid", children: [
2315
+ section === "board" && /* @__PURE__ */ jsxs15(Fragment3, { children: [
2316
+ /* @__PURE__ */ jsxs15("section", { children: [
2317
+ /* @__PURE__ */ jsx17("h3", { className: "pt-cap__title", children: ui.boardFactsTitle }),
2318
+ /* @__PURE__ */ jsx17("p", { className: "pt-sub", children: ui.boardFactsIntro }),
2319
+ /* @__PURE__ */ jsx17("div", { className: "pt-fact-grid", children: [
2090
2320
  [ui.factOpen, String(facts.open)],
2091
2321
  [ui.factWaiting, String(facts.waitingOnOwner)],
2092
2322
  [ui.factOrders, String(facts.orders)],
2093
2323
  [ui.factHighRisk, String(facts.highRisk)]
2094
- ].map(([label, value]) => /* @__PURE__ */ jsxs14("article", { className: "pt-fact", children: [
2095
- /* @__PURE__ */ jsx16("p", { className: "pt-fact__label", children: label }),
2096
- /* @__PURE__ */ jsx16("p", { className: "pt-fact__value", children: value })
2324
+ ].map(([label, value]) => /* @__PURE__ */ jsxs15("article", { className: "pt-fact", children: [
2325
+ /* @__PURE__ */ jsx17("p", { className: "pt-fact__label", children: label }),
2326
+ /* @__PURE__ */ jsx17("p", { className: "pt-fact__value", children: value })
2097
2327
  ] }, label)) }),
2098
- /* @__PURE__ */ jsx16("h4", { className: "pt-analysis__minor", children: ui.factColumnsTitle }),
2099
- /* @__PURE__ */ jsx16("ul", { className: "pt-analysis__list", children: facts.byColumn.map((column) => /* @__PURE__ */ jsxs14("li", { className: "pt-analysis__goal", children: [
2100
- /* @__PURE__ */ jsx16("span", { children: t(column.title) }),
2101
- /* @__PURE__ */ jsx16("span", { className: "pt-analysis__weight", children: column.count })
2328
+ /* @__PURE__ */ jsx17("h4", { className: "pt-analysis__minor", children: ui.factColumnsTitle }),
2329
+ /* @__PURE__ */ jsx17("ul", { className: "pt-analysis__list", children: facts.byColumn.map((column) => /* @__PURE__ */ jsxs15("li", { className: "pt-analysis__goal", children: [
2330
+ /* @__PURE__ */ jsx17("span", { children: t(column.title) }),
2331
+ /* @__PURE__ */ jsx17("span", { className: "pt-analysis__weight", children: column.count })
2102
2332
  ] }, column.id)) }),
2103
- facts.oldestOpen && facts.oldestOpenDays !== null && /* @__PURE__ */ jsxs14("p", { className: "pt-analysis__stage", children: [
2333
+ facts.oldestOpen && facts.oldestOpenDays !== null && /* @__PURE__ */ jsxs15("p", { className: "pt-analysis__stage", children: [
2104
2334
  ui.factOldest,
2105
2335
  ": ",
2106
- /* @__PURE__ */ jsx16("strong", { children: ui.factDays(facts.oldestOpenDays) }),
2336
+ /* @__PURE__ */ jsx17("strong", { children: ui.factDays(facts.oldestOpenDays) }),
2107
2337
  " \xB7 ",
2108
2338
  t(facts.oldestOpen.title)
2109
2339
  ] })
2110
2340
  ] }),
2111
- /* @__PURE__ */ jsxs14("section", { children: [
2112
- /* @__PURE__ */ jsx16("h3", { className: "pt-cap__title", children: ui.factClaimedTitle }),
2113
- /* @__PURE__ */ jsx16("p", { className: "pt-sub", children: ui.factClaimedIntro }),
2114
- facts.claimed.length === 0 ? /* @__PURE__ */ jsx16("p", { className: "pt-analysis__empty", children: ui.factClaimedNone }) : /* @__PURE__ */ jsx16("ul", { className: "pt-analysis__list", children: facts.claimed.map((card) => /* @__PURE__ */ jsxs14("li", { className: "pt-analysis__goal", children: [
2115
- /* @__PURE__ */ jsx16("button", { type: "button", className: "pt-analysis__link", onClick: () => onOpenCard?.(card.id), children: t(card.title) || ui.untitled }),
2116
- /* @__PURE__ */ jsx16("span", { className: "pt-analysis__weight", children: ui.neverStarted })
2341
+ /* @__PURE__ */ jsxs15("section", { children: [
2342
+ /* @__PURE__ */ jsx17("h3", { className: "pt-cap__title", children: ui.factClaimedTitle }),
2343
+ /* @__PURE__ */ jsx17("p", { className: "pt-sub", children: ui.factClaimedIntro }),
2344
+ facts.claimed.length === 0 ? /* @__PURE__ */ jsx17("p", { className: "pt-analysis__empty", children: ui.factClaimedNone }) : /* @__PURE__ */ jsx17("ul", { className: "pt-analysis__list", children: facts.claimed.map((card) => /* @__PURE__ */ jsxs15("li", { className: "pt-analysis__goal", children: [
2345
+ /* @__PURE__ */ jsx17("button", { type: "button", className: "pt-analysis__link", onClick: () => onOpenCard?.(card.id), children: t(card.title) || ui.untitled }),
2346
+ /* @__PURE__ */ jsx17("span", { className: "pt-analysis__weight", children: ui.neverStarted })
2117
2347
  ] }, card.id)) })
2118
2348
  ] })
2119
2349
  ] }),
2120
- section === "project" && /* @__PURE__ */ jsxs14(Fragment3, { children: [
2121
- /* @__PURE__ */ jsxs14("section", { children: [
2122
- /* @__PURE__ */ jsx16("h3", { className: "pt-cap__title", children: ui.briefTitle }),
2123
- /* @__PURE__ */ jsx16("p", { className: "pt-sub", children: t(analysis.brief) }),
2124
- /* @__PURE__ */ jsxs14("p", { className: "pt-analysis__stage", children: [
2350
+ section === "project" && /* @__PURE__ */ jsxs15(Fragment3, { children: [
2351
+ /* @__PURE__ */ jsxs15("section", { children: [
2352
+ /* @__PURE__ */ jsx17("h3", { className: "pt-cap__title", children: ui.briefTitle }),
2353
+ /* @__PURE__ */ jsx17("p", { className: "pt-sub", children: t(analysis.brief) }),
2354
+ /* @__PURE__ */ jsxs15("p", { className: "pt-analysis__stage", children: [
2125
2355
  ui.stage,
2126
2356
  ": ",
2127
- /* @__PURE__ */ jsx16("strong", { children: analysis.stage })
2357
+ /* @__PURE__ */ jsx17("strong", { children: analysis.stage })
2128
2358
  ] })
2129
2359
  ] }),
2130
- /* @__PURE__ */ jsxs14("section", { className: "pt-analysis__split", children: [
2131
- /* @__PURE__ */ jsxs14("div", { className: "pt-cap pt-hud", children: [
2132
- /* @__PURE__ */ jsx16("h3", { className: "pt-cap__title", children: ui.goalsTitle }),
2133
- /* @__PURE__ */ jsx16("ul", { className: "pt-analysis__list", children: analysis.goals.map((goal) => /* @__PURE__ */ jsxs14("li", { className: `pt-analysis__goal is-${goal.weight}`, children: [
2134
- /* @__PURE__ */ jsx16("span", { children: t(goal.label) }),
2135
- /* @__PURE__ */ jsx16("span", { className: "pt-analysis__weight", children: ui.weights[goal.weight] })
2360
+ /* @__PURE__ */ jsxs15("section", { className: "pt-analysis__split", children: [
2361
+ /* @__PURE__ */ jsxs15("div", { className: "pt-cap pt-hud", children: [
2362
+ /* @__PURE__ */ jsx17("h3", { className: "pt-cap__title", children: ui.goalsTitle }),
2363
+ /* @__PURE__ */ jsx17("ul", { className: "pt-analysis__list", children: analysis.goals.map((goal) => /* @__PURE__ */ jsxs15("li", { className: `pt-analysis__goal is-${goal.weight}`, children: [
2364
+ /* @__PURE__ */ jsx17("span", { children: t(goal.label) }),
2365
+ /* @__PURE__ */ jsx17("span", { className: "pt-analysis__weight", children: ui.weights[goal.weight] })
2136
2366
  ] }, goal.id)) })
2137
2367
  ] }),
2138
- /* @__PURE__ */ jsxs14("div", { className: "pt-cap pt-hud", children: [
2139
- /* @__PURE__ */ jsx16("h3", { className: "pt-cap__title", children: ui.constraintsTitle }),
2140
- /* @__PURE__ */ jsx16("ul", { className: "pt-analysis__list", children: analysis.constraints.map((constraint) => /* @__PURE__ */ jsxs14("li", { className: `pt-analysis__goal${constraint.on ? "" : " is-off"}`, children: [
2141
- /* @__PURE__ */ jsx16("span", { children: t(constraint.label) }),
2142
- /* @__PURE__ */ jsx16("span", { className: "pt-analysis__weight", children: constraint.on ? ui.constraintOn : ui.constraintOff })
2368
+ /* @__PURE__ */ jsxs15("div", { className: "pt-cap pt-hud", children: [
2369
+ /* @__PURE__ */ jsx17("h3", { className: "pt-cap__title", children: ui.constraintsTitle }),
2370
+ /* @__PURE__ */ jsx17("ul", { className: "pt-analysis__list", children: analysis.constraints.map((constraint) => /* @__PURE__ */ jsxs15("li", { className: `pt-analysis__goal${constraint.on ? "" : " is-off"}`, children: [
2371
+ /* @__PURE__ */ jsx17("span", { children: t(constraint.label) }),
2372
+ /* @__PURE__ */ jsx17("span", { className: "pt-analysis__weight", children: constraint.on ? ui.constraintOn : ui.constraintOff })
2143
2373
  ] }, constraint.id)) })
2144
2374
  ] })
2145
2375
  ] }),
2146
- /* @__PURE__ */ jsxs14("section", { children: [
2147
- /* @__PURE__ */ jsx16("h3", { className: "pt-cap__title", children: ui.metricsTitle }),
2148
- /* @__PURE__ */ jsx16("p", { className: "pt-sub", children: ui.metricsIntro }),
2149
- /* @__PURE__ */ jsx16("div", { className: "pt-metric-grid", children: analysis.metrics.map((metric) => /* @__PURE__ */ jsx16(MetricTile, { metric, lang, ui }, metric.id)) })
2376
+ /* @__PURE__ */ jsxs15("section", { children: [
2377
+ /* @__PURE__ */ jsx17("h3", { className: "pt-cap__title", children: ui.metricsTitle }),
2378
+ /* @__PURE__ */ jsx17("p", { className: "pt-sub", children: ui.metricsIntro }),
2379
+ /* @__PURE__ */ jsx17("div", { className: "pt-metric-grid", children: analysis.metrics.map((metric) => /* @__PURE__ */ jsx17(MetricTile, { metric, lang, ui }, metric.id)) })
2150
2380
  ] })
2151
2381
  ] }),
2152
- section === "strategy" && /* @__PURE__ */ jsxs14(Fragment3, { children: [
2153
- /* @__PURE__ */ jsxs14("section", { children: [
2154
- /* @__PURE__ */ jsx16("h3", { className: "pt-cap__title", children: ui.strategiesTitle }),
2155
- /* @__PURE__ */ jsx16("p", { className: "pt-sub", children: analysis.chosen ? ui.strategyChosenHint : ui.strategyOpenHint }),
2156
- /* @__PURE__ */ jsx16("div", { className: "pt-strategy-grid", children: analysis.strategies.map((strategy) => {
2382
+ section === "strategy" && /* @__PURE__ */ jsxs15(Fragment3, { children: [
2383
+ /* @__PURE__ */ jsxs15("section", { children: [
2384
+ /* @__PURE__ */ jsx17("h3", { className: "pt-cap__title", children: ui.strategiesTitle }),
2385
+ /* @__PURE__ */ jsx17("p", { className: "pt-sub", children: analysis.chosen ? ui.strategyChosenHint : ui.strategyOpenHint }),
2386
+ /* @__PURE__ */ jsx17("div", { className: "pt-strategy-grid", children: analysis.strategies.map((strategy) => {
2157
2387
  const chosen = analysis.chosen === strategy.id;
2158
- return /* @__PURE__ */ jsxs14("article", { className: `pt-strategy pt-hud${chosen ? " is-chosen" : ""}`, children: [
2159
- /* @__PURE__ */ jsx16("h4", { className: "pt-strategy__title", children: t(strategy.title) }),
2160
- /* @__PURE__ */ jsx16("p", { className: "pt-panel-text", children: t(strategy.thesis) }),
2161
- /* @__PURE__ */ jsx16("dl", { className: "pt-strategy__meters", children: [
2388
+ return /* @__PURE__ */ jsxs15("article", { className: `pt-strategy pt-hud${chosen ? " is-chosen" : ""}`, children: [
2389
+ /* @__PURE__ */ jsx17("h4", { className: "pt-strategy__title", children: t(strategy.title) }),
2390
+ /* @__PURE__ */ jsx17("p", { className: "pt-panel-text", children: t(strategy.thesis) }),
2391
+ /* @__PURE__ */ jsx17("dl", { className: "pt-strategy__meters", children: [
2162
2392
  [ui.effort, strategy.effort],
2163
2393
  [ui.riskShort, strategy.risk],
2164
2394
  [ui.upside, strategy.upside]
2165
- ].map(([label, value]) => /* @__PURE__ */ jsxs14("div", { children: [
2166
- /* @__PURE__ */ jsx16("dt", { children: label }),
2167
- /* @__PURE__ */ jsxs14("dd", { children: [
2168
- /* @__PURE__ */ jsx16("span", { className: "pt-strategy__track", children: /* @__PURE__ */ jsx16("span", { className: "pt-strategy__fill", style: { width: `${value * 10}%` } }) }),
2169
- /* @__PURE__ */ jsx16("b", { children: value })
2395
+ ].map(([label, value]) => /* @__PURE__ */ jsxs15("div", { children: [
2396
+ /* @__PURE__ */ jsx17("dt", { children: label }),
2397
+ /* @__PURE__ */ jsxs15("dd", { children: [
2398
+ /* @__PURE__ */ jsx17("span", { className: "pt-strategy__track", children: /* @__PURE__ */ jsx17("span", { className: "pt-strategy__fill", style: { width: `${value * 10}%` } }) }),
2399
+ /* @__PURE__ */ jsx17("b", { children: value })
2170
2400
  ] })
2171
2401
  ] }, label)) }),
2172
- /* @__PURE__ */ jsx16("p", { className: "pt-strategy__horizon", children: t(strategy.horizon) }),
2173
- /* @__PURE__ */ jsx16("ul", { className: "pt-cap__list", children: strategy.moves.map((move) => /* @__PURE__ */ jsx16("li", { children: t(move) }, t(move))) }),
2174
- /* @__PURE__ */ jsx16(
2402
+ /* @__PURE__ */ jsx17("p", { className: "pt-strategy__horizon", children: t(strategy.horizon) }),
2403
+ /* @__PURE__ */ jsx17("ul", { className: "pt-cap__list", children: strategy.moves.map((move) => /* @__PURE__ */ jsx17("li", { children: t(move) }, t(move))) }),
2404
+ /* @__PURE__ */ jsx17(
2175
2405
  FilterChip,
2176
2406
  {
2177
2407
  label: chosen ? ui.strategyChosen : ui.strategyChoose,
@@ -2182,19 +2412,19 @@ function AnalysisView({
2182
2412
  ] }, strategy.id);
2183
2413
  }) })
2184
2414
  ] }),
2185
- /* @__PURE__ */ jsxs14("section", { children: [
2186
- /* @__PURE__ */ jsx16("h3", { className: "pt-cap__title", children: ui.suggestionsTitle }),
2187
- /* @__PURE__ */ jsx16("p", { className: "pt-sub", children: ui.suggestionsIntro }),
2188
- /* @__PURE__ */ jsx16("ul", { className: "pt-analysis__suggestions", children: analysis.suggestions.map((suggestion) => /* @__PURE__ */ jsxs14("li", { className: `pt-suggestion pt-hud is-${suggestion.severity}`, children: [
2189
- /* @__PURE__ */ jsxs14("p", { className: "pt-suggestion__meta", children: [
2415
+ /* @__PURE__ */ jsxs15("section", { children: [
2416
+ /* @__PURE__ */ jsx17("h3", { className: "pt-cap__title", children: ui.suggestionsTitle }),
2417
+ /* @__PURE__ */ jsx17("p", { className: "pt-sub", children: ui.suggestionsIntro }),
2418
+ /* @__PURE__ */ jsx17("ul", { className: "pt-analysis__suggestions", children: analysis.suggestions.map((suggestion) => /* @__PURE__ */ jsxs15("li", { className: `pt-suggestion pt-hud is-${suggestion.severity}`, children: [
2419
+ /* @__PURE__ */ jsxs15("p", { className: "pt-suggestion__meta", children: [
2190
2420
  suggestion.area,
2191
2421
  " \xB7 ",
2192
2422
  ui.severities[suggestion.severity],
2193
2423
  " \xB7 ",
2194
2424
  suggestion.date
2195
2425
  ] }),
2196
- /* @__PURE__ */ jsx16("p", { className: "pt-panel-text", children: t(suggestion.text) }),
2197
- /* @__PURE__ */ jsx16("div", { className: "pt-panel-row", children: SUGGESTION_STATUSES.map((status) => /* @__PURE__ */ jsx16(
2426
+ /* @__PURE__ */ jsx17("p", { className: "pt-panel-text", children: t(suggestion.text) }),
2427
+ /* @__PURE__ */ jsx17("div", { className: "pt-panel-row", children: SUGGESTION_STATUSES.map((status) => /* @__PURE__ */ jsx17(
2198
2428
  FilterChip,
2199
2429
  {
2200
2430
  label: ui.suggestionStatuses[status],
@@ -2206,67 +2436,67 @@ function AnalysisView({
2206
2436
  ] }, suggestion.id)) })
2207
2437
  ] })
2208
2438
  ] }),
2209
- section === "market" && /* @__PURE__ */ jsx16("section", { children: analysis.market ? /* @__PURE__ */ jsxs14(Fragment3, { children: [
2210
- /* @__PURE__ */ jsxs14("div", { className: "pt-analysis__split", children: [
2211
- /* @__PURE__ */ jsxs14("div", { className: "pt-cap pt-hud", children: [
2212
- /* @__PURE__ */ jsx16("h3", { className: "pt-cap__title", children: ui.audienceTitle }),
2213
- /* @__PURE__ */ jsx16("p", { className: "pt-panel-text", children: t(analysis.market.audience) })
2439
+ section === "market" && /* @__PURE__ */ jsx17("section", { children: analysis.market ? /* @__PURE__ */ jsxs15(Fragment3, { children: [
2440
+ /* @__PURE__ */ jsxs15("div", { className: "pt-analysis__split", children: [
2441
+ /* @__PURE__ */ jsxs15("div", { className: "pt-cap pt-hud", children: [
2442
+ /* @__PURE__ */ jsx17("h3", { className: "pt-cap__title", children: ui.audienceTitle }),
2443
+ /* @__PURE__ */ jsx17("p", { className: "pt-panel-text", children: t(analysis.market.audience) })
2214
2444
  ] }),
2215
- /* @__PURE__ */ jsxs14("div", { className: "pt-cap pt-hud", children: [
2216
- /* @__PURE__ */ jsx16("h3", { className: "pt-cap__title", children: ui.positioningTitle }),
2217
- /* @__PURE__ */ jsx16("p", { className: "pt-panel-text", children: t(analysis.market.positioning) })
2445
+ /* @__PURE__ */ jsxs15("div", { className: "pt-cap pt-hud", children: [
2446
+ /* @__PURE__ */ jsx17("h3", { className: "pt-cap__title", children: ui.positioningTitle }),
2447
+ /* @__PURE__ */ jsx17("p", { className: "pt-panel-text", children: t(analysis.market.positioning) })
2218
2448
  ] })
2219
2449
  ] }),
2220
- /* @__PURE__ */ jsx16("h3", { className: "pt-cap__title pt-analysis__minor", children: ui.competitorsTitle }),
2221
- /* @__PURE__ */ jsx16("p", { className: "pt-sub", children: ui.marketIntro }),
2222
- /* @__PURE__ */ jsx16("div", { className: "pt-rival-grid", children: analysis.market.competitors.map((rival) => /* @__PURE__ */ jsxs14("article", { className: "pt-rival pt-hud", children: [
2223
- /* @__PURE__ */ jsx16("h4", { className: "pt-rival__name", children: rival.name }),
2224
- /* @__PURE__ */ jsxs14("p", { className: "pt-rival__line", children: [
2225
- /* @__PURE__ */ jsx16("span", { className: "pt-rival__tag", children: ui.competitorStrength }),
2450
+ /* @__PURE__ */ jsx17("h3", { className: "pt-cap__title pt-analysis__minor", children: ui.competitorsTitle }),
2451
+ /* @__PURE__ */ jsx17("p", { className: "pt-sub", children: ui.marketIntro }),
2452
+ /* @__PURE__ */ jsx17("div", { className: "pt-rival-grid", children: analysis.market.competitors.map((rival) => /* @__PURE__ */ jsxs15("article", { className: "pt-rival pt-hud", children: [
2453
+ /* @__PURE__ */ jsx17("h4", { className: "pt-rival__name", children: rival.name }),
2454
+ /* @__PURE__ */ jsxs15("p", { className: "pt-rival__line", children: [
2455
+ /* @__PURE__ */ jsx17("span", { className: "pt-rival__tag", children: ui.competitorStrength }),
2226
2456
  t(rival.strength)
2227
2457
  ] }),
2228
- /* @__PURE__ */ jsxs14("p", { className: "pt-rival__line is-gap", children: [
2229
- /* @__PURE__ */ jsx16("span", { className: "pt-rival__tag", children: ui.competitorGap }),
2458
+ /* @__PURE__ */ jsxs15("p", { className: "pt-rival__line is-gap", children: [
2459
+ /* @__PURE__ */ jsx17("span", { className: "pt-rival__tag", children: ui.competitorGap }),
2230
2460
  t(rival.gap)
2231
2461
  ] })
2232
2462
  ] }, rival.id)) }),
2233
- analysis.market.pricing && /* @__PURE__ */ jsxs14(Fragment3, { children: [
2234
- /* @__PURE__ */ jsx16("h3", { className: "pt-cap__title pt-analysis__minor", children: ui.pricingTitle }),
2235
- /* @__PURE__ */ jsx16("p", { className: "pt-panel-text", children: t(analysis.market.pricing) })
2463
+ analysis.market.pricing && /* @__PURE__ */ jsxs15(Fragment3, { children: [
2464
+ /* @__PURE__ */ jsx17("h3", { className: "pt-cap__title pt-analysis__minor", children: ui.pricingTitle }),
2465
+ /* @__PURE__ */ jsx17("p", { className: "pt-panel-text", children: t(analysis.market.pricing) })
2236
2466
  ] }),
2237
- analysis.market.notes && analysis.market.notes.length > 0 && /* @__PURE__ */ jsxs14(Fragment3, { children: [
2238
- /* @__PURE__ */ jsx16("h3", { className: "pt-cap__title pt-analysis__minor", children: ui.marketNotesTitle }),
2239
- /* @__PURE__ */ jsx16("ul", { className: "pt-cap__list", children: analysis.market.notes.map((note) => /* @__PURE__ */ jsx16("li", { children: t(note) }, t(note))) })
2467
+ analysis.market.notes && analysis.market.notes.length > 0 && /* @__PURE__ */ jsxs15(Fragment3, { children: [
2468
+ /* @__PURE__ */ jsx17("h3", { className: "pt-cap__title pt-analysis__minor", children: ui.marketNotesTitle }),
2469
+ /* @__PURE__ */ jsx17("ul", { className: "pt-cap__list", children: analysis.market.notes.map((note) => /* @__PURE__ */ jsx17("li", { children: t(note) }, t(note))) })
2240
2470
  ] })
2241
- ] }) : /* @__PURE__ */ jsx16("p", { className: "pt-analysis__empty", children: ui.marketEmpty }) }),
2242
- /* @__PURE__ */ jsx16(Choices, { section, analysis, lang, ui, onDecide }),
2243
- total > 0 && /* @__PURE__ */ jsxs14("section", { className: "pt-analysis__split", children: [
2244
- /* @__PURE__ */ jsxs14("div", { className: "pt-cap pt-hud", children: [
2245
- /* @__PURE__ */ jsx16("h3", { className: "pt-cap__title", children: ui.claudeReadsTitle }),
2246
- /* @__PURE__ */ jsx16("p", { className: "pt-sub", children: ui.claudeReadsIntro }),
2247
- /* @__PURE__ */ jsxs14("ul", { className: "pt-analysis__list", children: [
2248
- answers.map(({ section: from, choice, option }) => /* @__PURE__ */ jsxs14("li", { className: "pt-analysis__goal is-primary", children: [
2249
- /* @__PURE__ */ jsxs14("span", { children: [
2250
- /* @__PURE__ */ jsx16("span", { className: "pt-analysis__from", children: ui.analysisSections[from] }),
2471
+ ] }) : /* @__PURE__ */ jsx17("p", { className: "pt-analysis__empty", children: ui.marketEmpty }) }),
2472
+ /* @__PURE__ */ jsx17(Choices, { section, analysis, lang, ui, onDecide }),
2473
+ total > 0 && /* @__PURE__ */ jsxs15("section", { className: "pt-analysis__split", children: [
2474
+ /* @__PURE__ */ jsxs15("div", { className: "pt-cap pt-hud", children: [
2475
+ /* @__PURE__ */ jsx17("h3", { className: "pt-cap__title", children: ui.claudeReadsTitle }),
2476
+ /* @__PURE__ */ jsx17("p", { className: "pt-sub", children: ui.claudeReadsIntro }),
2477
+ /* @__PURE__ */ jsxs15("ul", { className: "pt-analysis__list", children: [
2478
+ answers.map(({ section: from, choice, option }) => /* @__PURE__ */ jsxs15("li", { className: "pt-analysis__goal is-primary", children: [
2479
+ /* @__PURE__ */ jsxs15("span", { children: [
2480
+ /* @__PURE__ */ jsx17("span", { className: "pt-analysis__from", children: ui.analysisSections[from] }),
2251
2481
  t(choice.question)
2252
2482
  ] }),
2253
- /* @__PURE__ */ jsx16("span", { className: "pt-analysis__weight", children: t(option.label) })
2483
+ /* @__PURE__ */ jsx17("span", { className: "pt-analysis__weight", children: t(option.label) })
2254
2484
  ] }, choice.id)),
2255
- answers.length === 0 && /* @__PURE__ */ jsx16("li", { className: "pt-analysis__goal is-off", children: ui.choicesNone })
2485
+ answers.length === 0 && /* @__PURE__ */ jsx17("li", { className: "pt-analysis__goal is-off", children: ui.choicesNone })
2256
2486
  ] })
2257
2487
  ] }),
2258
- /* @__PURE__ */ jsxs14("div", { className: "pt-cap pt-hud", children: [
2259
- /* @__PURE__ */ jsx16("h3", { className: "pt-cap__title", children: ui.claudeOpenTitle }),
2260
- /* @__PURE__ */ jsx16("p", { className: "pt-sub", children: ui.claudeOpenIntro }),
2261
- /* @__PURE__ */ jsxs14("ul", { className: "pt-analysis__list", children: [
2262
- open.map(({ section: from, choice }) => /* @__PURE__ */ jsxs14("li", { className: "pt-analysis__goal", children: [
2263
- /* @__PURE__ */ jsxs14("button", { type: "button", className: "pt-analysis__link", onClick: () => setSection(from), children: [
2264
- /* @__PURE__ */ jsx16("span", { className: "pt-analysis__from", children: ui.analysisSections[from] }),
2488
+ /* @__PURE__ */ jsxs15("div", { className: "pt-cap pt-hud", children: [
2489
+ /* @__PURE__ */ jsx17("h3", { className: "pt-cap__title", children: ui.claudeOpenTitle }),
2490
+ /* @__PURE__ */ jsx17("p", { className: "pt-sub", children: ui.claudeOpenIntro }),
2491
+ /* @__PURE__ */ jsxs15("ul", { className: "pt-analysis__list", children: [
2492
+ open.map(({ section: from, choice }) => /* @__PURE__ */ jsxs15("li", { className: "pt-analysis__goal", children: [
2493
+ /* @__PURE__ */ jsxs15("button", { type: "button", className: "pt-analysis__link", onClick: () => setSection(from), children: [
2494
+ /* @__PURE__ */ jsx17("span", { className: "pt-analysis__from", children: ui.analysisSections[from] }),
2265
2495
  t(choice.question)
2266
2496
  ] }),
2267
- /* @__PURE__ */ jsx16("span", { className: "pt-analysis__weight", children: ui.choiceOpen })
2497
+ /* @__PURE__ */ jsx17("span", { className: "pt-analysis__weight", children: ui.choiceOpen })
2268
2498
  ] }, choice.id)),
2269
- open.length === 0 && /* @__PURE__ */ jsx16("li", { className: "pt-analysis__goal is-off", children: ui.analysisAllDecided })
2499
+ open.length === 0 && /* @__PURE__ */ jsx17("li", { className: "pt-analysis__goal is-off", children: ui.analysisAllDecided })
2270
2500
  ] })
2271
2501
  ] })
2272
2502
  ] })
@@ -2274,7 +2504,7 @@ function AnalysisView({
2274
2504
  }
2275
2505
 
2276
2506
  // src/panel/MarketplaceView.tsx
2277
- import { useMemo as useMemo4, useState as useState7 } from "react";
2507
+ import { useMemo as useMemo4, useState as useState8 } from "react";
2278
2508
 
2279
2509
  // src/panel/marketplace.ts
2280
2510
  var MARKETPLACE_NAME = "dfklabs";
@@ -2317,39 +2547,39 @@ function ageInWords(seconds, lang) {
2317
2547
  }
2318
2548
 
2319
2549
  // src/panel/MarketplaceView.tsx
2320
- import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
2550
+ import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
2321
2551
  function ToolRow({
2322
2552
  tool,
2323
2553
  lang,
2324
2554
  ui,
2325
2555
  onInstall
2326
2556
  }) {
2327
- return /* @__PURE__ */ jsxs15("article", { className: `pt-tool${tool.state ? ` is-${tool.state}` : " is-command"}`, children: [
2328
- /* @__PURE__ */ jsxs15("div", { className: "pt-tool__head", children: [
2329
- /* @__PURE__ */ jsx17("h3", { className: "pt-tool__name", children: tool.name }),
2330
- /* @__PURE__ */ jsx17("span", { className: "pt-tool__state", children: tool.state ? ui.installStates[tool.state] : ui.toolCommandOnly })
2557
+ return /* @__PURE__ */ jsxs16("article", { className: `pt-tool${tool.state ? ` is-${tool.state}` : " is-command"}`, children: [
2558
+ /* @__PURE__ */ jsxs16("div", { className: "pt-tool__head", children: [
2559
+ /* @__PURE__ */ jsx18("h3", { className: "pt-tool__name", children: tool.name }),
2560
+ /* @__PURE__ */ jsx18("span", { className: "pt-tool__state", children: tool.state ? ui.installStates[tool.state] : ui.toolCommandOnly })
2331
2561
  ] }),
2332
- tool.summary && /* @__PURE__ */ jsx17("p", { className: "pt-panel-text", children: tool.summary }),
2333
- /* @__PURE__ */ jsxs15("p", { className: "pt-tool__meta", children: [
2334
- /* @__PURE__ */ jsx17("span", { className: "pt-tool__id", children: tool.id }),
2335
- tool.claudePlugin && /* @__PURE__ */ jsxs15(Fragment4, { children: [
2562
+ tool.summary && /* @__PURE__ */ jsx18("p", { className: "pt-panel-text", children: tool.summary }),
2563
+ /* @__PURE__ */ jsxs16("p", { className: "pt-tool__meta", children: [
2564
+ /* @__PURE__ */ jsx18("span", { className: "pt-tool__id", children: tool.id }),
2565
+ tool.claudePlugin && /* @__PURE__ */ jsxs16(Fragment4, { children: [
2336
2566
  " \xB7 ",
2337
- tool.version ? /* @__PURE__ */ jsxs15("span", { className: "pt-tool__version", children: [
2567
+ tool.version ? /* @__PURE__ */ jsxs16("span", { className: "pt-tool__version", children: [
2338
2568
  "v",
2339
2569
  tool.version
2340
2570
  ] }) : (
2341
2571
  // Never a version we made up. A blank here is the plugin's own
2342
2572
  // manifest failing to answer, and it says so on hover.
2343
- /* @__PURE__ */ jsx17("span", { className: "pt-tool__version is-unknown", title: tool.versionError ?? void 0, children: ui.versionUnknown })
2573
+ /* @__PURE__ */ jsx18("span", { className: "pt-tool__version is-unknown", title: tool.versionError ?? void 0, children: ui.versionUnknown })
2344
2574
  )
2345
2575
  ] }),
2346
- tool.repo && /* @__PURE__ */ jsxs15(Fragment4, { children: [
2576
+ tool.repo && /* @__PURE__ */ jsxs16(Fragment4, { children: [
2347
2577
  " \xB7 ",
2348
- /* @__PURE__ */ jsx17("a", { className: "pt-tool__repo", href: `https://github.com/${tool.repo}`, target: "_blank", rel: "noreferrer", children: tool.repo })
2578
+ /* @__PURE__ */ jsx18("a", { className: "pt-tool__repo", href: `https://github.com/${tool.repo}`, target: "_blank", rel: "noreferrer", children: tool.repo })
2349
2579
  ] })
2350
2580
  ] }),
2351
- tool.tags.length > 0 && /* @__PURE__ */ jsx17("p", { className: "pt-tool__tags", children: tool.tags.map((tag) => /* @__PURE__ */ jsx17("span", { className: "pt-tool__tag", children: tag }, tag)) }),
2352
- !tool.claudePlugin && tool.standaloneCommand && /* @__PURE__ */ jsx17(
2581
+ tool.tags.length > 0 && /* @__PURE__ */ jsx18("p", { className: "pt-tool__tags", children: tool.tags.map((tag) => /* @__PURE__ */ jsx18("span", { className: "pt-tool__tag", children: tag }, tag)) }),
2582
+ !tool.claudePlugin && tool.standaloneCommand && /* @__PURE__ */ jsx18(
2353
2583
  CopyBlock,
2354
2584
  {
2355
2585
  text: tool.standaloneCommand,
@@ -2357,16 +2587,16 @@ function ToolRow({
2357
2587
  labels: { copy: ui.copy, copied: ui.copied, selected: ui.copySelected }
2358
2588
  }
2359
2589
  ),
2360
- /* @__PURE__ */ jsxs15("div", { className: "pt-panel-row pt-tool__actions", children: [
2361
- /* @__PURE__ */ jsx17("button", { type: "button", className: "pt-btn pt-btn--sm", onClick: () => onInstall(tool), children: tool.claudePlugin ? ui.install : ui.howToRun }),
2362
- tool.homepage && /* @__PURE__ */ jsx17("a", { className: "pt-btn pt-btn--sm", href: tool.homepage, target: "_blank", rel: "noreferrer", children: ui.learnMore })
2590
+ /* @__PURE__ */ jsxs16("div", { className: "pt-panel-row pt-tool__actions", children: [
2591
+ /* @__PURE__ */ jsx18("button", { type: "button", className: "pt-btn pt-btn--sm", onClick: () => onInstall(tool), children: tool.claudePlugin ? ui.install : ui.howToRun }),
2592
+ tool.homepage && /* @__PURE__ */ jsx18("a", { className: "pt-btn pt-btn--sm", href: tool.homepage, target: "_blank", rel: "noreferrer", children: ui.learnMore })
2363
2593
  ] }),
2364
- tool.state === "misconfigured" && /* @__PURE__ */ jsx17("p", { className: "pt-warn", children: ui.stateMisconfiguredWhy })
2594
+ tool.state === "misconfigured" && /* @__PURE__ */ jsx18("p", { className: "pt-warn", children: ui.stateMisconfiguredWhy })
2365
2595
  ] });
2366
2596
  }
2367
2597
  function MarketplaceView({ report, loading, failure, lang, ui, onRefresh }) {
2368
- const [filter, setFilter] = useState7("all");
2369
- const [open, setOpen] = useState7(null);
2598
+ const [filter, setFilter] = useState8("all");
2599
+ const [open, setOpen] = useState8(null);
2370
2600
  const tools = report?.tools ?? [];
2371
2601
  const shown = useMemo4(() => {
2372
2602
  if (filter === "plugins") return tools.filter((tool) => tool.claudePlugin);
@@ -2383,39 +2613,39 @@ function MarketplaceView({ report, loading, failure, lang, ui, onRefresh }) {
2383
2613
  }),
2384
2614
  [tools]
2385
2615
  );
2386
- return /* @__PURE__ */ jsxs15("div", { className: "pt-panel-page pt-panel-section pt-marketplace", children: [
2387
- /* @__PURE__ */ jsxs15("section", { children: [
2388
- /* @__PURE__ */ jsx17("p", { className: "pt-eyebrow", children: report?.marketplace.name ?? ui.marketplaceEyebrow }),
2389
- /* @__PURE__ */ jsx17("h2", { className: "pt-h2", children: ui.marketplaceTitle }),
2390
- /* @__PURE__ */ jsx17("p", { className: "pt-sub", children: ui.marketplaceIntro }),
2391
- /* @__PURE__ */ jsxs15("div", { className: "pt-panel-row pt-marketplace__status", children: [
2392
- onRefresh && /* @__PURE__ */ jsx17("button", { type: "button", className: "pt-btn pt-btn--sm", onClick: onRefresh, disabled: loading, children: loading ? ui.refreshing : ui.refresh }),
2393
- report && onRefresh && /* @__PURE__ */ jsx17("span", { className: "pt-marketplace__age", children: ui.readAt(ageInWords(report.ageSeconds, lang)) })
2616
+ return /* @__PURE__ */ jsxs16("div", { className: "pt-panel-page pt-panel-section pt-marketplace", children: [
2617
+ /* @__PURE__ */ jsxs16("section", { children: [
2618
+ /* @__PURE__ */ jsx18("p", { className: "pt-eyebrow", children: report?.marketplace.name ?? ui.marketplaceEyebrow }),
2619
+ /* @__PURE__ */ jsx18("h2", { className: "pt-h2", children: ui.marketplaceTitle }),
2620
+ /* @__PURE__ */ jsx18("p", { className: "pt-sub", children: ui.marketplaceIntro }),
2621
+ /* @__PURE__ */ jsxs16("div", { className: "pt-panel-row pt-marketplace__status", children: [
2622
+ onRefresh && /* @__PURE__ */ jsx18("button", { type: "button", className: "pt-btn pt-btn--sm", onClick: onRefresh, disabled: loading, children: loading ? ui.refreshing : ui.refresh }),
2623
+ report && onRefresh && /* @__PURE__ */ jsx18("span", { className: "pt-marketplace__age", children: ui.readAt(ageInWords(report.ageSeconds, lang)) })
2394
2624
  ] }),
2395
- report?.stale && !report.unavailable && /* @__PURE__ */ jsx17("p", { className: "pt-warn", children: ui.catalogueStale(ageInWords(report.ageSeconds, lang)) }),
2396
- report?.unavailable && /* @__PURE__ */ jsx17("p", { className: "pt-warn", children: ui.catalogueUnavailable }),
2397
- failure && /* @__PURE__ */ jsx17("p", { className: "pt-warn", children: ui.catalogueFailed })
2625
+ report?.stale && !report.unavailable && /* @__PURE__ */ jsx18("p", { className: "pt-warn", children: ui.catalogueStale(ageInWords(report.ageSeconds, lang)) }),
2626
+ report?.unavailable && /* @__PURE__ */ jsx18("p", { className: "pt-warn", children: ui.catalogueUnavailable }),
2627
+ failure && /* @__PURE__ */ jsx18("p", { className: "pt-warn", children: ui.catalogueFailed })
2398
2628
  ] }),
2399
- report && /* @__PURE__ */ jsxs15("section", { children: [
2400
- /* @__PURE__ */ jsxs15("p", { className: "pt-marketplace__project", children: [
2629
+ report && /* @__PURE__ */ jsxs16("section", { children: [
2630
+ /* @__PURE__ */ jsxs16("p", { className: "pt-marketplace__project", children: [
2401
2631
  ui.stateFrom(report.project.repo, SETTINGS_PATH),
2402
- report.project.settingsStatus === "absent" && /* @__PURE__ */ jsxs15(Fragment4, { children: [
2632
+ report.project.settingsStatus === "absent" && /* @__PURE__ */ jsxs16(Fragment4, { children: [
2403
2633
  " \xB7 ",
2404
2634
  ui.settingsAbsent
2405
2635
  ] }),
2406
- report.project.settingsStatus === "unreadable" && /* @__PURE__ */ jsxs15(Fragment4, { children: [
2636
+ report.project.settingsStatus === "unreadable" && /* @__PURE__ */ jsxs16(Fragment4, { children: [
2407
2637
  " \xB7 ",
2408
2638
  ui.settingsUnreadable
2409
2639
  ] }),
2410
- report.project.settingsStatus === "unparseable" && /* @__PURE__ */ jsxs15(Fragment4, { children: [
2640
+ report.project.settingsStatus === "unparseable" && /* @__PURE__ */ jsxs16(Fragment4, { children: [
2411
2641
  " \xB7 ",
2412
2642
  ui.settingsUnparseable
2413
2643
  ] })
2414
2644
  ] }),
2415
- report.project.detail && /* @__PURE__ */ jsx17("p", { className: "pt-marketplace__detail", children: report.project.detail }),
2416
- /* @__PURE__ */ jsxs15("div", { className: "pt-panel-row pt-marketplace__filters", children: [
2417
- /* @__PURE__ */ jsx17(FilterChip, { label: ui.all, count: counts.all, active: filter === "all", onClick: () => setFilter("all") }),
2418
- /* @__PURE__ */ jsx17(
2645
+ report.project.detail && /* @__PURE__ */ jsx18("p", { className: "pt-marketplace__detail", children: report.project.detail }),
2646
+ /* @__PURE__ */ jsxs16("div", { className: "pt-panel-row pt-marketplace__filters", children: [
2647
+ /* @__PURE__ */ jsx18(FilterChip, { label: ui.all, count: counts.all, active: filter === "all", onClick: () => setFilter("all") }),
2648
+ /* @__PURE__ */ jsx18(
2419
2649
  FilterChip,
2420
2650
  {
2421
2651
  label: ui.filterPlugins,
@@ -2424,7 +2654,7 @@ function MarketplaceView({ report, loading, failure, lang, ui, onRefresh }) {
2424
2654
  onClick: () => setFilter("plugins")
2425
2655
  }
2426
2656
  ),
2427
- /* @__PURE__ */ jsx17(
2657
+ /* @__PURE__ */ jsx18(
2428
2658
  FilterChip,
2429
2659
  {
2430
2660
  label: ui.filterActive,
@@ -2433,7 +2663,7 @@ function MarketplaceView({ report, loading, failure, lang, ui, onRefresh }) {
2433
2663
  onClick: () => setFilter("active")
2434
2664
  }
2435
2665
  ),
2436
- /* @__PURE__ */ jsx17(
2666
+ /* @__PURE__ */ jsx18(
2437
2667
  FilterChip,
2438
2668
  {
2439
2669
  label: ui.filterStandalone,
@@ -2443,12 +2673,12 @@ function MarketplaceView({ report, loading, failure, lang, ui, onRefresh }) {
2443
2673
  }
2444
2674
  )
2445
2675
  ] }),
2446
- loading && tools.length === 0 ? /* @__PURE__ */ jsx17("p", { className: "pt-analysis__empty", children: ui.catalogueLoading }) : shown.length === 0 ? /* @__PURE__ */ jsx17("p", { className: "pt-analysis__empty", children: ui.catalogueEmpty }) : /* @__PURE__ */ jsx17("div", { className: "pt-tool-grid", children: shown.map((tool) => /* @__PURE__ */ jsx17(ToolRow, { tool, lang, ui, onInstall: setOpen }, tool.id)) })
2676
+ loading && tools.length === 0 ? /* @__PURE__ */ jsx18("p", { className: "pt-analysis__empty", children: ui.catalogueLoading }) : shown.length === 0 ? /* @__PURE__ */ jsx18("p", { className: "pt-analysis__empty", children: ui.catalogueEmpty }) : /* @__PURE__ */ jsx18("div", { className: "pt-tool-grid", children: shown.map((tool) => /* @__PURE__ */ jsx18(ToolRow, { tool, lang, ui, onInstall: setOpen }, tool.id)) })
2447
2677
  ] }),
2448
- open && /* @__PURE__ */ jsxs15(DetailSheet, { open: true, onClose: () => setOpen(null), ariaLabel: `${ui.installTitle} \u2014 ${open.name}`, children: [
2449
- /* @__PURE__ */ jsx17("p", { className: "pt-eyebrow", children: ui.installTitle }),
2450
- /* @__PURE__ */ jsx17("h2", { className: "pt-h2", children: open.name }),
2451
- /* @__PURE__ */ jsx17(
2678
+ open && /* @__PURE__ */ jsxs16(DetailSheet, { open: true, onClose: () => setOpen(null), ariaLabel: `${ui.installTitle} \u2014 ${open.name}`, children: [
2679
+ /* @__PURE__ */ jsx18("p", { className: "pt-eyebrow", children: ui.installTitle }),
2680
+ /* @__PURE__ */ jsx18("h2", { className: "pt-h2", children: open.name }),
2681
+ /* @__PURE__ */ jsx18(
2452
2682
  InstallSheet,
2453
2683
  {
2454
2684
  tool: open,
@@ -2457,7 +2687,7 @@ function MarketplaceView({ report, loading, failure, lang, ui, onRefresh }) {
2457
2687
  registered: report?.project.marketplaceRegistered ?? false
2458
2688
  }
2459
2689
  ),
2460
- /* @__PURE__ */ jsx17("button", { type: "button", className: "pt-btn pt-btn--sm", onClick: () => setOpen(null), children: ui.close })
2690
+ /* @__PURE__ */ jsx18("button", { type: "button", className: "pt-btn pt-btn--sm", onClick: () => setOpen(null), children: ui.close })
2461
2691
  ] })
2462
2692
  ] });
2463
2693
  }
@@ -2468,9 +2698,9 @@ function InstallSheet({
2468
2698
  registered
2469
2699
  }) {
2470
2700
  const copy = { copy: ui.copy, copied: ui.copied, selected: ui.copySelected };
2471
- return /* @__PURE__ */ jsxs15(Fragment4, { children: [
2472
- tool.claudePlugin ? /* @__PURE__ */ jsxs15(Fragment4, { children: [
2473
- /* @__PURE__ */ jsx17(DetailSection, { title: ui.installRepoTitle, subtitle: ui.installRepoHint, children: /* @__PURE__ */ jsx17(
2701
+ return /* @__PURE__ */ jsxs16(Fragment4, { children: [
2702
+ tool.claudePlugin ? /* @__PURE__ */ jsxs16(Fragment4, { children: [
2703
+ /* @__PURE__ */ jsx18(DetailSection, { title: ui.installRepoTitle, subtitle: ui.installRepoHint, children: /* @__PURE__ */ jsx18(
2474
2704
  CopyBlock,
2475
2705
  {
2476
2706
  text: repositorySnippet(tool.id, marketplace),
@@ -2479,24 +2709,24 @@ function InstallSheet({
2479
2709
  labels: copy
2480
2710
  }
2481
2711
  ) }),
2482
- /* @__PURE__ */ jsx17(DetailSection, { title: ui.installCliTitle, subtitle: ui.installCliHint, children: /* @__PURE__ */ jsx17(CopyBlock, { text: commandSnippet(tool.id, marketplace), labels: copy }) })
2483
- ] }) : /* @__PURE__ */ jsx17("p", { className: "pt-panel-text", children: ui.installNoPlugin }),
2484
- tool.standaloneCommand ? /* @__PURE__ */ jsx17(DetailSection, { title: ui.installStandaloneTitle, subtitle: ui.installStandaloneHint, children: /* @__PURE__ */ jsx17(CopyBlock, { text: tool.standaloneCommand, labels: copy }) }) : /* @__PURE__ */ jsx17(DetailSection, { title: ui.installStandaloneTitle, children: /* @__PURE__ */ jsx17("p", { className: "pt-panel-text", children: ui.installNoStandalone }) }),
2485
- /* @__PURE__ */ jsx17("p", { className: "pt-marketplace__source", children: ui.marketplaceSource(marketplace.url) })
2712
+ /* @__PURE__ */ jsx18(DetailSection, { title: ui.installCliTitle, subtitle: ui.installCliHint, children: /* @__PURE__ */ jsx18(CopyBlock, { text: commandSnippet(tool.id, marketplace), labels: copy }) })
2713
+ ] }) : /* @__PURE__ */ jsx18("p", { className: "pt-panel-text", children: ui.installNoPlugin }),
2714
+ tool.standaloneCommand ? /* @__PURE__ */ jsx18(DetailSection, { title: ui.installStandaloneTitle, subtitle: ui.installStandaloneHint, children: /* @__PURE__ */ jsx18(CopyBlock, { text: tool.standaloneCommand, labels: copy }) }) : /* @__PURE__ */ jsx18(DetailSection, { title: ui.installStandaloneTitle, children: /* @__PURE__ */ jsx18("p", { className: "pt-panel-text", children: ui.installNoStandalone }) }),
2715
+ /* @__PURE__ */ jsx18("p", { className: "pt-marketplace__source", children: ui.marketplaceSource(marketplace.url) })
2486
2716
  ] });
2487
2717
  }
2488
2718
 
2489
2719
  // src/panel/CardSheet.tsx
2490
- import { useState as useState8 } from "react";
2491
- import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
2720
+ import { useState as useState9 } from "react";
2721
+ import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
2492
2722
  var LEVEL_LABEL = (ui) => ({
2493
2723
  high: ui.levelHigh,
2494
2724
  medium: ui.levelMedium,
2495
2725
  low: ui.levelLow
2496
2726
  });
2497
2727
  function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }) {
2498
- const [step, setStep] = useState8("");
2499
- const [note, setNote] = useState8("");
2728
+ const [step, setStep] = useState9("");
2729
+ const [note, setNote] = useState9("");
2500
2730
  if (!card) return null;
2501
2731
  const patch = (changes) => onChange({ ...card, ...changes, updatedAt: today() });
2502
2732
  const levelLabel = LEVEL_LABEL(ui);
@@ -2515,9 +2745,9 @@ function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }) {
2515
2745
  });
2516
2746
  setNote("");
2517
2747
  }
2518
- return /* @__PURE__ */ jsxs16(DetailSheet, { open: true, onClose, ariaLabel: ui.cardDetail, children: [
2519
- /* @__PURE__ */ jsxs16(DetailSection, { title: ui.title, children: [
2520
- /* @__PURE__ */ jsx18(
2748
+ return /* @__PURE__ */ jsxs17(DetailSheet, { open: true, onClose, ariaLabel: ui.cardDetail, children: [
2749
+ /* @__PURE__ */ jsxs17(DetailSection, { title: ui.title, children: [
2750
+ /* @__PURE__ */ jsx19(
2521
2751
  "input",
2522
2752
  {
2523
2753
  className: "pt-input",
@@ -2526,9 +2756,9 @@ function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }) {
2526
2756
  onChange: (event) => patch({ title: writeText(lang, event.target.value) })
2527
2757
  }
2528
2758
  ),
2529
- untranslated(card.title) && /* @__PURE__ */ jsx18("span", { className: "pt-flag", children: ui.untranslatedBadge })
2759
+ untranslated(card.title) && /* @__PURE__ */ jsx19("span", { className: "pt-flag", children: ui.untranslatedBadge })
2530
2760
  ] }),
2531
- /* @__PURE__ */ jsx18(DetailSection, { title: ui.detail, children: /* @__PURE__ */ jsx18(
2761
+ /* @__PURE__ */ jsx19(DetailSection, { title: ui.detail, children: /* @__PURE__ */ jsx19(
2532
2762
  "textarea",
2533
2763
  {
2534
2764
  className: "pt-textarea",
@@ -2538,7 +2768,7 @@ function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }) {
2538
2768
  onChange: (event) => patch({ body: writeText(lang, event.target.value) })
2539
2769
  }
2540
2770
  ) }),
2541
- /* @__PURE__ */ jsx18(DetailSection, { title: ui.areaLabel, children: /* @__PURE__ */ jsx18("div", { className: "pt-panel-row", children: state.areas.map((area) => /* @__PURE__ */ jsx18(
2771
+ /* @__PURE__ */ jsx19(DetailSection, { title: ui.areaLabel, children: /* @__PURE__ */ jsx19("div", { className: "pt-panel-row", children: state.areas.map((area) => /* @__PURE__ */ jsx19(
2542
2772
  FilterChip,
2543
2773
  {
2544
2774
  label: text(area.label, lang),
@@ -2547,7 +2777,7 @@ function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }) {
2547
2777
  },
2548
2778
  area.id
2549
2779
  )) }) }),
2550
- /* @__PURE__ */ jsx18(DetailSection, { title: ui.priority, children: /* @__PURE__ */ jsx18("div", { className: "pt-panel-row", children: LEVELS.map((level) => /* @__PURE__ */ jsx18(
2780
+ /* @__PURE__ */ jsx19(DetailSection, { title: ui.priority, children: /* @__PURE__ */ jsx19("div", { className: "pt-panel-row", children: LEVELS.map((level) => /* @__PURE__ */ jsx19(
2551
2781
  FilterChip,
2552
2782
  {
2553
2783
  label: levelLabel[level],
@@ -2556,7 +2786,7 @@ function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }) {
2556
2786
  },
2557
2787
  level
2558
2788
  )) }) }),
2559
- /* @__PURE__ */ jsx18(DetailSection, { title: ui.risk, subtitle: ui.riskHint, children: /* @__PURE__ */ jsx18("div", { className: "pt-panel-row", children: LEVELS.map((level) => /* @__PURE__ */ jsx18(
2789
+ /* @__PURE__ */ jsx19(DetailSection, { title: ui.risk, subtitle: ui.riskHint, children: /* @__PURE__ */ jsx19("div", { className: "pt-panel-row", children: LEVELS.map((level) => /* @__PURE__ */ jsx19(
2560
2790
  FilterChip,
2561
2791
  {
2562
2792
  label: levelLabel[level],
@@ -2565,7 +2795,7 @@ function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }) {
2565
2795
  },
2566
2796
  level
2567
2797
  )) }) }),
2568
- /* @__PURE__ */ jsx18(DetailSection, { title: ui.dependsOn, children: /* @__PURE__ */ jsx18("div", { className: "pt-panel-row", children: OWNERS.map((owner) => /* @__PURE__ */ jsx18(
2798
+ /* @__PURE__ */ jsx19(DetailSection, { title: ui.dependsOn, children: /* @__PURE__ */ jsx19("div", { className: "pt-panel-row", children: OWNERS.map((owner) => /* @__PURE__ */ jsx19(
2569
2799
  FilterChip,
2570
2800
  {
2571
2801
  label: ownerLabel[owner],
@@ -2574,14 +2804,14 @@ function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }) {
2574
2804
  },
2575
2805
  owner
2576
2806
  )) }) }),
2577
- /* @__PURE__ */ jsx18(DetailSection, { title: ui.orderTitle, children: /* @__PURE__ */ jsxs16("div", { className: "pt-panel-row", children: [
2578
- /* @__PURE__ */ jsx18(FilterChip, { label: `\u26A1 ${ui.orderOn}`, active: card.order, onClick: () => patch({ order: true }) }),
2579
- /* @__PURE__ */ jsx18(FilterChip, { label: ui.orderOff, active: !card.order, onClick: () => patch({ order: false }) })
2807
+ /* @__PURE__ */ jsx19(DetailSection, { title: ui.orderTitle, children: /* @__PURE__ */ jsxs17("div", { className: "pt-panel-row", children: [
2808
+ /* @__PURE__ */ jsx19(FilterChip, { label: `\u26A1 ${ui.orderOn}`, active: card.order, onClick: () => patch({ order: true }) }),
2809
+ /* @__PURE__ */ jsx19(FilterChip, { label: ui.orderOff, active: !card.order, onClick: () => patch({ order: false }) })
2580
2810
  ] }) }),
2581
- /* @__PURE__ */ jsxs16(DetailSection, { title: ui.intentTitle, subtitle: ui.intentHint, children: [
2582
- /* @__PURE__ */ jsxs16("div", { className: "pt-panel-row", children: [
2583
- /* @__PURE__ */ jsx18(FilterChip, { label: ui.intentNone, active: card.intent === null, onClick: () => patch({ intent: null }) }),
2584
- INTENTS.map((intent) => /* @__PURE__ */ jsx18(
2811
+ /* @__PURE__ */ jsxs17(DetailSection, { title: ui.intentTitle, subtitle: ui.intentHint, children: [
2812
+ /* @__PURE__ */ jsxs17("div", { className: "pt-panel-row", children: [
2813
+ /* @__PURE__ */ jsx19(FilterChip, { label: ui.intentNone, active: card.intent === null, onClick: () => patch({ intent: null }) }),
2814
+ INTENTS.map((intent) => /* @__PURE__ */ jsx19(
2585
2815
  FilterChip,
2586
2816
  {
2587
2817
  label: INTENT_COPY[intent].label[lang],
@@ -2591,12 +2821,12 @@ function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }) {
2591
2821
  intent
2592
2822
  ))
2593
2823
  ] }),
2594
- card.intent && /* @__PURE__ */ jsx18("p", { className: "pt-panel-text pt-meaning", children: INTENT_COPY[card.intent].meaning[lang] })
2824
+ card.intent && /* @__PURE__ */ jsx19("p", { className: "pt-panel-text pt-meaning", children: INTENT_COPY[card.intent].meaning[lang] })
2595
2825
  ] }),
2596
- /* @__PURE__ */ jsxs16(DetailSection, { title: ui.checklist, children: [
2597
- card.checks.length > 0 && /* @__PURE__ */ jsx18("ul", { className: "pt-checks", children: card.checks.map((check) => /* @__PURE__ */ jsxs16("li", { children: [
2598
- /* @__PURE__ */ jsxs16("label", { children: [
2599
- /* @__PURE__ */ jsx18(
2826
+ /* @__PURE__ */ jsxs17(DetailSection, { title: ui.checklist, children: [
2827
+ card.checks.length > 0 && /* @__PURE__ */ jsx19("ul", { className: "pt-checks", children: card.checks.map((check) => /* @__PURE__ */ jsxs17("li", { children: [
2828
+ /* @__PURE__ */ jsxs17("label", { children: [
2829
+ /* @__PURE__ */ jsx19(
2600
2830
  "input",
2601
2831
  {
2602
2832
  type: "checkbox",
@@ -2608,9 +2838,9 @@ function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }) {
2608
2838
  })
2609
2839
  }
2610
2840
  ),
2611
- /* @__PURE__ */ jsx18("span", { className: check.done ? "is-done" : void 0, children: text(check.text, lang) })
2841
+ /* @__PURE__ */ jsx19("span", { className: check.done ? "is-done" : void 0, children: text(check.text, lang) })
2612
2842
  ] }),
2613
- /* @__PURE__ */ jsx18(
2843
+ /* @__PURE__ */ jsx19(
2614
2844
  "button",
2615
2845
  {
2616
2846
  type: "button",
@@ -2621,8 +2851,8 @@ function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }) {
2621
2851
  }
2622
2852
  )
2623
2853
  ] }, check.id)) }),
2624
- /* @__PURE__ */ jsxs16("div", { className: "pt-compose", children: [
2625
- /* @__PURE__ */ jsx18(
2854
+ /* @__PURE__ */ jsxs17("div", { className: "pt-compose", children: [
2855
+ /* @__PURE__ */ jsx19(
2626
2856
  "input",
2627
2857
  {
2628
2858
  className: "pt-input",
@@ -2637,19 +2867,19 @@ function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }) {
2637
2867
  }
2638
2868
  }
2639
2869
  ),
2640
- /* @__PURE__ */ jsx18("button", { type: "button", className: "pt-btn pt-btn--sm pt-btn--primary", onClick: addStep, children: ui.addStep })
2870
+ /* @__PURE__ */ jsx19("button", { type: "button", className: "pt-btn pt-btn--sm pt-btn--primary", onClick: addStep, children: ui.addStep })
2641
2871
  ] })
2642
2872
  ] }),
2643
- /* @__PURE__ */ jsxs16(DetailSection, { title: ui.notes, children: [
2644
- card.notes.map((entry) => /* @__PURE__ */ jsxs16("div", { className: "pt-note", children: [
2645
- /* @__PURE__ */ jsxs16("p", { className: "pt-note__meta", children: [
2873
+ /* @__PURE__ */ jsxs17(DetailSection, { title: ui.notes, children: [
2874
+ card.notes.map((entry) => /* @__PURE__ */ jsxs17("div", { className: "pt-note", children: [
2875
+ /* @__PURE__ */ jsxs17("p", { className: "pt-note__meta", children: [
2646
2876
  entry.by === "claude" ? "Claude" : ui.ownerYou,
2647
2877
  " \xB7 ",
2648
2878
  entry.date
2649
2879
  ] }),
2650
- /* @__PURE__ */ jsx18("p", { className: "pt-panel-text", children: text(entry.text, lang) })
2880
+ /* @__PURE__ */ jsx19("p", { className: "pt-panel-text", children: text(entry.text, lang) })
2651
2881
  ] }, entry.id)),
2652
- /* @__PURE__ */ jsx18(
2882
+ /* @__PURE__ */ jsx19(
2653
2883
  "textarea",
2654
2884
  {
2655
2885
  className: "pt-textarea",
@@ -2659,10 +2889,10 @@ function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }) {
2659
2889
  onChange: (event) => setNote(event.target.value)
2660
2890
  }
2661
2891
  ),
2662
- /* @__PURE__ */ jsx18("button", { type: "button", className: "pt-btn pt-btn--sm pt-btn--primary", onClick: addNote, children: ui.leaveNote })
2892
+ /* @__PURE__ */ jsx19("button", { type: "button", className: "pt-btn pt-btn--sm pt-btn--primary", onClick: addNote, children: ui.leaveNote })
2663
2893
  ] }),
2664
- /* @__PURE__ */ jsxs16(DetailSection, { title: ui.columnTitle, children: [
2665
- /* @__PURE__ */ jsx18("div", { className: "pt-panel-row", children: state.columns.map((column) => /* @__PURE__ */ jsx18(
2894
+ /* @__PURE__ */ jsxs17(DetailSection, { title: ui.columnTitle, children: [
2895
+ /* @__PURE__ */ jsx19("div", { className: "pt-panel-row", children: state.columns.map((column) => /* @__PURE__ */ jsx19(
2666
2896
  FilterChip,
2667
2897
  {
2668
2898
  label: text(column.title, lang),
@@ -2673,16 +2903,16 @@ function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }) {
2673
2903
  },
2674
2904
  column.id
2675
2905
  )) }),
2676
- (card.startedAt || card.completedAt) && /* @__PURE__ */ jsxs16("p", { className: "pt-panel-text pt-stamps", children: [
2906
+ (card.startedAt || card.completedAt) && /* @__PURE__ */ jsxs17("p", { className: "pt-panel-text pt-stamps", children: [
2677
2907
  card.startedAt && `${ui.started}: ${card.startedAt}`,
2678
2908
  card.startedAt && card.completedAt && " \xB7 ",
2679
2909
  card.completedAt && `${ui.completed}: ${card.completedAt}`
2680
2910
  ] }),
2681
- claimedWithoutStarting(card) && /* @__PURE__ */ jsx18("p", { className: "pt-warn", children: ui.neverStarted })
2911
+ claimedWithoutStarting(card) && /* @__PURE__ */ jsx19("p", { className: "pt-warn", children: ui.neverStarted })
2682
2912
  ] }),
2683
- /* @__PURE__ */ jsxs16("div", { className: "pt-sheet-actions", children: [
2684
- /* @__PURE__ */ jsx18("button", { type: "button", className: "pt-btn pt-btn--sm", onClick: onClose, children: ui.close }),
2685
- /* @__PURE__ */ jsx18("button", { type: "button", className: "pt-btn pt-btn--sm pt-danger", onClick: () => onDelete(card.id), children: ui.deleteCard })
2913
+ /* @__PURE__ */ jsxs17("div", { className: "pt-sheet-actions", children: [
2914
+ /* @__PURE__ */ jsx19("button", { type: "button", className: "pt-btn pt-btn--sm", onClick: onClose, children: ui.close }),
2915
+ /* @__PURE__ */ jsx19("button", { type: "button", className: "pt-btn pt-btn--sm pt-danger", onClick: () => onDelete(card.id), children: ui.deleteCard })
2686
2916
  ] })
2687
2917
  ] });
2688
2918
  }
@@ -2706,10 +2936,45 @@ function applyMove(cards, move, visible) {
2706
2936
  const at = rest.findIndex((card) => card.id === anchor.id);
2707
2937
  return [...rest.slice(0, at), moved, ...rest.slice(at)];
2708
2938
  }
2939
+ function resolveTheme(saved, stored, themes, hasImported, fallback) {
2940
+ for (const name of [saved, stored]) {
2941
+ if (name === "imported" && hasImported) return "imported";
2942
+ if (name && name in themes) return name;
2943
+ }
2944
+ return fallback ?? Object.keys(themes)[0];
2945
+ }
2709
2946
 
2710
2947
  // src/panel/PanelApp.tsx
2711
- import { Fragment as Fragment5, jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
2948
+ import { Fragment as Fragment5, jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
2712
2949
  var IMPORTED = "imported";
2950
+ var WIZARD_KEY = "paneltir:setup-done";
2951
+ var THEME_KEY = "paneltir:theme";
2952
+ function readStoredTheme() {
2953
+ try {
2954
+ return window.localStorage.getItem(THEME_KEY);
2955
+ } catch {
2956
+ return null;
2957
+ }
2958
+ }
2959
+ function storeTheme(name) {
2960
+ try {
2961
+ window.localStorage.setItem(THEME_KEY, name);
2962
+ } catch {
2963
+ }
2964
+ }
2965
+ function wizardClosed() {
2966
+ try {
2967
+ return window.localStorage.getItem(WIZARD_KEY) === "closed";
2968
+ } catch {
2969
+ return false;
2970
+ }
2971
+ }
2972
+ function closeWizard() {
2973
+ try {
2974
+ window.localStorage.setItem(WIZARD_KEY, "closed");
2975
+ } catch {
2976
+ }
2977
+ }
2713
2978
  function parseJson(body) {
2714
2979
  try {
2715
2980
  const parsed = JSON.parse(body);
@@ -2731,7 +2996,9 @@ var PRIORITY_TONE = {
2731
2996
  };
2732
2997
  function PanelApp({
2733
2998
  state: initialState,
2734
- themes = PRESET_PANEL_THEMES,
2999
+ themes: exactThemes,
3000
+ extraThemes,
3001
+ gate,
2735
3002
  defaultTheme,
2736
3003
  brand,
2737
3004
  decoration,
@@ -2748,35 +3015,42 @@ function PanelApp({
2748
3015
  marketplaceReport,
2749
3016
  fingerprint
2750
3017
  }) {
2751
- const [themeName, setThemeName] = useState9(() => {
2752
- const saved = initialState.preferences?.theme;
2753
- if (saved === IMPORTED && initialState.importedTheme) return IMPORTED;
2754
- return saved && saved in themes ? saved : defaultTheme ?? Object.keys(themes)[0];
2755
- });
2756
- const [lang, setLang] = useState9(
3018
+ const themes = useMemo5(() => offeredThemes(exactThemes, extraThemes), [exactThemes, extraThemes]);
3019
+ const gateReading = useMemo5(() => gateStatus(gate, paneltirBuild), [gate]);
3020
+ const [themeName, setThemeName] = useState10(
3021
+ () => resolveTheme(
3022
+ initialState.preferences?.theme,
3023
+ readStoredTheme(),
3024
+ themes,
3025
+ Boolean(initialState.importedTheme),
3026
+ defaultTheme
3027
+ )
3028
+ );
3029
+ const [lang, setLang] = useState10(
2757
3030
  () => initialState.preferences?.lang ?? (showLanguage ? readStoredLang() : "en")
2758
3031
  );
2759
- const [state, setState] = useState9(initialState);
2760
- const [filter, setFilter] = useState9("all");
2761
- const [openCardId, setOpenCardId] = useState9(null);
2762
- const [settingsOpen, setSettingsOpen] = useState9(false);
2763
- const [update, setUpdate] = useState9(null);
2764
- const [helpOpen, setHelpOpen] = useState9(false);
2765
- const [setup, setSetup] = useState9(null);
2766
- const [signOut, setSignOut] = useState9("idle");
2767
- const [view, setView] = useState9("board");
2768
- const [market, setMarket] = useState9(marketplaceReport ?? null);
2769
- const [marketLoading, setMarketLoading] = useState9(false);
2770
- const [marketFailure, setMarketFailure] = useState9(null);
2771
- const [marketAsked, setMarketAsked] = useState9(false);
2772
- const [noticeVisible, setNoticeVisible] = useState9(Boolean(initialState.notice));
2773
- const [savedSnapshot, setSavedSnapshot] = useState9(() => JSON.stringify(initialState));
2774
- const [save, setSave] = useState9({ status: "idle" });
3032
+ const [state, setState] = useState10(initialState);
3033
+ const [filter, setFilter] = useState10("all");
3034
+ const [openCardId, setOpenCardId] = useState10(null);
3035
+ const [settingsOpen, setSettingsOpen] = useState10(false);
3036
+ const [update, setUpdate] = useState10(null);
3037
+ const [releaseOpen, setReleaseOpen] = useState10(false);
3038
+ const [helpOpen, setHelpOpen] = useState10(false);
3039
+ const [wizardOpen, setWizardOpen] = useState10(false);
3040
+ const [setup, setSetup] = useState10(null);
3041
+ const [signOut, setSignOut] = useState10("idle");
3042
+ const [view, setView] = useState10("board");
3043
+ const [market, setMarket] = useState10(marketplaceReport ?? null);
3044
+ const [marketLoading, setMarketLoading] = useState10(false);
3045
+ const [marketFailure, setMarketFailure] = useState10(null);
3046
+ const [marketAsked, setMarketAsked] = useState10(false);
3047
+ const [noticeVisible, setNoticeVisible] = useState10(Boolean(initialState.notice));
3048
+ const [savedSnapshot, setSavedSnapshot] = useState10(() => JSON.stringify(initialState));
3049
+ const [save, setSave] = useState10({ status: "idle" });
2775
3050
  const imported = themeName === IMPORTED ? state.importedTheme : void 0;
2776
- const preset = themeName === IMPORTED ? "nightCity" : themeName;
2777
- const chosen = themes[preset] ?? Object.values(themes)[0];
3051
+ const chosen = themes[themeName] ?? Object.values(themes)[0];
2778
3052
  const theme = imported?.tokens ?? chosen.tokens;
2779
- const form = imported?.form ?? chosen.form;
3053
+ const form = imported?.form ?? (imported ? THEME_FORMS.panel : chosen.form);
2780
3054
  const ui = UI[lang];
2781
3055
  const t = useCallback5((value) => text(value, lang), [lang]);
2782
3056
  const dirty = JSON.stringify(state) !== savedSnapshot;
@@ -2800,11 +3074,11 @@ function PanelApp({
2800
3074
  status: state_("GH_TOKEN"),
2801
3075
  variable: "GH_TOKEN",
2802
3076
  enables: ui.needTokenEnables,
2803
- fix: /* @__PURE__ */ jsxs17("ol", { children: [
2804
- /* @__PURE__ */ jsx19("li", { children: ui.fixTokenCreate }),
2805
- /* @__PURE__ */ jsx19("li", { children: ui.fixTokenScope }),
2806
- /* @__PURE__ */ jsx19("li", { children: ui.fixTokenPaste }),
2807
- /* @__PURE__ */ jsx19("li", { children: ui.fixTokenRedeploy })
3077
+ fix: /* @__PURE__ */ jsxs18("ol", { children: [
3078
+ /* @__PURE__ */ jsx20("li", { children: ui.fixTokenCreate }),
3079
+ /* @__PURE__ */ jsx20("li", { children: ui.fixTokenScope }),
3080
+ /* @__PURE__ */ jsx20("li", { children: ui.fixTokenPaste }),
3081
+ /* @__PURE__ */ jsx20("li", { children: ui.fixTokenRedeploy })
2808
3082
  ] })
2809
3083
  },
2810
3084
  {
@@ -2813,10 +3087,40 @@ function PanelApp({
2813
3087
  status: state_("PANEL_REPO"),
2814
3088
  variable: "PANEL_REPO",
2815
3089
  enables: ui.needRepoEnables,
2816
- fix: /* @__PURE__ */ jsx19("p", { children: ui.fixRepo })
2817
- }
3090
+ fix: /* @__PURE__ */ jsx20("p", { children: ui.fixRepo })
3091
+ },
3092
+ // The gate is the only requirement here that is not an environment
3093
+ // variable: it is files this project owns, and the only one whose
3094
+ // failure is silent. A stale `api/panel-state.ts` does not read as
3095
+ // missing configuration — it reads as the panel being broken, which is
3096
+ // how the HTTP 500 cost a week.
3097
+ //
3098
+ // Drawn only when a stamp was passed. The kit does not invent a
3099
+ // requirement out of the absence of a prop: this project's own panel has
3100
+ // no copied gate — `template/` is the original, held honest by
3101
+ // `test:auth` — so a row here would invite wiring something that cannot
3102
+ // exist. A caller who passes nothing still has `paneltir doctor`, which
3103
+ // is what the skill file sends their Claude to.
3104
+ //
3105
+ // Passed but unreadable is a different thing and *is* reported, as
3106
+ // `unknown` rather than `missing`: telling somebody their gate is old on
3107
+ // the strength of a file we failed to parse is the mistake
3108
+ // `SetupWizard` already refuses to make.
3109
+ ...gate === void 0 ? [] : [{
3110
+ id: "gate",
3111
+ label: ui.needGate,
3112
+ status: gateReading.verdict === "current" ? "ok" : gateReading.verdict === "behind" ? "missing" : "unknown",
3113
+ enables: ui.needGateEnables,
3114
+ fix: /* @__PURE__ */ jsxs18(Fragment5, { children: [
3115
+ /* @__PURE__ */ jsxs18("p", { children: [
3116
+ ui.fixGate,
3117
+ gateReading.copiedFrom ? ` (v${gateReading.copiedFrom} \u2192 v${gateReading.installed})` : ""
3118
+ ] }),
3119
+ /* @__PURE__ */ jsx20("pre", { className: "pt-copy__pre", children: "npx paneltir doctor" })
3120
+ ] })
3121
+ }]
2818
3122
  ];
2819
- }, [setup, ui]);
3123
+ }, [setup, ui, gate, gateReading]);
2820
3124
  useEffect9(() => {
2821
3125
  document.documentElement.lang = lang;
2822
3126
  if (showLanguage) storeLang(lang);
@@ -2974,6 +3278,29 @@ function PanelApp({
2974
3278
  setState((current) => ({ ...current, updatedAt: today(), cards: [...current.cards, card] }));
2975
3279
  setOpenCardId(id);
2976
3280
  }, [update, state.cards, state.areas, state.preferences?.updateAsOrder]);
3281
+ const requestReport = useCallback5(
3282
+ (section) => {
3283
+ const id = `report-${section}-${today()}`;
3284
+ if (state.cards.some((card2) => card2.id === id)) {
3285
+ setOpenCardId(id);
3286
+ return;
3287
+ }
3288
+ const card = {
3289
+ ...emptyCard("next", state.areas[0]?.id ?? "general"),
3290
+ id,
3291
+ title: { en: UI.en.analysisRedoTitle[section], es: UI.es.analysisRedoTitle[section] },
3292
+ body: { en: UI.en.analysisRedoBody[section], es: UI.es.analysisRedoBody[section] },
3293
+ priority: "medium",
3294
+ risk: "low",
3295
+ owner: "claude",
3296
+ order: true,
3297
+ intent: "do"
3298
+ };
3299
+ setState((current) => ({ ...current, updatedAt: today(), cards: [...current.cards, card] }));
3300
+ setOpenCardId(id);
3301
+ },
3302
+ [state.cards, state.areas]
3303
+ );
2977
3304
  const moveCard = useCallback5(
2978
3305
  (move) => {
2979
3306
  setState((current) => {
@@ -3009,6 +3336,7 @@ function PanelApp({
3009
3336
  const chooseTheme = useCallback5(
3010
3337
  (name) => {
3011
3338
  setThemeName(name);
3339
+ storeTheme(name);
3012
3340
  setPreference("theme", name);
3013
3341
  },
3014
3342
  [setPreference]
@@ -3097,24 +3425,45 @@ function PanelApp({
3097
3425
  if (!checkForUpdates || !fingerprint?.version) return;
3098
3426
  let cancelled = false;
3099
3427
  void checkForUpdate(fingerprint.version).then((status2) => {
3100
- if (!cancelled) setUpdate(status2);
3428
+ if (cancelled) return;
3429
+ setUpdate(status2);
3430
+ if (!status2?.behind) return;
3431
+ try {
3432
+ const key = "pt_release_seen";
3433
+ if (window.localStorage.getItem(key) !== status2.latest) {
3434
+ window.localStorage.setItem(key, status2.latest);
3435
+ setReleaseOpen(true);
3436
+ }
3437
+ } catch {
3438
+ setReleaseOpen(true);
3439
+ }
3101
3440
  });
3102
3441
  return () => {
3103
3442
  cancelled = true;
3104
3443
  };
3105
3444
  }, [checkForUpdates, fingerprint?.version]);
3445
+ const readSetup = useCallback5(async () => {
3446
+ if (!saveEndpoint) return;
3447
+ try {
3448
+ const response = await fetch(saveEndpoint, { headers: { accept: "application/json" } });
3449
+ if (!response.ok) throw new Error(String(response.status));
3450
+ setSetup(await response.json());
3451
+ } catch {
3452
+ setSetup({ ready: false, missing: [], repo: null, branch: "", file: "", unknown: true });
3453
+ }
3454
+ }, [saveEndpoint]);
3106
3455
  useEffect9(() => {
3107
3456
  if (!helpOpen || !saveEndpoint || setup) return;
3108
- let cancelled = false;
3109
- fetch(saveEndpoint, { headers: { accept: "application/json" } }).then((response) => response.ok ? response.json() : Promise.reject(new Error(String(response.status)))).then((body) => {
3110
- if (!cancelled) setSetup(body);
3111
- }).catch(() => {
3112
- if (!cancelled) setSetup({ ready: false, missing: [], repo: null, branch: "", file: "", unknown: true });
3113
- });
3114
- return () => {
3115
- cancelled = true;
3116
- };
3117
- }, [helpOpen, saveEndpoint, setup]);
3457
+ void readSetup();
3458
+ }, [helpOpen, saveEndpoint, setup, readSetup]);
3459
+ useEffect9(() => {
3460
+ if (!saveEndpoint || setup || !isFirstRun(initialState)) return;
3461
+ void readSetup();
3462
+ }, [saveEndpoint, setup, initialState, readSetup]);
3463
+ useEffect9(() => {
3464
+ if (!setup || setup.ready || !isFirstRun(initialState) || wizardClosed()) return;
3465
+ setWizardOpen(true);
3466
+ }, [setup, initialState]);
3118
3467
  const endSession = useCallback5(async () => {
3119
3468
  setSignOut("working");
3120
3469
  try {
@@ -3142,7 +3491,8 @@ function PanelApp({
3142
3491
  const conflict = response.status === 409;
3143
3492
  throw Object.assign(new Error(saveError(response.status, data, body)), { conflict });
3144
3493
  }
3145
- setSavedSnapshot(JSON.stringify(state));
3494
+ setSavedSnapshot(JSON.stringify(next));
3495
+ setState(next);
3146
3496
  setSave({
3147
3497
  status: "saved",
3148
3498
  at: (/* @__PURE__ */ new Date()).toLocaleTimeString(lang === "es" ? "es-ES" : "en-GB", {
@@ -3177,21 +3527,21 @@ function PanelApp({
3177
3527
  state.updatedAt,
3178
3528
  save.status === "saved" ? ui.savedAt(save.at) : dirty ? ui.unsaved : ""
3179
3529
  ].filter(Boolean).join(" \xB7 ");
3180
- return /* @__PURE__ */ jsxs17(DashboardThemeProvider, { tokens: theme, form, className, children: [
3181
- decoration,
3182
- /* @__PURE__ */ jsx19(
3530
+ return /* @__PURE__ */ jsxs18(DashboardThemeProvider, { tokens: theme, form, className, children: [
3531
+ typeof decoration === "function" ? decoration(themeName) : decoration,
3532
+ /* @__PURE__ */ jsx20(
3183
3533
  DashboardHeader,
3184
3534
  {
3185
3535
  wordmark: (
3186
3536
  /* A board belongs to a project, so its name is what goes here. A
3187
3537
  caller with a mark of its own passes `brand`; drawing one here
3188
3538
  would be the kit deciding what somebody else's panel is called. */
3189
- brand ?? /* @__PURE__ */ jsx19("span", { className: "pt-panel-brand", children: state.project })
3539
+ brand ?? /* @__PURE__ */ jsx20("span", { className: "pt-panel-brand", children: state.project })
3190
3540
  ),
3191
3541
  status,
3192
- controls: /* @__PURE__ */ jsxs17(Fragment5, { children: [
3193
- (initialState.analysis || hasMarketplace || showHistory) && /* @__PURE__ */ jsxs17("span", { className: "pt-views", children: [
3194
- /* @__PURE__ */ jsx19(
3542
+ controls: /* @__PURE__ */ jsxs18(Fragment5, { children: [
3543
+ (initialState.analysis || hasMarketplace || showHistory) && /* @__PURE__ */ jsxs18("span", { className: "pt-views", children: [
3544
+ /* @__PURE__ */ jsx20(
3195
3545
  "button",
3196
3546
  {
3197
3547
  type: "button",
@@ -3201,7 +3551,7 @@ function PanelApp({
3201
3551
  children: ui.board
3202
3552
  }
3203
3553
  ),
3204
- initialState.analysis && /* @__PURE__ */ jsx19(
3554
+ initialState.analysis && /* @__PURE__ */ jsx20(
3205
3555
  "button",
3206
3556
  {
3207
3557
  type: "button",
@@ -3211,7 +3561,7 @@ function PanelApp({
3211
3561
  children: ui.analysis
3212
3562
  }
3213
3563
  ),
3214
- hasMarketplace && /* @__PURE__ */ jsx19(
3564
+ hasMarketplace && /* @__PURE__ */ jsx20(
3215
3565
  "button",
3216
3566
  {
3217
3567
  type: "button",
@@ -3221,7 +3571,7 @@ function PanelApp({
3221
3571
  children: ui.marketplace
3222
3572
  }
3223
3573
  ),
3224
- showHistory && /* @__PURE__ */ jsx19(
3574
+ showHistory && /* @__PURE__ */ jsx20(
3225
3575
  "button",
3226
3576
  {
3227
3577
  type: "button",
@@ -3232,7 +3582,7 @@ function PanelApp({
3232
3582
  }
3233
3583
  )
3234
3584
  ] }),
3235
- showLanguage && LANGS.map((code) => /* @__PURE__ */ jsx19(
3585
+ showLanguage && LANGS.map((code) => /* @__PURE__ */ jsx20(
3236
3586
  "button",
3237
3587
  {
3238
3588
  type: "button",
@@ -3243,7 +3593,7 @@ function PanelApp({
3243
3593
  },
3244
3594
  code
3245
3595
  )),
3246
- /* @__PURE__ */ jsx19(
3596
+ /* @__PURE__ */ jsx20(
3247
3597
  NotificationBell,
3248
3598
  {
3249
3599
  notifications,
@@ -3257,8 +3607,8 @@ function PanelApp({
3257
3607
  }
3258
3608
  }
3259
3609
  ),
3260
- saveEndpoint && /* @__PURE__ */ jsx19("button", { type: "button", className: "pt-lang", onClick: () => setHelpOpen(true), children: ui.help }),
3261
- saveEndpoint && (dirty || save.status === "saving") && /* @__PURE__ */ jsx19(
3610
+ saveEndpoint && /* @__PURE__ */ jsx20("button", { type: "button", className: "pt-lang", onClick: () => setHelpOpen(true), children: ui.help }),
3611
+ saveEndpoint && (dirty || save.status === "saving") && /* @__PURE__ */ jsx20(
3262
3612
  "button",
3263
3613
  {
3264
3614
  type: "button",
@@ -3273,7 +3623,7 @@ function PanelApp({
3273
3623
  onLinkClick: () => setSettingsOpen(true)
3274
3624
  }
3275
3625
  ),
3276
- state.notice && /* @__PURE__ */ jsx19(
3626
+ state.notice && /* @__PURE__ */ jsx20(
3277
3627
  AlertBanner,
3278
3628
  {
3279
3629
  visible: noticeVisible,
@@ -3282,8 +3632,17 @@ function PanelApp({
3282
3632
  onAction: () => setNoticeVisible(false)
3283
3633
  }
3284
3634
  ),
3285
- save.status === "error" && /* @__PURE__ */ jsx19(AlertBanner, { visible: true, message: `${ui.saveFailed}: ${save.message}` }),
3286
- view === "board" && !saveEndpoint && /* @__PURE__ */ jsx19(
3635
+ save.status === "error" && /* @__PURE__ */ jsx20(AlertBanner, { visible: true, message: `${ui.saveFailed}: ${save.message}` }),
3636
+ saveEndpoint && setup && !setup.ready && !setup.unknown && !wizardOpen && /* @__PURE__ */ jsx20(
3637
+ AlertBanner,
3638
+ {
3639
+ visible: true,
3640
+ message: ui.wizardBanner,
3641
+ actionLabel: ui.wizardOpen,
3642
+ onAction: () => setWizardOpen(true)
3643
+ }
3644
+ ),
3645
+ view === "board" && !saveEndpoint && /* @__PURE__ */ jsx20(
3287
3646
  GuideTour,
3288
3647
  {
3289
3648
  dismissed: state.preferences?.guideDismissed,
@@ -3292,32 +3651,32 @@ function PanelApp({
3292
3651
  {
3293
3652
  id: "demo-welcome",
3294
3653
  title: ui.demoTourWelcomeTitle,
3295
- children: /* @__PURE__ */ jsx19("p", { children: ui.demoTourWelcomeBody }),
3654
+ children: /* @__PURE__ */ jsx20("p", { children: ui.demoTourWelcomeBody }),
3296
3655
  dismissLabel: ui.gotIt
3297
3656
  },
3298
3657
  {
3299
3658
  id: "demo-board",
3300
3659
  title: ui.demoTourBoardTitle,
3301
- children: /* @__PURE__ */ jsx19("p", { children: ui.demoTourBoardBody }),
3660
+ children: /* @__PURE__ */ jsx20("p", { children: ui.demoTourBoardBody }),
3302
3661
  dismissLabel: ui.gotIt
3303
3662
  },
3304
3663
  {
3305
3664
  id: "demo-theme",
3306
3665
  title: ui.demoTourThemeTitle,
3307
- children: /* @__PURE__ */ jsx19("p", { children: ui.demoTourThemeBody }),
3666
+ children: /* @__PURE__ */ jsx20("p", { children: ui.demoTourThemeBody }),
3308
3667
  dismissLabel: ui.gotIt,
3309
3668
  action: { label: ui.settings, onClick: () => setSettingsOpen(true) }
3310
3669
  },
3311
3670
  {
3312
3671
  id: "demo-keep",
3313
3672
  title: ui.demoTourKeepTitle,
3314
- children: /* @__PURE__ */ jsx19("p", { children: ui.demoTourKeepBody }),
3673
+ children: /* @__PURE__ */ jsx20("p", { children: ui.demoTourKeepBody }),
3315
3674
  dismissLabel: ui.gotIt
3316
3675
  }
3317
3676
  ]
3318
3677
  }
3319
3678
  ),
3320
- view === "board" && saveEndpoint && /* @__PURE__ */ jsx19(
3679
+ view === "board" && saveEndpoint && /* @__PURE__ */ jsx20(
3321
3680
  GuideTour,
3322
3681
  {
3323
3682
  dismissed: state.preferences?.guideDismissed,
@@ -3326,38 +3685,38 @@ function PanelApp({
3326
3685
  {
3327
3686
  id: "welcome",
3328
3687
  title: ui.tourWelcomeTitle,
3329
- children: /* @__PURE__ */ jsx19("p", { children: ui.tourWelcomeBody }),
3688
+ children: /* @__PURE__ */ jsx20("p", { children: ui.tourWelcomeBody }),
3330
3689
  dismissLabel: ui.gotIt
3331
3690
  },
3332
3691
  {
3333
3692
  id: "board",
3334
3693
  title: ui.tourBoardTitle,
3335
- children: /* @__PURE__ */ jsx19("p", { children: ui.tourBoardBody }),
3694
+ children: /* @__PURE__ */ jsx20("p", { children: ui.tourBoardBody }),
3336
3695
  dismissLabel: ui.gotIt
3337
3696
  },
3338
3697
  {
3339
3698
  id: "orders",
3340
3699
  title: ui.tourOrdersTitle,
3341
- children: /* @__PURE__ */ jsx19("p", { children: ui.tourOrdersBody }),
3700
+ children: /* @__PURE__ */ jsx20("p", { children: ui.tourOrdersBody }),
3342
3701
  dismissLabel: ui.gotIt
3343
3702
  },
3344
3703
  {
3345
3704
  id: "save",
3346
3705
  title: ui.tourSaveTitle,
3347
- children: /* @__PURE__ */ jsx19("p", { children: ui.tourSaveBody }),
3706
+ children: /* @__PURE__ */ jsx20("p", { children: ui.tourSaveBody }),
3348
3707
  dismissLabel: ui.gotIt
3349
3708
  },
3350
3709
  {
3351
3710
  id: "theme",
3352
3711
  title: ui.tourThemeTitle,
3353
- children: /* @__PURE__ */ jsx19("p", { children: ui.tourThemeBody }),
3712
+ children: /* @__PURE__ */ jsx20("p", { children: ui.tourThemeBody }),
3354
3713
  dismissLabel: ui.gotIt,
3355
3714
  action: { label: ui.settings, onClick: () => setSettingsOpen(true) }
3356
3715
  }
3357
3716
  ]
3358
3717
  }
3359
3718
  ),
3360
- view === "marketplace" && hasMarketplace && /* @__PURE__ */ jsx19(
3719
+ view === "marketplace" && hasMarketplace && /* @__PURE__ */ jsx20(
3361
3720
  MarketplaceView,
3362
3721
  {
3363
3722
  report: market,
@@ -3368,9 +3727,10 @@ function PanelApp({
3368
3727
  onRefresh: marketplaceEndpoint ? () => loadMarketplace(true) : void 0
3369
3728
  }
3370
3729
  ),
3371
- view === "analysis" && state.analysis && /* @__PURE__ */ jsx19(
3730
+ view === "analysis" && state.analysis && /* @__PURE__ */ jsx20(
3372
3731
  AnalysisView,
3373
3732
  {
3733
+ onRequestReport: saveEndpoint ? requestReport : void 0,
3374
3734
  analysis: state.analysis,
3375
3735
  cards: state.cards,
3376
3736
  columns: state.columns,
@@ -3383,20 +3743,20 @@ function PanelApp({
3383
3743
  onOpenCard: setOpenCardId
3384
3744
  }
3385
3745
  ),
3386
- view === "board" && /* @__PURE__ */ jsxs17(Fragment5, { children: [
3387
- /* @__PURE__ */ jsxs17("div", { className: "pt-panel-page", children: [
3388
- /* @__PURE__ */ jsxs17(StatTileGrid, { children: [
3389
- /* @__PURE__ */ jsx19(StatTile, { label: ui.statOpen, value: counts.open, isZero: counts.open === 0 }),
3390
- /* @__PURE__ */ jsx19(StatTile, { label: ui.statOrders, value: counts.orders, tone: "warning", isZero: counts.orders === 0 }),
3391
- /* @__PURE__ */ jsx19(StatTile, { label: ui.statYours, value: counts.yours, tone: "danger", isZero: counts.yours === 0 }),
3392
- /* @__PURE__ */ jsx19(StatTile, { label: ui.statDecisions, value: counts.decisions, tone: "warning", isZero: counts.decisions === 0 }),
3393
- /* @__PURE__ */ jsx19(StatTile, { label: ui.statHighRisk, value: counts.highRisk, tone: "danger", isZero: counts.highRisk === 0 }),
3394
- /* @__PURE__ */ jsx19(StatTile, { label: ui.statDone, value: counts.done, tone: "success", isZero: counts.done === 0 })
3746
+ view === "board" && /* @__PURE__ */ jsxs18(Fragment5, { children: [
3747
+ /* @__PURE__ */ jsxs18("div", { className: "pt-panel-page", children: [
3748
+ /* @__PURE__ */ jsxs18(StatTileGrid, { children: [
3749
+ /* @__PURE__ */ jsx20(StatTile, { label: ui.statOpen, value: counts.open, isZero: counts.open === 0 }),
3750
+ /* @__PURE__ */ jsx20(StatTile, { label: ui.statOrders, value: counts.orders, tone: "warning", isZero: counts.orders === 0 }),
3751
+ /* @__PURE__ */ jsx20(StatTile, { label: ui.statYours, value: counts.yours, tone: "danger", isZero: counts.yours === 0 }),
3752
+ /* @__PURE__ */ jsx20(StatTile, { label: ui.statDecisions, value: counts.decisions, tone: "warning", isZero: counts.decisions === 0 }),
3753
+ /* @__PURE__ */ jsx20(StatTile, { label: ui.statHighRisk, value: counts.highRisk, tone: "danger", isZero: counts.highRisk === 0 }),
3754
+ /* @__PURE__ */ jsx20(StatTile, { label: ui.statDone, value: counts.done, tone: "success", isZero: counts.done === 0 })
3395
3755
  ] }),
3396
- /* @__PURE__ */ jsx19(HealthPillRow, { children: state.health.map((pill) => /* @__PURE__ */ jsx19(HealthPill, { label: t(pill.label), value: t(pill.value), status: pill.status }, t(pill.label))) }),
3397
- /* @__PURE__ */ jsxs17(FilterChipRow, { children: [
3398
- /* @__PURE__ */ jsx19(FilterChip, { label: ui.all, count: state.cards.length, active: filter === "all", onClick: () => setFilter("all") }),
3399
- /* @__PURE__ */ jsx19(
3756
+ /* @__PURE__ */ jsx20(HealthPillRow, { children: state.health.map((pill) => /* @__PURE__ */ jsx20(HealthPill, { label: t(pill.label), value: t(pill.value), status: pill.status }, t(pill.label))) }),
3757
+ /* @__PURE__ */ jsxs18(FilterChipRow, { children: [
3758
+ /* @__PURE__ */ jsx20(FilterChip, { label: ui.all, count: state.cards.length, active: filter === "all", onClick: () => setFilter("all") }),
3759
+ /* @__PURE__ */ jsx20(
3400
3760
  FilterChip,
3401
3761
  {
3402
3762
  label: `\u26A1 ${ui.filterForClaude}`,
@@ -3405,7 +3765,7 @@ function PanelApp({
3405
3765
  onClick: () => setFilter("orders")
3406
3766
  }
3407
3767
  ),
3408
- /* @__PURE__ */ jsx19(
3768
+ /* @__PURE__ */ jsx20(
3409
3769
  FilterChip,
3410
3770
  {
3411
3771
  label: ui.filterYours,
@@ -3414,7 +3774,7 @@ function PanelApp({
3414
3774
  onClick: () => setFilter("yours")
3415
3775
  }
3416
3776
  ),
3417
- /* @__PURE__ */ jsx19(
3777
+ /* @__PURE__ */ jsx20(
3418
3778
  FilterChip,
3419
3779
  {
3420
3780
  label: ui.filterHighRisk,
@@ -3423,7 +3783,7 @@ function PanelApp({
3423
3783
  onClick: () => setFilter("risk")
3424
3784
  }
3425
3785
  ),
3426
- state.areas.map((area) => /* @__PURE__ */ jsx19(
3786
+ state.areas.map((area) => /* @__PURE__ */ jsx20(
3427
3787
  FilterChip,
3428
3788
  {
3429
3789
  label: t(area.label),
@@ -3435,13 +3795,13 @@ function PanelApp({
3435
3795
  ))
3436
3796
  ] })
3437
3797
  ] }),
3438
- /* @__PURE__ */ jsx19(
3798
+ /* @__PURE__ */ jsx20(
3439
3799
  Board,
3440
3800
  {
3441
3801
  columns: boardColumns,
3442
3802
  onMove: moveCard,
3443
3803
  onAddCard: addCard,
3444
- renderCard: (card, index, columnId) => /* @__PURE__ */ jsx19(
3804
+ renderCard: (card, index, columnId) => /* @__PURE__ */ jsx20(
3445
3805
  Card,
3446
3806
  {
3447
3807
  cardId: card.id,
@@ -3458,39 +3818,39 @@ function PanelApp({
3458
3818
  }
3459
3819
  ),
3460
3820
  extras,
3461
- capabilities && capabilities.length > 0 && /* @__PURE__ */ jsxs17("section", { className: "pt-panel-page pt-panel-section", id: "functions", children: [
3462
- /* @__PURE__ */ jsxs17("div", { children: [
3463
- /* @__PURE__ */ jsx19("p", { className: "pt-eyebrow", children: ui.functionsEyebrow }),
3464
- /* @__PURE__ */ jsx19("h2", { className: "pt-h2", children: ui.functionsTitle }),
3465
- /* @__PURE__ */ jsx19("p", { className: "pt-sub", children: ui.functionsIntro })
3821
+ capabilities && capabilities.length > 0 && /* @__PURE__ */ jsxs18("section", { className: "pt-panel-page pt-panel-section", id: "functions", children: [
3822
+ /* @__PURE__ */ jsxs18("div", { children: [
3823
+ /* @__PURE__ */ jsx20("p", { className: "pt-eyebrow", children: ui.functionsEyebrow }),
3824
+ /* @__PURE__ */ jsx20("h2", { className: "pt-h2", children: ui.functionsTitle }),
3825
+ /* @__PURE__ */ jsx20("p", { className: "pt-sub", children: ui.functionsIntro })
3466
3826
  ] }),
3467
- /* @__PURE__ */ jsx19("div", { className: "pt-cap-list", children: capabilities.map((capability) => /* @__PURE__ */ jsxs17("article", { className: "pt-cap pt-hud", children: [
3468
- /* @__PURE__ */ jsx19("h3", { className: "pt-cap__title", children: t(capability.title) }),
3469
- /* @__PURE__ */ jsx19("p", { className: "pt-cap__summary", children: t(capability.summary) }),
3470
- /* @__PURE__ */ jsx19("ul", { className: "pt-cap__list", children: capability.points.map((point) => /* @__PURE__ */ jsx19("li", { children: t(point) }, t(point))) }),
3471
- capability.code && /* @__PURE__ */ jsxs17("div", { className: "pt-cap__code", children: [
3472
- /* @__PURE__ */ jsx19("p", { className: "pt-cap__caption", children: t(capability.code.caption) }),
3473
- /* @__PURE__ */ jsx19("pre", { children: /* @__PURE__ */ jsx19("code", { children: capability.code.body }) })
3827
+ /* @__PURE__ */ jsx20("div", { className: "pt-cap-list", children: capabilities.map((capability) => /* @__PURE__ */ jsxs18("article", { className: "pt-cap pt-hud", children: [
3828
+ /* @__PURE__ */ jsx20("h3", { className: "pt-cap__title", children: t(capability.title) }),
3829
+ /* @__PURE__ */ jsx20("p", { className: "pt-cap__summary", children: t(capability.summary) }),
3830
+ /* @__PURE__ */ jsx20("ul", { className: "pt-cap__list", children: capability.points.map((point) => /* @__PURE__ */ jsx20("li", { children: t(point) }, t(point))) }),
3831
+ capability.code && /* @__PURE__ */ jsxs18("div", { className: "pt-cap__code", children: [
3832
+ /* @__PURE__ */ jsx20("p", { className: "pt-cap__caption", children: t(capability.code.caption) }),
3833
+ /* @__PURE__ */ jsx20("pre", { children: /* @__PURE__ */ jsx20("code", { children: capability.code.body }) })
3474
3834
  ] })
3475
3835
  ] }, capability.id)) })
3476
3836
  ] })
3477
3837
  ] }),
3478
- view === "history" && showHistory && /* @__PURE__ */ jsxs17("section", { className: "pt-panel-page pt-panel-section", id: "revisions", children: [
3479
- /* @__PURE__ */ jsxs17("div", { children: [
3480
- /* @__PURE__ */ jsx19("p", { className: "pt-eyebrow", children: ui.historyEyebrow }),
3481
- /* @__PURE__ */ jsx19("h2", { className: "pt-h2", children: ui.historyTitle }),
3482
- /* @__PURE__ */ jsx19("p", { className: "pt-sub", children: ui.historyIntro })
3838
+ view === "history" && showHistory && /* @__PURE__ */ jsxs18("section", { className: "pt-panel-page pt-panel-section", id: "revisions", children: [
3839
+ /* @__PURE__ */ jsxs18("div", { children: [
3840
+ /* @__PURE__ */ jsx20("p", { className: "pt-eyebrow", children: ui.historyEyebrow }),
3841
+ /* @__PURE__ */ jsx20("h2", { className: "pt-h2", children: ui.historyTitle }),
3842
+ /* @__PURE__ */ jsx20("p", { className: "pt-sub", children: ui.historyIntro })
3483
3843
  ] }),
3484
- state.runs.length === 0 ? /* @__PURE__ */ jsx19("p", { className: "pt-panel-text", children: ui.historyEmpty }) : /* @__PURE__ */ jsx19("ol", { className: "pt-runs", children: [...state.runs].reverse().map((run) => /* @__PURE__ */ jsxs17("li", { className: "pt-run pt-hud", children: [
3485
- /* @__PURE__ */ jsxs17("p", { className: "pt-run__meta", children: [
3844
+ state.runs.length === 0 ? /* @__PURE__ */ jsx20("p", { className: "pt-panel-text", children: ui.historyEmpty }) : /* @__PURE__ */ jsx20("ol", { className: "pt-runs", children: [...state.runs].reverse().map((run) => /* @__PURE__ */ jsxs18("li", { className: "pt-run pt-hud", children: [
3845
+ /* @__PURE__ */ jsxs18("p", { className: "pt-run__meta", children: [
3486
3846
  run.date,
3487
3847
  " \xB7 ",
3488
3848
  run.by === "claude" ? "Claude" : ui.ownerYou,
3489
3849
  run.fingerprint ? ` \xB7 ${run.fingerprint.replace("sha256:", "").slice(0, 12)}` : ""
3490
3850
  ] }),
3491
- /* @__PURE__ */ jsx19("p", { className: "pt-panel-text", children: t(run.summary) }),
3492
- run.cards.length > 0 && /* @__PURE__ */ jsxs17("p", { className: "pt-run__cards", children: [
3493
- /* @__PURE__ */ jsxs17("span", { children: [
3851
+ /* @__PURE__ */ jsx20("p", { className: "pt-panel-text", children: t(run.summary) }),
3852
+ run.cards.length > 0 && /* @__PURE__ */ jsxs18("p", { className: "pt-run__cards", children: [
3853
+ /* @__PURE__ */ jsxs18("span", { children: [
3494
3854
  ui.historyTouched,
3495
3855
  ":"
3496
3856
  ] }),
@@ -3502,7 +3862,7 @@ function PanelApp({
3502
3862
  ] })
3503
3863
  ] }, run.id)) })
3504
3864
  ] }),
3505
- /* @__PURE__ */ jsx19(
3865
+ /* @__PURE__ */ jsx20(
3506
3866
  CardSheet,
3507
3867
  {
3508
3868
  card: openCard,
@@ -3514,9 +3874,50 @@ function PanelApp({
3514
3874
  onClose: () => setOpenCardId(null)
3515
3875
  }
3516
3876
  ),
3517
- /* @__PURE__ */ jsxs17(DetailSheet, { open: helpOpen, onClose: () => setHelpOpen(false), ariaLabel: ui.helpTitle, children: [
3518
- /* @__PURE__ */ jsx19(DetailSection, { title: ui.helpTitle, children: !setup ? /* @__PURE__ */ jsx19("p", { className: "pt-panel-text", children: ui.setupChecking }) : /* @__PURE__ */ jsxs17(Fragment5, { children: [
3519
- /* @__PURE__ */ jsx19(
3877
+ /* @__PURE__ */ jsx20(
3878
+ DetailSheet,
3879
+ {
3880
+ open: wizardOpen,
3881
+ onClose: () => {
3882
+ closeWizard();
3883
+ setWizardOpen(false);
3884
+ },
3885
+ ariaLabel: ui.wizardTitle,
3886
+ children: /* @__PURE__ */ jsx20(
3887
+ SetupWizard,
3888
+ {
3889
+ requirements,
3890
+ onCheck: readSetup,
3891
+ onClose: () => {
3892
+ closeWizard();
3893
+ setWizardOpen(false);
3894
+ },
3895
+ labels: {
3896
+ title: ui.wizardTitle,
3897
+ progress: ui.wizardProgress,
3898
+ nowDo: ui.wizardNowDo,
3899
+ check: ui.wizardCheck,
3900
+ checking: ui.wizardChecking,
3901
+ stillMissing: ui.wizardStillMissing,
3902
+ cannotTell: ui.wizardCannotTell,
3903
+ doneTitle: ui.wizardDoneTitle,
3904
+ readyTitle: ui.wizardReadyTitle,
3905
+ readyBody: ui.wizardReadyBody,
3906
+ verify: ui.wizardVerify,
3907
+ close: ui.wizardClose,
3908
+ stuckTitle: ui.wizardStuckTitle,
3909
+ stuckBody: ui.wizardStuckBody,
3910
+ stuckPrompt: ui.wizardStuckPrompt,
3911
+ copy: ui.wizardCopy,
3912
+ copied: ui.wizardCopied
3913
+ }
3914
+ }
3915
+ )
3916
+ }
3917
+ ),
3918
+ /* @__PURE__ */ jsxs18(DetailSheet, { open: helpOpen, onClose: () => setHelpOpen(false), ariaLabel: ui.helpTitle, children: [
3919
+ /* @__PURE__ */ jsx20(DetailSection, { title: ui.helpTitle, children: !setup ? /* @__PURE__ */ jsx20("p", { className: "pt-panel-text", children: ui.setupChecking }) : /* @__PURE__ */ jsxs18(Fragment5, { children: [
3920
+ /* @__PURE__ */ jsx20(
3520
3921
  SetupGuide,
3521
3922
  {
3522
3923
  requirements,
@@ -3529,9 +3930,21 @@ function PanelApp({
3529
3930
  }
3530
3931
  }
3531
3932
  ),
3532
- setup.repo && /* @__PURE__ */ jsx19("p", { className: "pt-panel-text", style: { marginTop: 12 }, children: ui.setupWriteTarget(setup.repo, setup.branch, setup.file) })
3933
+ setup.repo && /* @__PURE__ */ jsx20("p", { className: "pt-panel-text", style: { marginTop: 12 }, children: ui.setupWriteTarget(setup.repo, setup.branch, setup.file) }),
3934
+ !setup.ready && /* @__PURE__ */ jsx20("div", { className: "pt-panel-row", style: { marginTop: 12 }, children: /* @__PURE__ */ jsx20(
3935
+ "button",
3936
+ {
3937
+ type: "button",
3938
+ className: "pt-btn pt-btn--sm pt-btn--primary",
3939
+ onClick: () => {
3940
+ setHelpOpen(false);
3941
+ setWizardOpen(true);
3942
+ },
3943
+ children: ui.wizardOpen
3944
+ }
3945
+ ) })
3533
3946
  ] }) }),
3534
- /* @__PURE__ */ jsx19(DetailSection, { title: ui.guideSection, children: /* @__PURE__ */ jsx19("div", { className: "pt-panel-row", children: /* @__PURE__ */ jsx19(
3947
+ /* @__PURE__ */ jsx20(DetailSection, { title: ui.guideSection, children: /* @__PURE__ */ jsx20("div", { className: "pt-panel-row", children: /* @__PURE__ */ jsx20(
3535
3948
  "button",
3536
3949
  {
3537
3950
  type: "button",
@@ -3549,9 +3962,43 @@ function PanelApp({
3549
3962
  }
3550
3963
  ) }) })
3551
3964
  ] }),
3552
- /* @__PURE__ */ jsxs17(DetailSheet, { open: settingsOpen, onClose: () => setSettingsOpen(false), ariaLabel: ui.panelSettings, children: [
3553
- saveEndpoint ? /* @__PURE__ */ jsxs17(DetailSection, { title: ui.saveSection, subtitle: ui.saveSubtitle, children: [
3554
- /* @__PURE__ */ jsx19("div", { className: "pt-panel-row", children: /* @__PURE__ */ jsx19(
3965
+ update?.behind && /* @__PURE__ */ jsxs18(
3966
+ DetailSheet,
3967
+ {
3968
+ open: releaseOpen,
3969
+ onClose: () => setReleaseOpen(false),
3970
+ ariaLabel: ui.releaseTitle(update.latest),
3971
+ children: [
3972
+ /* @__PURE__ */ jsxs18("div", { children: [
3973
+ /* @__PURE__ */ jsx20("p", { className: "pt-eyebrow", children: releaseShape(update.notes) ? ui.releaseShape[releaseShape(update.notes)] : "" }),
3974
+ /* @__PURE__ */ jsx20("h2", { className: "pt-h2", children: ui.releaseTitle(update.latest) }),
3975
+ update.notes?.date && /* @__PURE__ */ jsx20("p", { className: "pt-sub", children: ui.releaseDate(update.notes.date) })
3976
+ ] }),
3977
+ update.notes ? /* @__PURE__ */ jsx20("ul", { className: "pt-runs", children: update.notes.entries.map((item, index) => /* @__PURE__ */ jsxs18("li", { className: "pt-run pt-hud", children: [
3978
+ /* @__PURE__ */ jsx20("p", { className: "pt-run__meta", children: ui.releaseKind[item.kind] }),
3979
+ /* @__PURE__ */ jsx20("p", { className: "pt-panel-text", children: item.text[lang] })
3980
+ ] }, index)) }) : /* @__PURE__ */ jsx20("p", { className: "pt-panel-text", children: ui.releaseNone }),
3981
+ /* @__PURE__ */ jsxs18("div", { className: "pt-panel-row", style: { marginTop: 16 }, children: [
3982
+ /* @__PURE__ */ jsx20(
3983
+ "button",
3984
+ {
3985
+ type: "button",
3986
+ className: "pt-btn",
3987
+ onClick: () => {
3988
+ setReleaseOpen(false);
3989
+ setSettingsOpen(true);
3990
+ },
3991
+ children: ui.updateCreateCard
3992
+ }
3993
+ ),
3994
+ /* @__PURE__ */ jsx20("button", { type: "button", className: "pt-btn", onClick: () => setReleaseOpen(false), children: ui.releaseClose })
3995
+ ] })
3996
+ ]
3997
+ }
3998
+ ),
3999
+ /* @__PURE__ */ jsxs18(DetailSheet, { open: settingsOpen, onClose: () => setSettingsOpen(false), ariaLabel: ui.panelSettings, children: [
4000
+ saveEndpoint ? /* @__PURE__ */ jsxs18(DetailSection, { title: ui.saveSection, subtitle: ui.saveSubtitle, children: [
4001
+ /* @__PURE__ */ jsx20("div", { className: "pt-panel-row", children: /* @__PURE__ */ jsx20(
3555
4002
  "button",
3556
4003
  {
3557
4004
  type: "button",
@@ -3561,15 +4008,15 @@ function PanelApp({
3561
4008
  children: save.status === "saving" ? ui.saving : ui.save
3562
4009
  }
3563
4010
  ) }),
3564
- /* @__PURE__ */ jsxs17("p", { className: "pt-panel-text", style: { marginTop: 10 }, children: [
4011
+ /* @__PURE__ */ jsxs18("p", { className: "pt-panel-text", style: { marginTop: 10 }, children: [
3565
4012
  save.status === "error" ? `${ui.saveFailed}: ${save.message}` : save.status === "saved" ? ui.savedWithCommit : dirty ? ui.saveHelp : ui.upToDate,
3566
- save.status === "saved" && save.url && /* @__PURE__ */ jsxs17(Fragment5, { children: [
4013
+ save.status === "saved" && save.url && /* @__PURE__ */ jsxs18(Fragment5, { children: [
3567
4014
  " ",
3568
- /* @__PURE__ */ jsx19("a", { href: save.url, children: "commit" })
4015
+ /* @__PURE__ */ jsx20("a", { href: save.url, children: "commit" })
3569
4016
  ] })
3570
4017
  ] })
3571
- ] }) : /* @__PURE__ */ jsx19(DetailSection, { title: ui.saveSection, subtitle: ui.saveSubtitle, children: /* @__PURE__ */ jsx19("p", { className: "pt-panel-text", children: ui.demoNotice }) }),
3572
- showLanguage && /* @__PURE__ */ jsx19(DetailSection, { title: ui.language, subtitle: ui.languageSubtitle, children: /* @__PURE__ */ jsx19("div", { className: "pt-panel-row", children: LANGS.map((code) => /* @__PURE__ */ jsx19(
4018
+ ] }) : /* @__PURE__ */ jsx20(DetailSection, { title: ui.saveSection, subtitle: ui.saveSubtitle, children: /* @__PURE__ */ jsx20("p", { className: "pt-panel-text", children: ui.demoNotice }) }),
4019
+ showLanguage && /* @__PURE__ */ jsx20(DetailSection, { title: ui.language, subtitle: ui.languageSubtitle, children: /* @__PURE__ */ jsx20("div", { className: "pt-panel-row", children: LANGS.map((code) => /* @__PURE__ */ jsx20(
3573
4020
  FilterChip,
3574
4021
  {
3575
4022
  label: LANG_LABELS[code],
@@ -3578,9 +4025,9 @@ function PanelApp({
3578
4025
  },
3579
4026
  code
3580
4027
  )) }) }),
3581
- /* @__PURE__ */ jsxs17(DetailSection, { title: ui.theme, subtitle: ui.themeSubtitle, children: [
3582
- /* @__PURE__ */ jsxs17("div", { className: "pt-panel-row", children: [
3583
- Object.entries(themes).map(([name, entry]) => /* @__PURE__ */ jsx19(
4028
+ /* @__PURE__ */ jsxs18(DetailSection, { title: ui.theme, subtitle: ui.themeSubtitle, children: [
4029
+ /* @__PURE__ */ jsxs18("div", { className: "pt-panel-row", children: [
4030
+ Object.entries(themes).map(([name, entry]) => /* @__PURE__ */ jsx20(
3584
4031
  FilterChip,
3585
4032
  {
3586
4033
  label: entry.label,
@@ -3589,7 +4036,7 @@ function PanelApp({
3589
4036
  },
3590
4037
  name
3591
4038
  )),
3592
- state.importedTheme && /* @__PURE__ */ jsx19(
4039
+ state.importedTheme && /* @__PURE__ */ jsx20(
3593
4040
  FilterChip,
3594
4041
  {
3595
4042
  label: t(state.importedTheme.label),
@@ -3598,21 +4045,21 @@ function PanelApp({
3598
4045
  }
3599
4046
  )
3600
4047
  ] }),
3601
- /* @__PURE__ */ jsx19("p", { className: "pt-panel-text", style: { marginTop: 10 }, children: themeName === IMPORTED ? t(imported?.from.reasoning) : [chosen.note, ui.themeNote].filter(Boolean).join(". ") }),
3602
- state.importedTheme && /* @__PURE__ */ jsxs17("div", { className: "pt-cap pt-hud", style: { marginTop: 14 }, children: [
3603
- /* @__PURE__ */ jsx19("h3", { className: "pt-cap__title", children: ui.importedTheme }),
3604
- /* @__PURE__ */ jsx19("p", { className: "pt-panel-text", children: ui.importedFrom(state.importedTheme.importedAt, state.importedTheme.from.files.join(", ")) }),
3605
- state.importedTheme.from.colours.length > 0 && /* @__PURE__ */ jsx19("p", { className: "pt-tool__tags", children: state.importedTheme.from.colours.map((colour) => /* @__PURE__ */ jsx19("span", { className: "pt-tool__tag", children: colour }, colour)) }),
3606
- state.importedTheme.refreshRequested ? /* @__PURE__ */ jsx19("p", { className: "pt-warn", children: ui.importedRefreshAsked(state.importedTheme.refreshRequested) }) : /* @__PURE__ */ jsx19("div", { className: "pt-panel-row", style: { marginTop: 10 }, children: /* @__PURE__ */ jsx19("button", { type: "button", className: "pt-btn pt-btn--sm", onClick: requestThemeRefresh, children: ui.importedRefresh }) }),
3607
- /* @__PURE__ */ jsx19("p", { className: "pt-marketplace__detail", children: ui.importedRefreshHow })
4048
+ /* @__PURE__ */ jsx20("p", { className: "pt-panel-text", style: { marginTop: 10 }, children: themeName === IMPORTED ? t(imported?.from.reasoning) : [chosen.note, ui.themeNote].filter(Boolean).join(". ") }),
4049
+ state.importedTheme && /* @__PURE__ */ jsxs18("div", { className: "pt-cap pt-hud", style: { marginTop: 14 }, children: [
4050
+ /* @__PURE__ */ jsx20("h3", { className: "pt-cap__title", children: ui.importedTheme }),
4051
+ /* @__PURE__ */ jsx20("p", { className: "pt-panel-text", children: ui.importedFrom(state.importedTheme.importedAt, state.importedTheme.from.files.join(", ")) }),
4052
+ state.importedTheme.from.colours.length > 0 && /* @__PURE__ */ jsx20("p", { className: "pt-tool__tags", children: state.importedTheme.from.colours.map((colour) => /* @__PURE__ */ jsx20("span", { className: "pt-tool__tag", children: colour }, colour)) }),
4053
+ state.importedTheme.refreshRequested ? /* @__PURE__ */ jsx20("p", { className: "pt-warn", children: ui.importedRefreshAsked(state.importedTheme.refreshRequested) }) : /* @__PURE__ */ jsx20("div", { className: "pt-panel-row", style: { marginTop: 10 }, children: /* @__PURE__ */ jsx20("button", { type: "button", className: "pt-btn pt-btn--sm", onClick: requestThemeRefresh, children: ui.importedRefresh }) }),
4054
+ /* @__PURE__ */ jsx20("p", { className: "pt-marketplace__detail", children: ui.importedRefreshHow })
3608
4055
  ] })
3609
4056
  ] }),
3610
- checkForUpdates && fingerprint?.version && /* @__PURE__ */ jsxs17(DetailSection, { title: ui.updateTitle, subtitle: ui.updateSubtitle, children: [
3611
- /* @__PURE__ */ jsx19("p", { className: "pt-panel-text", children: ui.updateCurrent(fingerprint.version) }),
3612
- /* @__PURE__ */ jsx19("p", { className: "pt-panel-text", style: { marginTop: 8 }, children: !update ? ui.updateUnknown : update.behind ? ui.updateAvailable(update.latest) : ui.updateUpToDate }),
3613
- update?.behind && (state.cards.some((card) => card.id === updateCardId(update.latest)) ? /* @__PURE__ */ jsx19("p", { className: "pt-panel-text", style: { marginTop: 8 }, children: ui.updateCardExists }) : /* @__PURE__ */ jsx19("div", { className: "pt-panel-row", style: { marginTop: 12 }, children: /* @__PURE__ */ jsx19("button", { type: "button", className: "pt-btn", onClick: addUpdateCard, children: ui.updateCreateCard }) })),
3614
- /* @__PURE__ */ jsxs17("label", { className: "pt-panel-row", style: { marginTop: 12 }, children: [
3615
- /* @__PURE__ */ jsx19(
4057
+ checkForUpdates && fingerprint?.version && /* @__PURE__ */ jsxs18(DetailSection, { title: ui.updateTitle, subtitle: ui.updateSubtitle, children: [
4058
+ /* @__PURE__ */ jsx20("p", { className: "pt-panel-text", children: ui.updateCurrent(fingerprint.version) }),
4059
+ /* @__PURE__ */ jsx20("p", { className: "pt-panel-text", style: { marginTop: 8 }, children: !update ? ui.updateUnknown : update.behind ? ui.updateAvailable(update.latest) : ui.updateUpToDate }),
4060
+ update?.behind && (state.cards.some((card) => card.id === updateCardId(update.latest)) ? /* @__PURE__ */ jsx20("p", { className: "pt-panel-text", style: { marginTop: 8 }, children: ui.updateCardExists }) : /* @__PURE__ */ jsx20("div", { className: "pt-panel-row", style: { marginTop: 12 }, children: /* @__PURE__ */ jsx20("button", { type: "button", className: "pt-btn", onClick: addUpdateCard, children: ui.updateCreateCard }) })),
4061
+ /* @__PURE__ */ jsxs18("label", { className: "pt-panel-row", style: { marginTop: 12 }, children: [
4062
+ /* @__PURE__ */ jsx20(
3616
4063
  "input",
3617
4064
  {
3618
4065
  type: "checkbox",
@@ -3620,16 +4067,16 @@ function PanelApp({
3620
4067
  onChange: (event) => setPreference("updateAsOrder", event.target.checked)
3621
4068
  }
3622
4069
  ),
3623
- /* @__PURE__ */ jsx19("span", { className: "pt-panel-text", children: ui.updateAsOrder })
4070
+ /* @__PURE__ */ jsx20("span", { className: "pt-panel-text", children: ui.updateAsOrder })
3624
4071
  ] }),
3625
- /* @__PURE__ */ jsx19("p", { className: "pt-marketplace__detail", children: ui.updateAsOrderHow })
4072
+ /* @__PURE__ */ jsx20("p", { className: "pt-marketplace__detail", children: ui.updateAsOrderHow })
3626
4073
  ] }),
3627
- fingerprint && /* @__PURE__ */ jsxs17(DetailSection, { title: ui.fingerprint, subtitle: ui.fingerprintSubtitle, children: [
3628
- /* @__PURE__ */ jsx19("p", { className: "pt-panel-mono", children: fingerprint.hash }),
3629
- /* @__PURE__ */ jsx19("p", { className: "pt-panel-text", style: { marginTop: 8 }, children: ui.trackedFiles(fingerprint.fileCount, fingerprint.version) })
4074
+ fingerprint && /* @__PURE__ */ jsxs18(DetailSection, { title: ui.fingerprint, subtitle: ui.fingerprintSubtitle, children: [
4075
+ /* @__PURE__ */ jsx20("p", { className: "pt-panel-mono", children: fingerprint.hash }),
4076
+ /* @__PURE__ */ jsx20("p", { className: "pt-panel-text", style: { marginTop: 8 }, children: ui.trackedFiles(fingerprint.fileCount, fingerprint.version) })
3630
4077
  ] }),
3631
- saveEndpoint && /* @__PURE__ */ jsxs17(DetailSection, { title: ui.session, subtitle: ui.sessionSubtitle, children: [
3632
- /* @__PURE__ */ jsx19("div", { className: "pt-panel-row", children: /* @__PURE__ */ jsx19(
4078
+ saveEndpoint && /* @__PURE__ */ jsxs18(DetailSection, { title: ui.session, subtitle: ui.sessionSubtitle, children: [
4079
+ /* @__PURE__ */ jsx20("div", { className: "pt-panel-row", children: /* @__PURE__ */ jsx20(
3633
4080
  "button",
3634
4081
  {
3635
4082
  type: "button",
@@ -3639,11 +4086,11 @@ function PanelApp({
3639
4086
  children: signOut === "working" ? ui.signingOut : ui.signOut
3640
4087
  }
3641
4088
  ) }),
3642
- signOut === "failed" && /* @__PURE__ */ jsx19("p", { className: "pt-panel-text", style: { marginTop: 10 }, children: ui.signOutFailed })
4089
+ signOut === "failed" && /* @__PURE__ */ jsx20("p", { className: "pt-panel-text", style: { marginTop: 10 }, children: ui.signOutFailed })
3643
4090
  ] }),
3644
- links && links.length > 0 && /* @__PURE__ */ jsx19(DetailSection, { title: ui.links, children: /* @__PURE__ */ jsx19("p", { className: "pt-panel-text", children: links.map((link, index) => /* @__PURE__ */ jsxs17(React12.Fragment, { children: [
4091
+ links && links.length > 0 && /* @__PURE__ */ jsx20(DetailSection, { title: ui.links, children: /* @__PURE__ */ jsx20("p", { className: "pt-panel-text", children: links.map((link, index) => /* @__PURE__ */ jsxs18(React13.Fragment, { children: [
3645
4092
  index > 0 && " \xB7 ",
3646
- /* @__PURE__ */ jsx19("a", { href: link.href, children: link.label })
4093
+ /* @__PURE__ */ jsx20("a", { href: link.href, children: link.label })
3647
4094
  ] }, link.href)) }) })
3648
4095
  ] }),
3649
4096
  footer
@@ -3842,10 +4289,12 @@ export {
3842
4289
  OWNERS,
3843
4290
  PANELTIR_FILE_COUNT,
3844
4291
  PANELTIR_FINGERPRINT,
4292
+ PANELTIR_TEMPLATE_HASH,
3845
4293
  PANELTIR_VERSION,
3846
4294
  PRESET_PANEL_THEMES,
3847
4295
  PanelApp,
3848
4296
  SetupGuide,
4297
+ SetupWizard,
3849
4298
  StatTile,
3850
4299
  StatTileGrid,
3851
4300
  THEME_FORMS,
@@ -3862,11 +4311,14 @@ export {
3862
4311
  decided,
3863
4312
  emptyCard,
3864
4313
  explainBoard,
4314
+ gateStatus,
3865
4315
  isCard,
4316
+ isFirstRun,
3866
4317
  ledgerForm,
3867
4318
  midnightTheme,
3868
4319
  moveCardInColumns,
3869
4320
  newId,
4321
+ offeredThemes,
3870
4322
  oldMoneyTheme,
3871
4323
  panelForm,
3872
4324
  paneltirBuild,
@@ -3889,5 +4341,6 @@ export {
3889
4341
  useGuideNote,
3890
4342
  useMediaQuery,
3891
4343
  validateBoard,
4344
+ wizardStep,
3892
4345
  writeText
3893
4346
  };