/* Maison Silya — website kit local primitives.
These mirror the system components (Button, Tag, Input, Divider) and
add website chrome (icons, placeholders). Kept kit-local so the kit
renders standalone; production should consume the published library
at window.MaisonSilyaDesignSystem_db0f02. */
const C = (v) => `var(--ms-${v})`;
/* True only on devices with a real hovering pointer (mouse / trackpad).
On touch screens a tap emulates mouseenter and it sticks — which made
rug cards swap to their in-situ photo and zoom in. Hover effects are
gated on this so phones keep the flat, un-zoomed image. */
const MS_CAN_HOVER = !(window.matchMedia && window.matchMedia('(hover: none)').matches);
/* ---- Thin hairline icons (~1.25px stroke, currentColor) ---- */
function Icon({ name, size = 20, style = {} }) {
const p = { fill: 'none', stroke: 'currentColor', strokeWidth: 1.25, strokeLinecap: 'square' };
const paths = {
menu: ,
close: ,
search: ,
account: ,
arrow: ,
chevron: ,
plus: ,
minus: ,
};
return ;
}
/* ---- Button (mirrors system Button) ---- */
function Btn({ children, variant = 'primary', size = 'md', as = 'button', style = {}, ...rest }) {
const sizes = {
sm: { padding: '10px 22px', fontSize: 10, letterSpacing: '0.24em' },
md: { padding: '15px 32px', fontSize: 11, letterSpacing: '0.26em' },
lg: { padding: '19px 44px', fontSize: 12, letterSpacing: '0.28em' },
};
const variants = {
primary: { background: C('ink'), color: C('ivory'), borderColor: C('ink') },
secondary: { background: 'transparent', color: C('ink'), borderColor: C('line-strong') },
ghost: { background: 'transparent', color: C('ink'), borderColor: 'transparent', padding: `${sizes[size].padding.split(' ')[0]} 0` },
inverse: { background: C('ivory'), color: C('ink'), borderColor: C('ivory') },
'ghost-inverse': { background: 'transparent', color: C('ivory'), borderColor: 'transparent', padding: `${sizes[size].padding.split(' ')[0]} 0` },
};
const Tag = as;
const enter = (e) => {
if (variant === 'primary') Object.assign(e.currentTarget.style, { background: C('stone-800'), borderColor: C('stone-800') });
if (variant === 'secondary') e.currentTarget.style.borderColor = C('ink');
if (variant === 'ghost') e.currentTarget.style.color = C('accent');
if (variant === 'ghost-inverse') e.currentTarget.style.opacity = 0.7;
if (variant === 'inverse') Object.assign(e.currentTarget.style, { background: C('champagne'), borderColor: C('champagne') });
};
const leave = (e) => { Object.assign(e.currentTarget.style, { ...variants[variant], opacity: 1 }); };
return (
{children}
);
}
/* ---- Filter tag (mirrors system Tag) ---- */
function FilterTag({ children, selected, onClick }) {
const [h, setH] = React.useState(false);
return (
);
}
/* ---- Underline field (mirrors system Input) ---- */
function Field({ label, type = 'text', placeholder, defaultValue, name, required }) {
const [f, setF] = React.useState(false);
return (
);
}
function Diamond({ size = 5, color = C('accent') }) {
return ;
}
/* ---- Stone placeholder for imagery (no stock photos available) ---- */
function Plate({ ratio = '4 / 5', label = 'Silya', tone = 'stone-200', radius = 'sm', image, children, style = {} }) {
return (
{image &&

}
{!image &&
{label}
}
{children}
);
}
/* ---- Chapter masthead: a monograph-style page opener.
Replaces the bronze-eyebrow + giant-italic formula. A diamond + optional
chapter numeral + section label + hairline, then the title. ---- */
function Chapter({ index, label, title, lede, max = 920 }) {
return (
);
}
Object.assign(window, { Icon, Btn, FilterTag, Field, Diamond, Plate, Chapter, C, MS_CAN_HOVER });