// Hotel Walks — Brand components & tokens
// LOCKED design system. Drop this file into any prototype with:
//
//
// Then use:
// window.HW.tokens → colors, fonts, sizing
// window.HW.SmartKey → the mark, optically tuned by size
// window.HW.Lockup → horizontal lockup (mark + wordmark)
// window.HW.LockupStacked → stacked lockup
// window.HW.Wordmark → wordmark only
const HW_TOKENS = {
color: {
ink: "#0d0d0d", // primary — backgrounds, text on light
bone: "#f4eedd", // secondary — backgrounds, text on dark
rule: "rgba(13,13,13,0.12)",
ruleDark: "rgba(244,238,221,0.18)",
muted: "#807a6d",
mutedOnDark: "rgba(244,238,221,0.6)",
},
font: {
serif: "'Spectral', 'Times New Roman', serif", // display — italic only
sans: "'Helvetica Neue', Helvetica, Arial, sans-serif", // UI text
mono: "'JetBrains Mono', ui-monospace, monospace", // caps, labels, metadata
},
// Suggested type ramps (use as starting point, tune per layout)
type: {
displayItalic: { fontFamily: "'Spectral', serif", fontStyle: "italic", fontWeight: 400, letterSpacing: "-0.015em" },
bodyUI: { fontFamily: "'Helvetica Neue', Helvetica, Arial, sans-serif", fontWeight: 400 },
capsLabel: { fontFamily: "'JetBrains Mono', monospace", fontSize: 10, letterSpacing: "0.16em", textTransform: "uppercase" },
},
radius: {
appIcon: 0.235, // multiply by tile size for an iOS-style icon corner
card: 2, // sharp — minimal rounding on cards/buttons
},
};
/* ─────────────────────────────────────────────────────────────
THE MARK — round-bow key inside a disc.
Drawn in a 180-unit viewBox so it scales cleanly.
───────────────────────────────────────────────────────────── */
function HWKeyRound({ stroke = 7, fg }) {
const c = fg || HW_TOKENS.color.bone;
return (
);
}
function HWKeySolid({ size = 16, fg, bg }) {
const F = fg || HW_TOKENS.color.bone;
const B = bg || HW_TOKENS.color.ink;
return (
);
}
/**
* HWSmartKey — the mark, optically sized for the requested px.
* ≥ 96 px : stroke 7 (primary marketing)
* 48–80 px: stroke 9–12 (UI nav, headers)
* 24–32 px: stroke 16 (list rows, badges)
* ≤ 20 px : solid silhouette (favicons, tab icons)
*
* Defaults: bone-on-ink (the primary form).
* Pass { fg, bg } to invert or recolor.
*/
function HWSmartKey({ size = 64, fg, bg }) {
const F = fg || HW_TOKENS.color.bone;
const B = bg || HW_TOKENS.color.ink;
if (size <= 20) return ;
let stroke;
if (size <= 32) stroke = 16;
else if (size <= 48) stroke = 12;
else if (size <= 80) stroke = 9;
else stroke = 7;
return (
);
}
/* ─────────────────────────────────────────────────────────────
LOCKUPS
───────────────────────────────────────────────────────────── */
function HWWordmark({ size = 36, color, italic = true }) {
return (
Hotel Walks
);
}
function HWLockup({ size = 36, dark = false, tagline }) {
// Horizontal: mark + wordmark side-by-side.
// `dark` flips the wordmark + tagline colors so it works on either bg.
const markPx = Math.round(size * 2.2);
const textColor = dark ? HW_TOKENS.color.bone : HW_TOKENS.color.ink;
const mutedColor = dark ? HW_TOKENS.color.mutedOnDark : HW_TOKENS.color.muted;
return (
{tagline && (
{tagline}
)}
);
}
function HWLockupStacked({ size = 30, dark = false }) {
const markPx = Math.round(size * 3.2);
const textColor = dark ? HW_TOKENS.color.bone : HW_TOKENS.color.ink;
return (
);
}
/* ─────────────────────────────────────────────────────────────
Convenience — load Google Fonts once. Call from your page
if not already loaded (e.g. ).
───────────────────────────────────────────────────────────── */
function loadHWFonts() {
if (document.getElementById("hw-fonts")) return;
const link = document.createElement("link");
link.id = "hw-fonts";
link.rel = "stylesheet";
link.href = "https://fonts.googleapis.com/css2?family=Spectral:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&family=JetBrains+Mono:wght@400;500&display=swap";
document.head.appendChild(link);
}
window.HW = {
tokens: HW_TOKENS,
SmartKey: HWSmartKey,
KeyRound: HWKeyRound,
KeySolid: HWKeySolid,
Wordmark: HWWordmark,
Lockup: HWLockup,
LockupStacked: HWLockupStacked,
loadFonts: loadHWFonts,
};