// hf-kit.jsx — Wiggleverse ecomm HI-FI primitives (Direction A · Quiet centered).
// Depth = layered surfaces + hairlines (the brand avoids shadows). Hover = 1–3px lift.
// Merchant persona: Ben's Bets · ben@bensbets.com
const HFDS = window.WiggleverseDesignSystem_94cd80;
const { Button: HFButton, Soul: HFSoul, Eyebrow: HFEyebrow, Tag: HFTag } = HFDS;
// Resolve a brand asset: blob URL when bundled offline (window.__resources), else relative path.
const HF_ASSET = (id, path) => (window.__resources && window.__resources[id]) || path;
window.HF_ASSET = HF_ASSET;
// ---- token shorthands ----------------------------------------------------
const H = {
sky: 'var(--wv-midnight)', night: 'var(--wv-night)',
raised: 'var(--wv-indigo)', raisedHi: 'var(--wv-indigo-2)',
star: 'var(--wv-starlight)', soft: 'var(--wv-starlight-78)',
mute: 'var(--wv-starlight-60)', faint: 'var(--wv-starlight-55)',
lilac: 'var(--wv-lilac)', violet: 'var(--wv-violet)',
gold: 'var(--wv-gold)', goldHi: 'var(--wv-gold-hi)', goldInk: 'var(--wv-gold-ink)',
hair: 'var(--border-soft)', hairCard: 'var(--border-card)', hairStrong: 'var(--border-strong)',
disp: 'var(--wv-font-display)', body: 'var(--wv-font-body)', soul: 'var(--wv-font-human)',
shadow: 'var(--shadow-soft)',
};
const MENU_EMAIL = 'ben@bensbets.com';
const STORE = "Ben's Bets";
// barely-there starfield (Direction A: restrained) — a few asymmetric nodes
const HF_STARS =
'radial-gradient(1.3px 1.3px at 16% 22%, rgba(237,234,255,.34), transparent),' +
'radial-gradient(1.2px 1.2px at 78% 14%, rgba(237,234,255,.22), transparent),' +
'radial-gradient(1.1px 1.1px at 88% 46%, rgba(155,140,255,.30), transparent),' +
'radial-gradient(1.3px 1.3px at 30% 72%, rgba(237,234,255,.24), transparent),' +
'radial-gradient(1.1px 1.1px at 62% 86%, rgba(237,234,255,.18), transparent),' +
'radial-gradient(1.2px 1.2px at 7% 56%, rgba(155,140,255,.26), transparent)';
// gold horizon — the brand's warmth, a low glow at the bottom of the sky
const HF_HORIZON = 'radial-gradient(120% 70% at 50% 142%, rgba(244,199,107,.16) 0%, rgba(244,199,107,.05) 38%, transparent 64%)';
// One-time injected stylesheet: hover + focus affordances (subtle motion only).
function HFStyles() {
return (
);
}
// ── Screen ground ──────────────────────────────────────────────────────────
function HFScreen({ children, horizon = false, stars = true, bg = H.sky, style = {} }) {
const layers = [];
if (stars) layers.push(HF_STARS);
if (horizon) layers.unshift(HF_HORIZON);
const background = layers.length ? `${layers.join(',')}, ${bg}` : bg;
return (
{children}
);
}
// ── Wordmark — mark tile + "ecomm" in Space Grotesk ───────────────────────
function HFWordmark({ size = 26, sub = false }) {
return (
ecomm
{sub && by Wiggleverse }
);
}
// ── TopBar — glass chrome ──────────────────────────────────────────────────
function HFTopBar({ left, right, pad = '0 36px', height = 68 }) {
return (
);
}
function HFAccountChip({ email = MENU_EMAIL, menu = false }) {
return (
B
{email}
Sign out
{menu && (
Account settings
Sign out
)}
);
}
// ── Field ──────────────────────────────────────────────────────────────────
function HFField({ label, placeholder, value, helper, error, focus = false, optional = false, hint }) {
const cls = `field${focus ? ' is-focus' : ''}${error ? ' is-attn' : ''}`;
return (
{label}
{optional && optional }
{value || placeholder}
{focus && !value && }
{hint && {hint} }
{error &&
{error} }
{helper && !error &&
{helper} }
);
}
function HFNote({ children, tone }) {
return
{tone === 'attn' && ◆ }
{children}
;
}
// ── CodeField — 6 cells ─────────────────────────────────────────────────────
function HFCodeField({ filled = 0, error = false, vals = ['4', '1', '9', '2', '0', '4'] }) {
return (
{[0, 1, 2, 3, 4, 5].map((i) => {
const active = i === filled && !error;
const has = i < filled;
return (
{has ? vals[i] : (active ? : '')}
);
})}
);
}
// ── Banner — gold attention / lilac info (no red in palette) ───────────────
function HFBanner({ children, tone = 'attn', title }) {
const attn = tone === 'attn';
return (
{attn ? '◆' : '◇'}
{title &&
{title}
}
{children}
);
}
// ── AuthCard — the one surface that earns a real shadow ────────────────────
function HFAuthCard({ children, width = 440 }) {
return (
{children}
);
}
// ── Primary action wrapper (DS Button, full-width option) ──────────────────
function HFPrimary({ children, full = true, disabled = false }) {
return (
{children}
);
}
// ── Footer ──────────────────────────────────────────────────────────────────
function HFFooter({ pad = '20px 36px' }) {
return (
);
}
// ── Heading helper ───────────────────────────────────────────────────────────
function HFHeading({ children, sub, size = 27 }) {
return (
{children}
{sub &&
{sub}
}
);
}
const hfHonest = { fontFamily: H.body, fontSize: 13, color: H.mute, lineHeight: 1.5, margin: 0 };
// ── StateCard — frames a single state in the states stacks ─────────────────
function HFStateCard({ label, note, children }) {
return (
{label}
{note && {note} }
{children}
);
}
function HFStates({ children }) {
return {children}
;
}
Object.assign(window, {
HF_H: H, HF_STARS, HF_HORIZON, HF_STORE: STORE, HF_EMAIL: MENU_EMAIL, HF_DSC: HFDS,
HFStyles, HFScreen, HFWordmark, HFTopBar, HFAccountChip, HFField, HFNote, HFCodeField,
HFBanner, HFAuthCard, HFPrimary, HFFooter, HFHeading, HFStateCard, HFStates,
hfHonest,
});