@akropolys/kiku 1.7.3 → 1.7.5

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
@@ -1162,6 +1162,7 @@ var ArrowUpIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", {
1162
1162
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M12 19V5" })
1163
1163
  ] });
1164
1164
  var StopIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("rect", { x: "5", y: "5", width: "14", height: "14", rx: "2" }) });
1165
+ var ContinueIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M8 5v14l11-7z" }) });
1165
1166
  var CloseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
1166
1167
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1167
1168
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
@@ -1191,12 +1192,22 @@ var MicOffIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { wi
1191
1192
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M9 9v3a3 3 0 0 0 5.12 2.12" }),
1192
1193
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "12", y1: "19", x2: "12", y2: "22" })
1193
1194
  ] });
1194
- var DEFAULT_CHIPS = [
1195
- "Cheapest smartphone",
1196
- "Smart TV under KSh 20,000",
1197
- "Noise-cancelling headphones",
1198
- "Best laptop for students"
1199
- ];
1195
+ var DEFAULT_CHIPS = [];
1196
+ function extractName(raw) {
1197
+ let s = raw.trim();
1198
+ if (!s || s.length > 40 || s.includes("?")) return null;
1199
+ s = s.replace(/^(hi|hey|hello|yo)[,!.\s]+/i, "");
1200
+ s = s.replace(/^(i['’]?m|im|my name is|call me|it['’]?s|this is|name['’]?s)\s+/i, "");
1201
+ s = s.trim().replace(/[.!,]+$/, "");
1202
+ const words = s.split(/\s+/);
1203
+ if (words.length === 0 || words.length > 3) return null;
1204
+ if (!/^[\p{L}][\p{L}\-'’ ]{0,30}$/u.test(s)) return null;
1205
+ const q = s.toLowerCase();
1206
+ const queryish = ["phone", "laptop", "tv", "cheap", "best", "under", "buy", "search", "find", "show", "need", "want", "price", "sofa", "shoe", "headphone", "camera", "gift", "help"];
1207
+ if (queryish.some((w) => q.includes(w))) return null;
1208
+ const name = words[0];
1209
+ return name.charAt(0).toUpperCase() + name.slice(1);
1210
+ }
1200
1211
  function parseAtKiku(raw) {
1201
1212
  const trimmed = raw.trim();
1202
1213
  if (!/^@kiku\b/i.test(trimmed)) return null;
@@ -1656,15 +1667,9 @@ function ThinkingBlock({ text, isComplete }) {
1656
1667
  }, children: text })
1657
1668
  ] });
1658
1669
  }
1659
- var PROPERTY_CHIPS = [
1660
- "3 bedroom apartments",
1661
- "Houses under KSh 5,000,000",
1662
- "Properties in Palm Beach",
1663
- "Studio apartments with pool"
1664
- ];
1665
1670
  function ChatModal({
1666
1671
  title = "kiku",
1667
- placeholder = "Ask me anything \u2014 gifts, budget, use case\u2026",
1672
+ placeholder = "Ask me anything\u2026",
1668
1673
  backdropColor,
1669
1674
  backdropBlur,
1670
1675
  onClose,
@@ -1679,8 +1684,17 @@ function ChatModal({
1679
1684
  visionCategoryHint
1680
1685
  }) {
1681
1686
  const client = (0, import_sdk6.useAkropolysContext)();
1682
- const { messages, sources, loading, streaming, error, lastAction, lastIntent, send, stop, reset, referencedIds } = (0, import_sdk5.useKiku)();
1687
+ const { messages, sources, loading, streaming, error, lastAction, lastIntent, send, stop, stopped, continueGenerating, reset, referencedIds } = (0, import_sdk5.useKiku)();
1683
1688
  const [input, setInput] = (0, import_react5.useState)("");
1689
+ const [shopperName, setShopperNameState] = (0, import_react5.useState)(() => {
1690
+ try {
1691
+ return client.getShopperName?.() ?? "";
1692
+ } catch {
1693
+ return "";
1694
+ }
1695
+ });
1696
+ const [nameSkipped, setNameSkipped] = (0, import_react5.useState)(false);
1697
+ const awaitingName = messages.length === 0 && !shopperName && !nameSkipped;
1684
1698
  const [attachments, setAttachments] = (0, import_react5.useState)([]);
1685
1699
  const imageInputRef = (0, import_react5.useRef)(null);
1686
1700
  const handleImageFiles = (files) => {
@@ -1749,10 +1763,9 @@ function ChatModal({
1749
1763
  (0, import_react5.useEffect)(() => {
1750
1764
  return () => recognitionRef.current?.abort();
1751
1765
  }, []);
1752
- const isProperty = client.vertical === "property";
1753
- const activeChips = chips === DEFAULT_CHIPS && isProperty ? PROPERTY_CHIPS : chips;
1766
+ const activeChips = chips;
1754
1767
  const activeTitle = title;
1755
- const activePlaceholder = placeholder === "Ask me anything \u2014 gifts, budget, use case\u2026" && isProperty ? "Ask me anything \u2014 location, budget, bedrooms\u2026" : placeholder;
1768
+ const activePlaceholder = awaitingName ? "Type your name\u2026" : placeholder;
1756
1769
  const [selectedProduct, setSelectedProduct] = (0, import_react5.useState)(null);
1757
1770
  const [lightboxSrc, setLightboxSrc] = (0, import_react5.useState)(null);
1758
1771
  const bottomRef = (0, import_react5.useRef)(null);
@@ -1760,6 +1773,7 @@ function ChatModal({
1760
1773
  const [keyInput, setKeyInput] = (0, import_react5.useState)("");
1761
1774
  const [keyPhase, setKeyPhase] = (0, import_react5.useState)("idle");
1762
1775
  const [mintedKey, setMintedKey] = (0, import_react5.useState)(null);
1776
+ const [mintedPub, setMintedPub] = (0, import_react5.useState)(null);
1763
1777
  const [keyCountdown, setKeyCountdown] = (0, import_react5.useState)(KIKU_KEY_REVEAL_SECONDS);
1764
1778
  const [minting, setMinting] = (0, import_react5.useState)(false);
1765
1779
  const [showKikuPicker, setShowKikuPicker] = (0, import_react5.useState)(false);
@@ -1778,6 +1792,7 @@ function ChatModal({
1778
1792
  if (s <= 1) {
1779
1793
  clearInterval(t);
1780
1794
  setMintedKey(null);
1795
+ setMintedPub(null);
1781
1796
  return 0;
1782
1797
  }
1783
1798
  return s - 1;
@@ -1799,9 +1814,9 @@ function ChatModal({
1799
1814
  if (lastUserMsg) await handleSend(lastUserMsg.content);
1800
1815
  };
1801
1816
  const handleUseExistingKey = async () => {
1802
- const key = keyInput.trim();
1803
- if (!key) return;
1804
- client.setKikuKey(key);
1817
+ const pub = keyInput.trim();
1818
+ if (!pub) return;
1819
+ client.setKikuPub(pub);
1805
1820
  setKeyInput("");
1806
1821
  setKeyPhase("idle");
1807
1822
  await retryLastMessage();
@@ -1810,8 +1825,9 @@ function ChatModal({
1810
1825
  if (minting) return;
1811
1826
  setMinting(true);
1812
1827
  try {
1813
- const key = await client.mintKikuKey();
1814
- setMintedKey(key);
1828
+ const { secret, publicId } = await client.mintKikuKey();
1829
+ setMintedKey(secret);
1830
+ setMintedPub(publicId);
1815
1831
  setKeyPhase("idle");
1816
1832
  await retryLastMessage();
1817
1833
  } catch {
@@ -1860,12 +1876,31 @@ function ChatModal({
1860
1876
  const handleSourceClick = (src) => {
1861
1877
  setSelectedProduct(src);
1862
1878
  onSelectSource?.(src);
1879
+ const lastAssistant = [...messages].reverse().find((m) => m.role === "assistant");
1880
+ if (lastAssistant && lastAssistant.content.trim().endsWith("?")) {
1881
+ send(`The ${src.name}`);
1882
+ return;
1883
+ }
1863
1884
  const q = `Tell me more about the ${src.name}${src.price ? ` (${src.currency ?? defaultCurrency} ${src.price})` : ""} \u2014 what are its key specs, who is it best for, and is it worth buying?`;
1864
1885
  send(q);
1865
1886
  };
1866
1887
  const handleSend = async (text, extraAttachments, forcedIntent, captureTargets) => {
1867
1888
  const raw = (text ?? input).trim();
1868
1889
  if (!raw || loading) return;
1890
+ if (awaitingName) {
1891
+ const name = extractName(raw);
1892
+ if (name) {
1893
+ try {
1894
+ client.setShopperName?.(name);
1895
+ } catch {
1896
+ }
1897
+ setShopperNameState(name);
1898
+ setInput("");
1899
+ if (textareaRef.current) textareaRef.current.style.height = "auto";
1900
+ return;
1901
+ }
1902
+ setNameSkipped(true);
1903
+ }
1869
1904
  const kiku = parseAtKiku(raw);
1870
1905
  const q = kiku ? kiku.cleanQuery : raw;
1871
1906
  const resolvedForcedIntent = forcedIntent ?? kiku?.intent;
@@ -1948,7 +1983,7 @@ function ChatModal({
1948
1983
  setInput(val);
1949
1984
  const trimmed = val.trim();
1950
1985
  setShowAtPicker(trimmed === "@");
1951
- setShowKikuPicker(/^@kiku\b/i.test(trimmed));
1986
+ setShowKikuPicker(/^@kiku\s*$/i.test(trimmed));
1952
1987
  const t = e.target;
1953
1988
  t.style.height = "auto";
1954
1989
  t.style.height = `${Math.min(t.scrollHeight, 140)}px`;
@@ -2011,9 +2046,31 @@ function ChatModal({
2011
2046
  ] }),
2012
2047
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-msgs", ref: msgsContainerRef, children: [
2013
2048
  displayMessages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-empty", children: [
2014
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-empty-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
2015
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-empty-title", children: "Find exactly what you need" }),
2016
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-chips", children: activeChips.map((chip) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2049
+ awaitingName ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2050
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("h2", { className: "hsk-cb-hello", children: [
2051
+ "Hi, I'm ",
2052
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("b", { children: "kiku" }),
2053
+ "."
2054
+ ] }),
2055
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "hsk-cb-hello-lead", children: "I can search, visualize, or capture anything for you \u2014 on this site or any other." }),
2056
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "hsk-cb-hello-ask", children: "What should I call you?" }),
2057
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-hello-skip", onClick: () => setNameSkipped(true), children: "Skip for now" })
2058
+ ] }) : shopperName ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2059
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("h2", { className: "hsk-cb-hello", children: [
2060
+ "Hi, ",
2061
+ shopperName,
2062
+ "."
2063
+ ] }),
2064
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "hsk-cb-hello-lead", children: "What can I find for you today?" })
2065
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2066
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("h2", { className: "hsk-cb-hello", children: [
2067
+ "Hi, I'm ",
2068
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("b", { children: "kiku" }),
2069
+ "."
2070
+ ] }),
2071
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "hsk-cb-hello-lead", children: "Ask me to search, visualize, or capture anything \u2014 I look across the whole site in real time." })
2072
+ ] }),
2073
+ !awaitingName && activeChips.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-chips", children: activeChips.map((chip) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2017
2074
  "button",
2018
2075
  {
2019
2076
  className: "hsk-cb-chip",
@@ -2135,17 +2192,24 @@ function ChatModal({
2135
2192
  ] }),
2136
2193
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-cb-thinking-text", children: "Thinking\u2026" })
2137
2194
  ] }),
2195
+ stopped && !loading && !streaming && messages[messages.length - 1]?.role === "assistant" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-stopped", children: [
2196
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-cb-stopped-label", children: "You stopped this response." }),
2197
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("button", { className: "hsk-cb-continue", onClick: continueGenerating, children: [
2198
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ContinueIcon, {}),
2199
+ "Continue generating"
2200
+ ] })
2201
+ ] }),
2138
2202
  error && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-error", children: getFriendlyError(error) }),
2139
2203
  keyPhase === "prompt_key" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
2140
2204
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
2141
2205
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-body", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-text", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-phone-form", children: [
2142
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "hsk-cb-phone-label", children: "Paste your kiku key \u2014 or create one" }),
2206
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "hsk-cb-phone-label", children: "Paste your public id \u2014 or create one" }),
2143
2207
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2144
2208
  "input",
2145
2209
  {
2146
2210
  type: "text",
2147
2211
  className: "hsk-cb-phone-input",
2148
- placeholder: "kiku_\u2026",
2212
+ placeholder: "your public id\u2026",
2149
2213
  value: keyInput,
2150
2214
  onChange: (e) => setKeyInput(e.target.value),
2151
2215
  onKeyDown: (e) => e.key === "Enter" && handleUseExistingKey(),
@@ -2153,28 +2217,44 @@ function ChatModal({
2153
2217
  }
2154
2218
  ),
2155
2219
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", gap: 8 }, children: [
2156
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-phone-submit", onClick: handleUseExistingKey, disabled: !keyInput.trim(), children: "Use my key" }),
2157
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-phone-submit", onClick: handleCreateKey, disabled: minting, children: minting ? "Creating\u2026" : "I'm new \u2014 create my key" })
2220
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-phone-submit", onClick: handleUseExistingKey, disabled: !keyInput.trim(), children: "Use my id" }),
2221
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-phone-submit", onClick: handleCreateKey, disabled: minting, children: minting ? "Creating\u2026" : "I'm new \u2014 create one" })
2158
2222
  ] })
2159
2223
  ] }) }) })
2160
2224
  ] }),
2161
2225
  mintedKey && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
2162
2226
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
2163
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-body", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-text", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { padding: "10px 12px", border: "1px solid var(--hsk-border, #e5e5e5)", borderRadius: 8 }, children: [
2164
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { fontSize: 12, fontWeight: 600, marginBottom: 4 }, children: "\u{1F511} Your kiku key \u2014 shown only once" }),
2165
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { style: { display: "block", fontSize: 14, fontWeight: 700, marginBottom: 6, wordBreak: "break-all" }, children: mintedKey }),
2166
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
2167
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-phone-submit", style: { padding: "4px 10px" }, onClick: () => {
2168
- try {
2169
- navigator.clipboard?.writeText(mintedKey);
2170
- } catch {
2171
- }
2172
- }, children: "Copy" }),
2173
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { style: { fontSize: 11, opacity: 0.7 }, children: [
2174
- "Disappears in ",
2175
- keyCountdown,
2176
- "s. Save it like a password \u2014 if lost, the memory it opens is lost with it."
2227
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-body", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-text", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { padding: "12px 14px", border: "1px solid var(--hsk-border, #e5e5e5)", borderRadius: "var(--hsk-border-radius, 0px)", display: "flex", flexDirection: "column", gap: 12 }, children: [
2228
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
2229
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { fontSize: 12, fontWeight: 600, marginBottom: 4 }, children: "Your secret \u2014 shown only once" }),
2230
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { style: { display: "block", fontSize: 14, fontWeight: 700, marginBottom: 6, wordBreak: "break-all" }, children: mintedKey }),
2231
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
2232
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-phone-submit", style: { padding: "4px 10px" }, onClick: () => {
2233
+ try {
2234
+ navigator.clipboard?.writeText(mintedKey);
2235
+ } catch {
2236
+ }
2237
+ }, children: "Copy secret" }),
2238
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: 11, opacity: 0.7 }, children: "Keep it private \u2014 use it to unlock your memory at mimi.akropolys.cloud. If lost, the memory is lost with it." })
2177
2239
  ] })
2240
+ ] }),
2241
+ mintedPub && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
2242
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { fontSize: 12, fontWeight: 600, marginBottom: 4 }, children: "Your public id" }),
2243
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { style: { display: "block", fontSize: 13, fontWeight: 600, marginBottom: 6, wordBreak: "break-all", opacity: 0.85 }, children: mintedPub }),
2244
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
2245
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-phone-submit", style: { padding: "4px 10px" }, onClick: () => {
2246
+ try {
2247
+ navigator.clipboard?.writeText(mintedPub);
2248
+ } catch {
2249
+ }
2250
+ }, children: "Copy id" }),
2251
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: 11, opacity: 0.7 }, children: "Paste this on any site to keep saving to the same memory." })
2252
+ ] })
2253
+ ] }),
2254
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { fontSize: 11, opacity: 0.6 }, children: [
2255
+ "Hidden in ",
2256
+ keyCountdown,
2257
+ "s."
2178
2258
  ] })
2179
2259
  ] }) }) })
2180
2260
  ] }),