@loafmarkets/ui 0.1.408 → 0.1.409

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.d.mts CHANGED
@@ -712,6 +712,11 @@ type HeaderProps = {
712
712
  * without DOM-level click interception. */
713
713
  onReferClick?: () => void;
714
714
  portfolioSummary?: HeaderPortfolioData | null;
715
+ /**
716
+ * Cumulative competition points the user has earned across all rounds up to now.
717
+ * When provided, the account dropdown leads with a "Total Points" summary row.
718
+ */
719
+ totalPoints?: number | null;
715
720
  /**
716
721
  * True while a brand-new user's test funds (100k mock USD) are being deposited
717
722
  * on-chain (~10s). Replaces the portfolio metrics with a "funds arriving" banner.
@@ -768,9 +773,12 @@ interface OnboardingGuideProps {
768
773
  onEnterCode?: () => void;
769
774
  /** Dismiss / skip (✕, "Skip for now", or after Browse). */
770
775
  onClose: () => void;
776
+ /** Save the chosen handle (optional step). Reject to surface an error
777
+ * (e.g. handle taken). If omitted, the handle step is skipped entirely. */
778
+ onClaimHandle?: (handle: string) => Promise<void> | void;
771
779
  logoSrc?: string;
772
780
  }
773
- declare function OnboardingGuide({ open, fundsReady, cashLabel, onBrowseProperties, onEnterCode, onClose, logoSrc, }: OnboardingGuideProps): react_jsx_runtime.JSX.Element | null;
781
+ declare function OnboardingGuide({ open, fundsReady, cashLabel, onBrowseProperties, onEnterCode, onClose, onClaimHandle, logoSrc, }: OnboardingGuideProps): react_jsx_runtime.JSX.Element | null;
774
782
 
775
783
  type PropertyAddressOption = {
776
784
  id: string;
package/dist/index.d.ts CHANGED
@@ -712,6 +712,11 @@ type HeaderProps = {
712
712
  * without DOM-level click interception. */
713
713
  onReferClick?: () => void;
714
714
  portfolioSummary?: HeaderPortfolioData | null;
715
+ /**
716
+ * Cumulative competition points the user has earned across all rounds up to now.
717
+ * When provided, the account dropdown leads with a "Total Points" summary row.
718
+ */
719
+ totalPoints?: number | null;
715
720
  /**
716
721
  * True while a brand-new user's test funds (100k mock USD) are being deposited
717
722
  * on-chain (~10s). Replaces the portfolio metrics with a "funds arriving" banner.
@@ -768,9 +773,12 @@ interface OnboardingGuideProps {
768
773
  onEnterCode?: () => void;
769
774
  /** Dismiss / skip (✕, "Skip for now", or after Browse). */
770
775
  onClose: () => void;
776
+ /** Save the chosen handle (optional step). Reject to surface an error
777
+ * (e.g. handle taken). If omitted, the handle step is skipped entirely. */
778
+ onClaimHandle?: (handle: string) => Promise<void> | void;
771
779
  logoSrc?: string;
772
780
  }
773
- declare function OnboardingGuide({ open, fundsReady, cashLabel, onBrowseProperties, onEnterCode, onClose, logoSrc, }: OnboardingGuideProps): react_jsx_runtime.JSX.Element | null;
781
+ declare function OnboardingGuide({ open, fundsReady, cashLabel, onBrowseProperties, onEnterCode, onClose, onClaimHandle, logoSrc, }: OnboardingGuideProps): react_jsx_runtime.JSX.Element | null;
774
782
 
775
783
  type PropertyAddressOption = {
776
784
  id: string;
package/dist/index.js CHANGED
@@ -5103,6 +5103,7 @@ var Header = ({
5103
5103
  onSettingsClick,
5104
5104
  onReferClick,
5105
5105
  portfolioSummary,
5106
+ totalPoints,
5106
5107
  fundsPending = false,
5107
5108
  transparentOnTop = false,
5108
5109
  headerCta = "deposit",
@@ -5566,6 +5567,11 @@ var Header = ({
5566
5567
  }
5567
5568
  ),
5568
5569
  isUserMenuOpen && /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { className: "user-menu-dropdown", children: [
5570
+ totalPoints != null && /* @__PURE__ */ jsxRuntime.jsxs(PointsHeader, { children: [
5571
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pts-label", children: "Total Points" }),
5572
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pts-value", children: totalPoints.toLocaleString() }),
5573
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pts-note", children: "Cumulative points earned. More soon." })
5574
+ ] }),
5569
5575
  /* @__PURE__ */ jsxRuntime.jsx(
5570
5576
  "button",
5571
5577
  {
@@ -5623,7 +5629,7 @@ var Header = ({
5623
5629
  }
5624
5630
  )
5625
5631
  ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center" }, children: [
5626
- /* @__PURE__ */ jsxRuntime.jsx(Button2, { className: "signup", onClick: handleSignIn, children: "Connect" }),
5632
+ /* @__PURE__ */ jsxRuntime.jsx(Button2, { className: "signup", onClick: handleSignIn, children: "Join Competition" }),
5627
5633
  /* @__PURE__ */ jsxRuntime.jsx(
5628
5634
  MobileOnlyButton,
5629
5635
  {
@@ -6151,6 +6157,33 @@ var DropdownMenu = styled10__default.default.div`
6151
6157
  display: block;
6152
6158
  }
6153
6159
  `;
6160
+ var PointsHeader = styled10__default.default.div`
6161
+ padding: 0.7rem 1.25rem 0.8rem;
6162
+ margin-bottom: 0.35rem;
6163
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
6164
+ .pts-note {
6165
+ margin-top: 0.4rem;
6166
+ font-size: 0.6rem;
6167
+ line-height: 1.4;
6168
+ color: rgba(255, 255, 255, 0.4);
6169
+ }
6170
+ .pts-label {
6171
+ font-family: 'SF Mono', 'Fira Code', ui-monospace, monospace;
6172
+ font-size: 0.56rem;
6173
+ font-weight: 700;
6174
+ letter-spacing: 0.16em;
6175
+ text-transform: uppercase;
6176
+ color: rgba(255, 255, 255, 0.45);
6177
+ }
6178
+ .pts-value {
6179
+ margin-top: 0.2rem;
6180
+ font-size: 1.15rem;
6181
+ font-weight: 800;
6182
+ color: #E6C87E;
6183
+ font-variant-numeric: tabular-nums;
6184
+ line-height: 1;
6185
+ }
6186
+ `;
6154
6187
  var MenuItem = styled10__default.default.div`
6155
6188
  padding: 0.75rem 1.25rem;
6156
6189
  cursor: pointer;
@@ -9053,6 +9086,48 @@ var CodeLink = styled10__default.default.button`
9053
9086
  text-underline-offset: 2px;
9054
9087
  }
9055
9088
  `;
9089
+ var HandleField = styled10__default.default.div`
9090
+ display: flex;
9091
+ align-items: center;
9092
+ gap: 0.1rem;
9093
+ width: 100%;
9094
+ margin-bottom: 0.4rem;
9095
+ padding: 0 0.9rem;
9096
+ background: rgba(255, 255, 255, 0.04);
9097
+ border: 1px solid rgba(255, 255, 255, 0.1);
9098
+ border-radius: 10px;
9099
+ transition: border-color 0.15s ease;
9100
+
9101
+ &:focus-within {
9102
+ border-color: rgba(230, 200, 126, 0.6);
9103
+ }
9104
+ `;
9105
+ var HandleAt = styled10__default.default.span`
9106
+ color: rgba(255, 255, 255, 0.4);
9107
+ font-size: 1rem;
9108
+ font-weight: 600;
9109
+ `;
9110
+ var HandleInput = styled10__default.default.input`
9111
+ flex: 1;
9112
+ min-width: 0;
9113
+ padding: 0.85rem 0.4rem;
9114
+ border: none;
9115
+ background: transparent;
9116
+ color: #fff;
9117
+ font-size: 1rem;
9118
+ font-family: inherit;
9119
+ outline: none;
9120
+
9121
+ &::placeholder {
9122
+ color: rgba(255, 255, 255, 0.35);
9123
+ }
9124
+ `;
9125
+ var FieldError = styled10__default.default.div`
9126
+ width: 100%;
9127
+ margin-bottom: 0.6rem;
9128
+ font-size: 0.78rem;
9129
+ color: #ff6b6b;
9130
+ `;
9056
9131
  function OnboardingGuide({
9057
9132
  open,
9058
9133
  fundsReady,
@@ -9060,8 +9135,21 @@ function OnboardingGuide({
9060
9135
  onBrowseProperties,
9061
9136
  onEnterCode,
9062
9137
  onClose,
9138
+ onClaimHandle,
9063
9139
  logoSrc = "/Loaf-logo-Banner.png"
9064
9140
  }) {
9141
+ const [step, setStep] = React5.useState(onClaimHandle ? "handle" : "funds");
9142
+ const [handle, setHandle] = React5.useState("");
9143
+ const [claiming, setClaiming] = React5.useState(false);
9144
+ const [handleError, setHandleError] = React5.useState("");
9145
+ React5.useEffect(() => {
9146
+ if (open) {
9147
+ setStep(onClaimHandle ? "handle" : "funds");
9148
+ setHandle("");
9149
+ setClaiming(false);
9150
+ setHandleError("");
9151
+ }
9152
+ }, [open, onClaimHandle]);
9065
9153
  React5.useEffect(() => {
9066
9154
  if (!open) return;
9067
9155
  const onKey = (e) => {
@@ -9071,6 +9159,58 @@ function OnboardingGuide({
9071
9159
  return () => window.removeEventListener("keydown", onKey);
9072
9160
  }, [open, onClose]);
9073
9161
  if (!open) return null;
9162
+ const handleClaimContinue = async () => {
9163
+ const trimmed = handle.trim().replace(/^@+/, "");
9164
+ if (trimmed && onClaimHandle) {
9165
+ setClaiming(true);
9166
+ setHandleError("");
9167
+ try {
9168
+ await onClaimHandle(trimmed);
9169
+ } catch (err) {
9170
+ setHandleError(err instanceof Error ? err.message : "Couldn't claim that handle. Try another or skip.");
9171
+ setClaiming(false);
9172
+ return;
9173
+ }
9174
+ setClaiming(false);
9175
+ }
9176
+ setStep("funds");
9177
+ };
9178
+ if (step === "handle") {
9179
+ return /* @__PURE__ */ jsxRuntime.jsx(Overlay3, { onClick: onClose, role: "dialog", "aria-modal": "true", "aria-label": "Claim your handle", children: /* @__PURE__ */ jsxRuntime.jsxs(Card2, { onClick: (e) => e.stopPropagation(), children: [
9180
+ /* @__PURE__ */ jsxRuntime.jsx(CloseButton2, { onClick: onClose, "aria-label": "Skip", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 6l12 12M18 6L6 18" }) }) }),
9181
+ /* @__PURE__ */ jsxRuntime.jsxs(LogoRow, { children: [
9182
+ /* @__PURE__ */ jsxRuntime.jsx(LogoImage2, { src: logoSrc, alt: "Loaf" }),
9183
+ /* @__PURE__ */ jsxRuntime.jsx(LogoBeta2, { children: "Private Beta" })
9184
+ ] }),
9185
+ /* @__PURE__ */ jsxRuntime.jsx(Title2, { children: "Claim your handle" }),
9186
+ /* @__PURE__ */ jsxRuntime.jsx(Subtitle2, { children: "Pick a username for your Loaf profile. It's optional \u2014 you can set or change it later." }),
9187
+ /* @__PURE__ */ jsxRuntime.jsxs(HandleField, { children: [
9188
+ /* @__PURE__ */ jsxRuntime.jsx(HandleAt, { children: "@" }),
9189
+ /* @__PURE__ */ jsxRuntime.jsx(
9190
+ HandleInput,
9191
+ {
9192
+ type: "text",
9193
+ autoComplete: "off",
9194
+ autoCapitalize: "none",
9195
+ spellCheck: false,
9196
+ placeholder: "username (optional)",
9197
+ value: handle,
9198
+ onChange: (e) => {
9199
+ setHandle(e.target.value.replace(/[^a-zA-Z0-9_]/g, ""));
9200
+ setHandleError("");
9201
+ },
9202
+ onKeyDown: (e) => {
9203
+ if (e.key === "Enter" && !claiming) void handleClaimContinue();
9204
+ },
9205
+ autoFocus: true
9206
+ }
9207
+ )
9208
+ ] }),
9209
+ handleError && /* @__PURE__ */ jsxRuntime.jsx(FieldError, { children: handleError }),
9210
+ /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: () => void handleClaimContinue(), disabled: claiming, children: claiming ? "Saving\u2026" : "Continue" }),
9211
+ /* @__PURE__ */ jsxRuntime.jsx(SkipButton, { onClick: () => setStep("funds"), disabled: claiming, children: "Skip for now" })
9212
+ ] }) });
9213
+ }
9074
9214
  return /* @__PURE__ */ jsxRuntime.jsx(Overlay3, { onClick: onClose, role: "dialog", "aria-modal": "true", "aria-label": "Welcome to Loaf", children: /* @__PURE__ */ jsxRuntime.jsxs(Card2, { onClick: (e) => e.stopPropagation(), children: [
9075
9215
  /* @__PURE__ */ jsxRuntime.jsx(CloseButton2, { onClick: onClose, "aria-label": "Skip", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 6l12 12M18 6L6 18" }) }) }),
9076
9216
  /* @__PURE__ */ jsxRuntime.jsxs(LogoRow, { children: [
@@ -12134,6 +12274,11 @@ var DocIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height
12134
12274
  /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "16", y1: "17", x2: "8", y2: "17" }),
12135
12275
  /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "10 9 9 9 8 9" })
12136
12276
  ] });
12277
+ var DownloadIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
12278
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
12279
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "7 10 12 15 17 10" }),
12280
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
12281
+ ] });
12137
12282
  var LIVE_TITLE_PATTERNS = [/term\s*sheet/i, /memo/i];
12138
12283
  var COMING_SOON_TITLES = [
12139
12284
  "Valuation Report",
@@ -12148,11 +12293,30 @@ var COMING_SOON_TITLES = [
12148
12293
  ];
12149
12294
  function PropertyDocuments({ documentsData, highlightDocument, onClearHighlight }) {
12150
12295
  const highlightRef = React5.useRef(null);
12151
- React5.useRef(null);
12296
+ const [previewUrl, setPreviewUrl] = React5.useState(null);
12297
+ const [previewTitle, setPreviewTitle] = React5.useState(null);
12298
+ const backendDocuments = Array.isArray(documentsData?.documents) ? documentsData.documents : [];
12299
+ const liveDocs = backendDocuments.filter(
12300
+ (d) => Boolean(d.documentUrl) && LIVE_TITLE_PATTERNS.some((rx) => rx.test(d.title))
12301
+ );
12302
+ const comingSoonDocs = COMING_SOON_TITLES.filter(
12303
+ (title) => !liveDocs.some((d) => d.title.toLowerCase().includes(title.toLowerCase()) || title.toLowerCase().includes(d.title.toLowerCase()))
12304
+ ).map((title) => ({ title, documentUrl: "" }));
12305
+ const documents = [...liveDocs, ...comingSoonDocs];
12306
+ const activeUrl = previewUrl ?? (liveDocs[0]?.documentUrl || null);
12307
+ const activeTitle = previewUrl ? previewTitle : liveDocs[0]?.title || null;
12308
+ const selectPreview = (doc) => {
12309
+ setPreviewUrl(doc.documentUrl);
12310
+ setPreviewTitle(doc.title);
12311
+ };
12152
12312
  React5.useEffect(() => {
12153
12313
  if (highlightDocument && highlightRef.current) {
12154
12314
  highlightRef.current.scrollIntoView({ behavior: "smooth", block: "nearest" });
12155
12315
  }
12316
+ if (highlightDocument) {
12317
+ const hit = liveDocs.find((d) => d.title.toLowerCase().includes(highlightDocument.toLowerCase()));
12318
+ if (hit) selectPreview(hit);
12319
+ }
12156
12320
  }, [highlightDocument]);
12157
12321
  React5.useEffect(() => {
12158
12322
  if (!highlightDocument || !onClearHighlight) return;
@@ -12164,36 +12328,58 @@ function PropertyDocuments({ documentsData, highlightDocument, onClearHighlight
12164
12328
  document.addEventListener("click", handler, true);
12165
12329
  return () => document.removeEventListener("click", handler, true);
12166
12330
  }, [highlightDocument, onClearHighlight]);
12167
- const backendDocuments = Array.isArray(documentsData?.documents) ? documentsData.documents : [];
12168
- const liveDocs = backendDocuments.filter(
12169
- (d) => Boolean(d.documentUrl) && LIVE_TITLE_PATTERNS.some((rx) => rx.test(d.title))
12170
- );
12171
- const comingSoonDocs = COMING_SOON_TITLES.filter(
12172
- (title) => !liveDocs.some((d) => d.title.toLowerCase().includes(title.toLowerCase()) || title.toLowerCase().includes(d.title.toLowerCase()))
12173
- ).map((title) => ({ title, documentUrl: "" }));
12174
- const documents = [...liveDocs, ...comingSoonDocs];
12175
12331
  return /* @__PURE__ */ jsxRuntime.jsxs(Section2, { children: [
12176
12332
  /* @__PURE__ */ jsxRuntime.jsx(SectionHeading, { children: "Investment Documents" }),
12177
- /* @__PURE__ */ jsxRuntime.jsx(DocList, { children: documents.map(({ documentUrl, title }) => {
12178
- const isAvailable = Boolean(documentUrl);
12179
- const isHighlighted = highlightDocument != null && title.toLowerCase().includes(highlightDocument.toLowerCase());
12180
- return /* @__PURE__ */ jsxRuntime.jsx(
12181
- DocItem,
12333
+ /* @__PURE__ */ jsxRuntime.jsxs(SplitLayout, { children: [
12334
+ /* @__PURE__ */ jsxRuntime.jsx(DocList, { children: documents.map(({ documentUrl, title }) => {
12335
+ const isAvailable = Boolean(documentUrl);
12336
+ const isHighlighted = highlightDocument != null && title.toLowerCase().includes(highlightDocument.toLowerCase());
12337
+ const isActive = isAvailable && documentUrl === activeUrl;
12338
+ return /* @__PURE__ */ jsxRuntime.jsx(
12339
+ DocItem,
12340
+ {
12341
+ ref: isHighlighted ? highlightRef : void 0,
12342
+ $highlighted: isHighlighted,
12343
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
12344
+ DocRow,
12345
+ {
12346
+ $available: isAvailable,
12347
+ $active: isActive,
12348
+ onMouseEnter: isAvailable ? () => selectPreview({ documentUrl, title }) : void 0,
12349
+ onClick: isAvailable ? () => selectPreview({ documentUrl, title }) : void 0,
12350
+ children: [
12351
+ /* @__PURE__ */ jsxRuntime.jsxs(DocName, { $available: isAvailable, children: [
12352
+ /* @__PURE__ */ jsxRuntime.jsx(DocIconWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(DocIcon, {}) }),
12353
+ title
12354
+ ] }),
12355
+ isAvailable ? /* @__PURE__ */ jsxRuntime.jsx(
12356
+ DownloadBtn,
12357
+ {
12358
+ href: documentUrl,
12359
+ target: "_blank",
12360
+ rel: "noopener noreferrer",
12361
+ "aria-label": `Open ${title}`,
12362
+ title: "Open document",
12363
+ onClick: (e) => e.stopPropagation(),
12364
+ children: /* @__PURE__ */ jsxRuntime.jsx(DownloadIcon, {})
12365
+ }
12366
+ ) : /* @__PURE__ */ jsxRuntime.jsx(ComingSoonBadge, { children: "Coming Soon" })
12367
+ ]
12368
+ }
12369
+ )
12370
+ },
12371
+ `${title}-${documentUrl || "pending"}`
12372
+ );
12373
+ }) }),
12374
+ /* @__PURE__ */ jsxRuntime.jsx(PreviewPane, { children: activeUrl ? /* @__PURE__ */ jsxRuntime.jsx(
12375
+ PreviewFrame,
12182
12376
  {
12183
- ref: isHighlighted ? highlightRef : void 0,
12184
- $highlighted: isHighlighted,
12185
- children: isAvailable ? /* @__PURE__ */ jsxRuntime.jsxs(DocLink, { href: documentUrl, target: "_blank", rel: "noopener noreferrer", children: [
12186
- /* @__PURE__ */ jsxRuntime.jsx(DocIconWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(DocIcon, {}) }),
12187
- title
12188
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(DocItemDisabled, { children: [
12189
- /* @__PURE__ */ jsxRuntime.jsx(DocIconWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(DocIcon, {}) }),
12190
- title,
12191
- /* @__PURE__ */ jsxRuntime.jsx(ComingSoonBadge, { children: "Coming Soon" })
12192
- ] })
12377
+ src: `${activeUrl}#toolbar=0&navpanes=0&view=FitH`,
12378
+ title: activeTitle ?? "Document preview"
12193
12379
  },
12194
- `${title}-${documentUrl || "pending"}`
12195
- );
12196
- }) })
12380
+ activeUrl
12381
+ ) : /* @__PURE__ */ jsxRuntime.jsx(PreviewEmpty, { children: "Hover a document to preview it here" }) })
12382
+ ] })
12197
12383
  ] });
12198
12384
  }
12199
12385
  var Section2 = styled10__default.default.section`
@@ -12213,45 +12399,103 @@ var SectionHeading = styled10__default.default.h2`
12213
12399
  align-items: center;
12214
12400
  gap: 0.5rem;
12215
12401
  `;
12402
+ var SplitLayout = styled10__default.default.div`
12403
+ display: flex;
12404
+ gap: 1.25rem;
12405
+ align-items: stretch;
12406
+
12407
+ @media (max-width: 768px) {
12408
+ flex-direction: column;
12409
+ }
12410
+ `;
12216
12411
  var DocList = styled10__default.default.ul`
12217
12412
  list-style: none;
12218
12413
  padding: 0;
12219
12414
  margin: 0;
12415
+ flex: 1 1 50%;
12416
+ min-width: 0;
12220
12417
  `;
12221
12418
  var DocItem = styled10__default.default.li`
12222
- padding: 0.75rem 0;
12419
+ padding: 0.35rem 0;
12223
12420
  border-bottom: 1px solid var(--color-border, rgba(255, 255, 255, 0.1));
12224
12421
  border-radius: ${(p) => p.$highlighted ? "6px" : "0"};
12225
12422
  background: ${(p) => p.$highlighted ? "rgba(212, 175, 55, 0.08)" : "transparent"};
12226
- ${(p) => p.$highlighted ? "padding: 0.75rem;" : ""}
12227
12423
  transition: background 0.3s;
12228
12424
 
12229
12425
  &:last-child {
12230
12426
  border-bottom: none;
12231
12427
  }
12232
12428
  `;
12233
- var DocLink = styled10__default.default.a`
12429
+ var DocRow = styled10__default.default.div`
12234
12430
  display: flex;
12235
12431
  align-items: center;
12236
- color: var(--color-text);
12237
- text-decoration: none;
12238
- transition: color 0.2s;
12432
+ gap: 0.5rem;
12433
+ padding: 0.4rem 0.5rem;
12434
+ border-radius: 6px;
12435
+ cursor: ${(p) => p.$available ? "pointer" : "not-allowed"};
12436
+ background: ${(p) => p.$active ? "rgba(230, 200, 126, 0.10)" : "transparent"};
12437
+ transition: background 0.2s, color 0.2s;
12239
12438
 
12240
- &:hover {
12241
- color: var(--color-accent);
12242
- }
12439
+ ${(p) => p.$available && !p.$active ? "&:hover { background: rgba(230, 200, 126, 0.06); }" : ""}
12243
12440
  `;
12244
- var DocItemDisabled = styled10__default.default.div`
12441
+ var DocName = styled10__default.default.span`
12245
12442
  display: flex;
12246
12443
  align-items: center;
12247
- color: var(--color-text-secondary);
12248
- cursor: not-allowed;
12249
- opacity: 0.6;
12444
+ flex: 1;
12445
+ min-width: 0;
12446
+ color: ${(p) => p.$available ? "var(--color-text)" : "var(--color-text-secondary)"};
12447
+ opacity: ${(p) => p.$available ? 1 : 0.6};
12250
12448
  `;
12251
12449
  var DocIconWrapper = styled10__default.default.span`
12252
12450
  margin-right: 0.75rem;
12253
12451
  flex-shrink: 0;
12254
12452
  color: var(--color-text-secondary);
12453
+ display: inline-flex;
12454
+ `;
12455
+ var DownloadBtn = styled10__default.default.a`
12456
+ flex-shrink: 0;
12457
+ display: inline-flex;
12458
+ align-items: center;
12459
+ justify-content: center;
12460
+ width: 30px;
12461
+ height: 30px;
12462
+ border-radius: 6px;
12463
+ color: var(--color-text-secondary);
12464
+ transition: color 0.2s, background 0.2s;
12465
+
12466
+ &:hover {
12467
+ color: var(--color-accent);
12468
+ background: rgba(230, 200, 126, 0.1);
12469
+ }
12470
+ `;
12471
+ var PreviewPane = styled10__default.default.div`
12472
+ flex: 1 1 50%;
12473
+ min-width: 0;
12474
+ min-height: 360px;
12475
+ display: flex;
12476
+ border: 1px solid var(--color-border, rgba(255, 255, 255, 0.1));
12477
+ border-radius: 10px;
12478
+ overflow: hidden;
12479
+ background: rgba(0, 0, 0, 0.25);
12480
+
12481
+ /* No hover on touch devices — fall back to the list + download icon. */
12482
+ @media (max-width: 768px) {
12483
+ display: none;
12484
+ }
12485
+ `;
12486
+ var PreviewFrame = styled10__default.default.iframe`
12487
+ width: 100%;
12488
+ height: 100%;
12489
+ min-height: 360px;
12490
+ border: 0;
12491
+ background: #fff;
12492
+ `;
12493
+ var PreviewEmpty = styled10__default.default.div`
12494
+ margin: auto;
12495
+ padding: 1rem;
12496
+ text-align: center;
12497
+ color: var(--color-text-secondary);
12498
+ font-size: 0.85rem;
12255
12499
  `;
12256
12500
  var ComingSoonBadge = styled10__default.default.span`
12257
12501
  margin-left: auto;
@@ -12263,6 +12507,7 @@ var ComingSoonBadge = styled10__default.default.span`
12263
12507
  font-weight: 500;
12264
12508
  text-transform: uppercase;
12265
12509
  letter-spacing: 0.05em;
12510
+ flex-shrink: 0;
12266
12511
  `;
12267
12512
  var formatIsoDate = (value) => {
12268
12513
  const parsed = new Date(value);
@@ -19900,7 +20145,7 @@ var OpenMailButton = styled10__default.default.a`
19900
20145
  `;
19901
20146
  var ContactPopup = ({ onClose }) => {
19902
20147
  const [copied, setCopied] = React5.useState(false);
19903
- const email = "Gavin@loafmarkets.com";
20148
+ const email = "admin@loafmarkets.com";
19904
20149
  const handleCopy = async () => {
19905
20150
  try {
19906
20151
  await navigator.clipboard.writeText(email);
@@ -20127,7 +20372,17 @@ var SiteFooter = () => {
20127
20372
  /* @__PURE__ */ jsxRuntime.jsx(FooterLinkItem, { children: /* @__PURE__ */ jsxRuntime.jsx(FooterLink, { href: "/trade", children: "Trade" }) }),
20128
20373
  /* @__PURE__ */ jsxRuntime.jsx(FooterLinkItem, { children: /* @__PURE__ */ jsxRuntime.jsx(FooterLink, { href: "/offerings", children: "Initial Offerings" }) }),
20129
20374
  /* @__PURE__ */ jsxRuntime.jsx(FooterLinkItem, { children: /* @__PURE__ */ jsxRuntime.jsx(FooterLink, { href: "/map", children: "Property Map" }) }),
20130
- /* @__PURE__ */ jsxRuntime.jsx(FooterLinkItem, { children: /* @__PURE__ */ jsxRuntime.jsx(FooterLink, { href: "/loaf-liquidity", children: "Loaf Liquidity" }) })
20375
+ /* @__PURE__ */ jsxRuntime.jsx(FooterLinkItem, { children: /* @__PURE__ */ jsxRuntime.jsx(
20376
+ FooterLink,
20377
+ {
20378
+ href: "/loaf-liquidity",
20379
+ onClick: (e) => {
20380
+ e.preventDefault();
20381
+ if (typeof window !== "undefined") window.dispatchEvent(new CustomEvent("loaf:open-liquidity-popup"));
20382
+ },
20383
+ children: "Loaf Liquidity"
20384
+ }
20385
+ ) })
20131
20386
  ] })
20132
20387
  ] }),
20133
20388
  /* @__PURE__ */ jsxRuntime.jsxs(FooterColumn, { children: [
@@ -20163,7 +20418,7 @@ var SiteFooter = () => {
20163
20418
  /* @__PURE__ */ jsxRuntime.jsx(LegalLink, { href: "/cookies", children: "Cookie Policy" })
20164
20419
  ] })
20165
20420
  ] }),
20166
- /* @__PURE__ */ jsxRuntime.jsx(Disclaimer2, { children: /* @__PURE__ */ jsxRuntime.jsx(DisclaimerText, { children: "Warning: Digital asset prices can be volatile. The value of your investment can go down or up and you may not get back the amount invested. Past gains are not indicative of future returns. You are solely responsible for your investment decisions and Loaf is not liable for any losses you may incur. The information here should not be regarded as financial or investment advice. For more information, see our Terms of Use and Risk Warning." }) })
20421
+ /* @__PURE__ */ jsxRuntime.jsx(Disclaimer2, { children: /* @__PURE__ */ jsxRuntime.jsx(DisclaimerText, { children: "Warning: Digital asset prices can be volatile. The value of your investment can go down or up and you may not get back the amount invested. Past gains are not indicative of future returns. You are solely responsible for your investment decisions and Loaf is not liable for any losses you may incur. The information here should not be regarded as financial or investment advice. For more information, see our Terms of Use." }) })
20167
20422
  ] }) }),
20168
20423
  showContactPopup && /* @__PURE__ */ jsxRuntime.jsx(ContactPopup, { onClose: () => setShowContactPopup(false) })
20169
20424
  ] });