// Shared primitives for the TensorHost marketing site.
// Theme-aware: all colors are CSS tokens defined in the host page.
const TH = { container: 1280 };
// Buttons -------------------------------------------------------------
// primary flips with the theme (ink-on-bg → bg-on-ink). Only placed on
// default-background sections, so --fg / --bg always give correct contrast.
function Button({ kind = 'primary', children, href = '#', onClick, style, accentArrow }) {
const [hover, setHover] = React.useState(false);
const [press, setPress] = React.useState(false);
const base = {
fontFamily: 'inherit', fontSize: 14, letterSpacing: '0.01em',
padding: '13px 22px', borderRadius: 2, textDecoration: 'none',
display: 'inline-flex', alignItems: 'center', gap: 8, cursor: 'pointer',
transition: 'background 140ms cubic-bezier(0.2,0,0,1), border-color 140ms cubic-bezier(0.2,0,0,1), transform 80ms cubic-bezier(0.2,0,0,1)',
transform: press ? 'translateY(1px)' : 'none', whiteSpace: 'nowrap',
};
const variants = {
primary: {
background: press ? 'var(--fg)' : hover ? 'color-mix(in srgb, var(--fg) 68%, var(--bg))' : 'var(--fg)',
color: 'var(--bg)', border: `1px solid ${hover ? 'color-mix(in srgb, var(--fg) 68%, var(--bg))' : 'var(--fg)'}`,
},
secondary: {
background: press ? 'var(--bg-alt)' : hover ? 'var(--surface-2)' : 'transparent', color: 'var(--fg)',
border: `1px solid ${hover ? 'var(--fg)' : 'var(--rule)'}`,
},
ghost: { background: 'transparent', color: 'var(--fg)', border: '1px solid transparent', padding: '13px 6px' },
};
return (
setHover(true)} onMouseLeave={() => { setHover(false); setPress(false); }}
onMouseDown={() => setPress(true)} onMouseUp={() => setPress(false)}>
{children}
{accentArrow && →}
);
}
// Eyebrow with a monospace index in accent ---------------------------
// `dark` = sits on an always-inverted island (uses inverted tokens).
function Eyebrow({ index, children, dark }) {
return (
{index != null && {index}}
{children}
);
}
// Section wrapper with a CSS-only entrance (resting state always visible).
function Section({ id, dark, children, style, pad = 96 }) {
return (
);
}
// A live status dot — accent fill when online ------------------------
function StatusDot({ state = 'online' }) {
const map = {
online: { ch: '●', color: 'var(--accent)' },
degraded: { ch: '◐', color: 'var(--fg-4)' },
offline: { ch: '○', color: 'var(--fg-4)' },
error: { ch: '×', color: 'var(--fg)' },
};
const m = map[state] || map.online;
return {m.ch};
}
Object.assign(window, { TH, Button, Eyebrow, Section, StatusDot });