// Kafana — shared primitives. Lives on window for use across babel scripts.
// Wordmark — New York serif
function Wordmark({ size = 22, color }) {
return (
Kafana
);
}
// SF-Symbol-style line icons (1.5px stroke, rounded). Hand-tuned, not from a pack.
function Icon({ name, size = 20, color = 'currentColor', strokeWidth = 1.5 }) {
const common = {
width: size, height: size, viewBox: '0 0 24 24',
fill: 'none', stroke: color, strokeWidth, strokeLinecap: 'round', strokeLinejoin: 'round',
};
switch (name) {
case 'glass':
// tulip glass
return (
);
case 'book':
return (
);
case 'passport':
return (
);
case 'camera':
return (
);
case 'pin':
return (
);
case 'star':
return (
);
case 'plus':
return (
);
case 'arrow':
return (
);
case 'check':
return (
);
case 'fruit':
// simple plum
return (
);
case 'still':
// alembic / copper still silhouette
return (
);
case 'globe':
return (
);
default:
return null;
}
}
// Status bar for phone screens
function StatusBar({ time = '20:14', dark = false }) {
const fg = dark ? 'var(--d-text)' : 'var(--ink)';
return (
{time}
{/* signal */}
{/* battery */}
);
}
// Small coral/copper underline used to mark the active nav link state — ONE per viewport
function CopperRule({ width = 18 }) {
return ;
}
// Country list (Latin / Cyrillic). `id` matches BALKAN_PATHS.
const COUNTRIES = [
{ id: 'rs', latin: 'Serbia', cyr: 'Србија' },
{ id: 'hr', latin: 'Croatia', cyr: 'Hrvatska', latinOnly: true },
{ id: 'ba', latin: 'Bosnia and Herzegovina', cyr: 'Босна и Херцеговина' },
{ id: 'me', latin: 'Montenegro', cyr: 'Crna Gora', latinOnly: true },
{ id: 'mk', latin: 'North Macedonia', cyr: 'Северна Македонија' },
{ id: 'al', latin: 'Albania', cyr: 'Shqipëria', latinOnly: true },
{ id: 'si', latin: 'Slovenia', cyr: 'Slovenija', latinOnly: true },
{ id: 'bg', latin: 'Bulgaria', cyr: 'България' },
{ id: 'ro', latin: 'Romania', cyr: 'România', latinOnly: true },
{ id: 'xk', latin: 'Kosovo', cyr: 'Kosovë', latinOnly: true },
];
// 12 fruits + spirits, alphabetical (Latin/Bosnian-Serbian-Croatian).
// `file` is the SVG icon basename in /assets/fruits.
const FRUITS = [
{ latin: 'Dunja', en: 'Quince', file: 'dunja' },
{ latin: 'Jabuka', en: 'Apple', file: 'jabuka' },
{ latin: 'Kajsija', en: 'Apricot', file: 'kajsija' },
{ latin: 'Kruška', en: 'Pear', file: 'kruska' },
{ latin: 'Loza', en: 'Grape', file: 'loza' },
{ latin: 'Malina', en: 'Raspberry', file: 'malina' },
{ latin: 'Medovača', en: 'Honey', file: 'medovaca' },
{ latin: 'Orah', en: 'Walnut', file: 'orah' },
{ latin: 'Šljiva', en: 'Plum', file: 'sljiva' },
{ latin: 'Smokva', en: 'Fig', file: 'smokva' },
{ latin: 'Travarica', en: 'Herb', file: 'travarica' },
{ latin: 'Višnja', en: 'Sour cherry', file: 'visnja' },
];
// Geographically accurate Balkan map. Country paths baked at build time from
// world-atlas Natural Earth 50m (see balkan-paths.js), projected equirectangular
// with cos(midLat) correction onto a 320×260 viewBox.
function BalkanMap({ width = 280, visited = ['rs', 'ba', 'me', 'hr', 'mk'], dark = false }) {
const stroke = dark ? 'var(--d-whisper)' : 'var(--whisper)';
const visitedFill = 'var(--copper)';
const baseFill = dark ? '#2C2924' : 'var(--honey-light)';
const labelColor = dark ? 'var(--d-smoke)' : 'var(--smoke)';
// Render order matters — large containers first so visited fills sit on top.
return (
);
}
// CountryMark — a tiny Balkans map highlighting just one country in copper.
// Uses the same baked geographic paths as BalkanMap. Shape variation per
// country gives each its own visual fingerprint.
function CountryMark({ id, size = 80, dark = false }) {
const stroke = dark ? 'var(--d-whisper)' : 'var(--whisper)';
const muted = dark ? 'rgba(241,239,232,0.10)' : 'rgba(74,27,12,0.10)';
const visited = 'var(--copper)';
const vb = window.BALKAN_VB || '0 0 320 260';
return (
);
}
// Inline-replaced above; legacy stub removed.
Object.assign(window, { Wordmark, Icon, StatusBar, CopperRule, COUNTRIES, FRUITS, BalkanMap, CountryMark });