<!doctype html>
<html lang=”en”>
<head>
<meta charset=”utf-8″ />
<meta name=”viewport” content=”width=device-width,initial-scale=1″ />
<title>Bar Name Finder</title>
<style>
:root{
–bg:#0b0b0b;
–panel:#101010;
–panel2:#0f0f0f;
–text:#f5f5f5;
–muted:#b8b8b8;
–line:#222;
–accent:#fff;
–shadow: 0 12px 40px rgba(0,0,0,.45);
–radius: 18px;
–radius2: 14px;
–pad: 20px;
}
*{box-sizing:border-box}
body{
margin:0;
font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, “Apple Color Emoji”,”Segoe UI Emoji”;
background: radial-gradient(1200px 800px at 20% 0%, #151515 0%, var(–bg) 55%, #070707 100%);
color:var(–text);
min-height:100vh;
display:flex;
align-items:center;
justify-content:center;
padding:28px 16px;
}
.wrap{
width:min(920px, 100%);
}
header{
display:flex;
align-items:flex-end;
justify-content:space-between;
gap:16px;
margin-bottom:14px;
}
.brand{
display:flex;
flex-direction:column;
gap:6px;
}
.brand h1{
margin:0;
font-size:24px;
letter-spacing:.02em;
font-weight:650;
}
.brand p{
margin:0;
color:var(–muted);
font-size:14px;
line-height:1.35;
max-width:52ch;
}
.pill{
border:1px solid var(–line);
background:rgba(255,255,255,0.03);
padding:10px 12px;
border-radius:999px;
font-size:13px;
color:var(–muted);
white-space:nowrap;
display:flex;
gap:10px;
align-items:center;
}
.dot{
width:8px;height:8px;border-radius:50%;
background:#fff;
opacity:.85;
}
.card{
background: linear-gradient(180deg, rgba(255,255,255,.03), rgba(255,255,255,.01));
border:1px solid var(–line);
border-radius:var(–radius);
box-shadow: var(–shadow);
overflow:hidden;
}
.topbar{
padding:14px var(–pad);
border-bottom:1px solid var(–line);
display:flex;
align-items:center;
justify-content:space-between;
gap:14px;
background: rgba(0,0,0,.25);
}
.progress{
width:100%;
height:10px;
border-radius:999px;
background:#0d0d0d;
border:1px solid var(–line);
overflow:hidden;
position:relative;
}
.progress > div{
height:100%;
width:0%;
background: linear-gradient(90deg, rgba(255,255,255,.9), rgba(255,255,255,.55));
border-radius:999px;
transition:width .28s ease;
}
.counter{
color:var(–muted);
font-size:13px;
min-width:120px;
text-align:right;
}
main{
padding: 18px var(–pad) 20px;
}
.qTitle{
font-size:18px;
font-weight:650;
letter-spacing:.01em;
margin:0 0 6px 0;
}
.qHelp{
margin:0 0 14px 0;
color:var(–muted);
font-size:13px;
line-height:1.5;
}
.choices{
display:grid;
grid-template-columns: repeat(2, minmax(0,1fr));
gap:12px;
}
@media (max-width:720px){
.choices{ grid-template-columns: 1fr; }
.counter{ min-width:auto; }
header{ flex-direction:column; align-items:flex-start; }
}
.choice{
border:1px solid var(–line);
background: rgba(255,255,255,0.02);
padding:14px 14px;
border-radius: var(–radius2);
display:flex;
gap:12px;
align-items:flex-start;
cursor:pointer;
user-select:none;
transition: transform .08s ease, border-color .18s ease, background .18s ease;
position:relative;
min-height:56px;
}
.choice:hover{
border-color:#343434;
transform: translateY(-1px);
}
.choice[aria-checked=”true”]{
border-color: rgba(255,255,255,.75);
background: rgba(255,255,255,0.06);
}
.checkbox{
width:18px;
height:18px;
border-radius:5px;
border:1px solid #3b3b3b;
margin-top:2px;
flex:0 0 auto;
display:grid;
place-items:center;
background: rgba(0,0,0,.35);
}
.choice[aria-checked=”true”] .checkbox{
border-color: rgba(255,255,255,.85);
background: rgba(255,255,255,.08);
}
.checkmark{
width:10px;
height:10px;
border-radius:3px;
background:#fff;
opacity:0;
transform: scale(.85);
transition: opacity .12s ease, transform .12s ease;
}
.choice[aria-checked=”true”] .checkmark{
opacity:1;
transform: scale(1);
}
.label{
display:flex;
flex-direction:column;
gap:4px;
min-width:0;
}
.label strong{
font-size:14px;
font-weight:650;
letter-spacing:.01em;
}
.label span{
font-size:12.5px;
color:var(–muted);
line-height:1.35;
}
.footer{
padding: 14px var(–pad);
border-top:1px solid var(–line);
display:flex;
justify-content:space-between;
align-items:center;
gap:12px;
background: rgba(0,0,0,.22);
}
.leftMeta{
display:flex;
flex-direction:column;
gap:4px;
color:var(–muted);
font-size:12.5px;
line-height:1.35;
}
.buttons{
display:flex;
gap:10px;
align-items:center;
flex-wrap:wrap;
justify-content:flex-end;
}
button{
appearance:none;
border:1px solid var(–line);
background: rgba(255,255,255,0.03);
color:var(–text);
padding:10px 12px;
border-radius: 12px;
cursor:pointer;
font-weight:620;
letter-spacing:.01em;
transition: background .16s ease, border-color .16s ease, transform .08s ease;
display:flex;
gap:8px;
align-items:center;
}
button:hover{
background: rgba(255,255,255,0.06);
border-color:#343434;
transform: translateY(-1px);
}
button:disabled{
opacity:.5;
cursor:not-allowed;
transform:none;
}
.primary{
border-color: rgba(255,255,255,.55);
background: rgba(255,255,255,.10);
}
.primary:hover{
background: rgba(255,255,255,.14);
border-color: rgba(255,255,255,.80);
}
.note{
color:var(–muted);
font-size:12px;
margin-top:12px;
line-height:1.45;
}
/* Results */
.results{
display:grid;
gap:14px;
}
.resultTop{
display:flex;
flex-direction:column;
gap:8px;
}
.resultTop h2{
margin:0;
font-size:20px;
font-weight:700;
letter-spacing:.01em;
}
.resultTop p{
margin:0;
color:var(–muted);
line-height:1.45;
font-size:13.5px;
max-width:70ch;
}
.names{
display:grid;
grid-template-columns: repeat(3, minmax(0,1fr));
gap:12px;
margin-top:4px;
}
@media (max-width:720px){
.names{ grid-template-columns: 1fr; }
}
.nameCard{
border:1px solid var(–line);
border-radius:var(–radius2);
background: rgba(255,255,255,0.02);
padding:14px;
display:flex;
flex-direction:column;
gap:8px;
}
.nameCard .name{
font-size:16px;
font-weight:750;
letter-spacing:.01em;
}
.bar{
height:8px;
border-radius:999px;
background:#0d0d0d;
border:1px solid var(–line);
overflow:hidden;
}
.bar > div{
height:100%;
width:0%;
background: linear-gradient(90deg, rgba(255,255,255,.9), rgba(255,255,255,.55));
}
.nameCard .desc{
color:var(–muted);
font-size:12.5px;
line-height:1.4;
min-height:2.6em;
}
.tagRow{
display:flex;
gap:8px;
flex-wrap:wrap;
}
.tag{
font-size:11.5px;
color:var(–muted);
border:1px solid var(–line);
background: rgba(255,255,255,0.03);
padding:6px 8px;
border-radius:999px;
white-space:nowrap;
}
.kbd{
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, “Liberation Mono”, “Courier New”, monospace;
font-size:11px;
padding:2px 6px;
border:1px solid var(–line);
border-bottom-color:#111;
border-radius:8px;
background: rgba(255,255,255,0.02);
color:var(–muted);
}
</style>
</head>
<body>
<div class=”wrap”>
<header>
<div class=”brand”>
<h1>Bar Name Finder</h1>
<p>Pick up to <strong>3</strong> answers per question. Your results are calculated from the pattern of choices—not a single selection.</p>
</div>
<div class=”pill” title=”Modern black & white UI”>
<span class=”dot”></span>
<span>Modern • Black & White</span>
</div>
</header>

<section class=”card” aria-live=”polite”>
<div class=”topbar”>
<div class=”progress” aria-label=”Progress”>
<div id=”progressFill”></div>
</div>
<div class=”counter” id=”counter”>Question 1 of 20</div>
</div>

<main id=”main”></main>

<div class=”footer”>
<div class=”leftMeta” id=”leftMeta”>
<div><span class=”kbd”>Tip</span> Click up to 3 options, then press <strong>Next</strong>.</div>
<div id=”selectionMeta”>0 / 3 selected</div>
</div>
<div class=”buttons”>
<button id=”backBtn” type=”button”>Back</button>
<button id=”resetBtn” type=”button”>Reset</button>
<button id=”nextBtn” class=”primary” type=”button” disabled>Next</button>
</div>
</div>
</section>
</div>

<script>
/**
* HOW TO CUSTOMIZE:
* 1) Update QUESTIONS text/options below.
* 2) Update NAME_WEIGHTS and NAME_PROFILES to tune results.
* Scoring is transparent & editable.
*/

// ———- Questions (the “test above”) ———-
const QUESTIONS = [
{
id: “room_energy”,
title: “When he walks into a room, does the energy…”,
help: “Choose up to 3. Go with instinct.”,
options: [
{ id:”rise”, label:”Rise”, desc:”Attention lifts; focus intensifies.” },
{ id:”settle”, label:”Settle”, desc:”The room calms; people feel anchored.” },
{ id:”focus”, label:”Focus”, desc:”Eyes lock in; clarity sharpens.” },
{ id:”soften”, label:”Soften”, desc:”Edges smooth; warmth spreads.” }
]
},
{
id: “power_style”,
title: “Is his power…”,
help: “Pick what fits most often.”,
options: [
{ id:”quiet”, label:”Quiet”, desc:”Low volume, high gravity.” },
{ id:”intense”, label:”Intense”, desc:”High heat, high charge.” },
{ id:”playful”, label:”Playful”, desc:”Light, mischievous, teasing.” },
{ id:”controlled”, label:”Controlled”, desc:”Measured, deliberate, precise.” },
{ id:”magnetic”, label:”Magnetic”, desc:”Draws people in effortlessly.” }
]
},
{
id: “command_channel”,
title: “Does he command through…”,
help: “Select what people respond to most.”,
options: [
{ id:”presence”, label:”Presence”, desc:”He fills space without trying.” },
{ id:”voice”, label:”Voice”, desc:”Tone and cadence carry authority.” },
{ id:”touch”, label:”Touch”, desc:”Physical certainty, grounded contact.” },
{ id:”eye_contact”, label:”Eye contact”, desc:”Locks attention; controls tempo.” },
{ id:”wit”, label:”Wit”, desc:”Sharp mind; effortless control.” }
]
},
{
id: “identity”,
title: “Does he identify primarily as…”,
help: “Choose up to 3 if he spans roles.”,
options: [
{ id:”dom”, label:”Dominant”, desc:”Leads, structures, directs.” },
{ id:”sub”, label:”Submissive”, desc:”Surrenders, serves, trusts.” },
{ id:”switch”, label:”Switch”, desc:”Moves fluidly between roles.” },
{ id:”service”, label:”Service-oriented”, desc:”Care, duty, devotion.” },
{ id:”protector”, label:”Protector”, desc:”Guards the space and the people.” },
{ id:”trickster”, label:”Trickster”, desc:”Playful disruption; charming edge.” }
]
},
{
id: “style_in_dynamic”,
title: “In power exchange, is he more…”,
help: “What’s the dominant flavor?”,
options: [
{ id:”structured”, label:”Structured & protocol-driven”, desc:”Rules, standards, ritual.” },
{ id:”instinctual”, label:”Instinctual & intuitive”, desc:”Reads the moment.” },
{ id:”mischievous”, label:”Playful & mischievous”, desc:”Teasing, testing, games.” },
{ id:”devotional”, label:”Devotional”, desc:”Bonded, loyal, committed.” },
{ id:”strategic”, label:”Strategic”, desc:”Plans, anticipates, positions.” }
]
},
{
id: “preference”,
title: “Does he prefer to…”,
help: “How he moves socially.”,
options: [
{ id:”lead”, label:”Lead”, desc:”Sets direction; holds the frame.” },
{ id:”support”, label:”Support”, desc:”Strength behind the scenes.” },
{ id:”challenge”, label:”Challenge”, desc:”Tests truth; sharpens people.” },
{ id:”nurture”, label:”Nurture”, desc:”Soft power; steady care.” },
{ id:”observe”, label:”Observe”, desc:”Quiet assessment; decisive later.” }
]
},
{
id: “how_people_experience”,
title: “People experience him as…”,
help: “Pick what’s most consistently true.”,
options: [
{ id:”intimidating”, label:”Intimidating”, desc:”Edge, bite, command.” },
{ id:”safe”, label:”Safe”, desc:”Protected, steady, held.” },
{ id:”sexy”, label:”Sexy”, desc:”Heat, allure, pull.” },
{ id:”intelligent”, label:”Intelligent”, desc:”Smart, sharp, discerning.” },
{ id:”warm”, label:”Warm”, desc:”Approachable, human, kind.” },
{ id:”mysterious”, label:”Mysterious”, desc:”Hard to read; compelling.” }
]
},
{
id: “anger_mode”,
title: “When he is angry, does he become…”,
help: “Select up to 3 if it depends on context.”,
options: [
{ id:”ang_quiet”, label:”Quiet”, desc:”Tight focus; calm intensity.” },
{ id:”ang_sharp”, label:”Sharp”, desc:”Cuts clean; direct.” },
{ id:”ang_cold”, label:”Cold”, desc:”Detached; controlled distance.” },
{ id:”ang_explosive”, label:”Explosive”, desc:”Eruption; storm.” },
{ id:”ang_controlled”, label:”Controlled”, desc:”Contained force; measured.” }
]
},
{
id: “affection_mode”,
title: “When he is affectionate, is he…”,
help: “Pick what feels most like him.”,
options: [
{ id:”aff_protective”, label:”Protective”, desc:”Covering, guarding, holding.” },
{ id:”aff_soft”, label:”Soft”, desc:”Gentle, tender.” },
{ id:”aff_physical”, label:”Physical”, desc:”Touch-forward; embodied.” },
{ id:”aff_teasing”, label:”Teasing”, desc:”Playful affection.” },
{ id:”aff_devoted”, label:”Devoted”, desc:”Steady loyalty; unwavering.” }
]
},
{
id: “aesthetic”,
title: “His leather style is…”,
help: “What people would say at a glance.”,
options: [
{ id:”classic”, label:”Classic old guard”, desc:”Traditional, timeless.” },
{ id:”modern”, label:”Sleek modern”, desc:”Clean lines; minimal excess.” },
{ id:”raw”, label:”Rough and raw”, desc:”Edge, grit, texture.” },
{ id:”minimal”, label:”Minimal”, desc:”Sparse; intentional.” },
{ id:”detailed”, label:”Decorative and detailed”, desc:”Ornate; expressive.” }
]
},
{
id: “gear_pref”,
title: “Does he prefer…”,
help: “Choose the closest match.”,
options: [
{ id:”boots_jacket”, label:”Boots & jacket”, desc:”Classic leather iconography.” },
{ id:”harness_min”, label:”Harness & minimal”, desc:”Show the frame; lean.” },
{ id:”full_formal”, label:”Full formal leather”, desc:”Uniform-level presence.” },
{ id:”pup_gear”, label:”Pup gear”, desc:”Play, pack energy.” },
{ id:”unexpected”, label:”Something unexpected”, desc:”Surprising signature.” }
]
},
{
id: “vibe”,
title: “His vibe is closer to…”,
help: “Pick the archetype that lands.”,
options: [
{ id:”military”, label:”Military”, desc:”Order; command; bearing.” },
{ id:”viking”, label:”Viking”, desc:”Mythic strength; wild honor.” },
{ id:”professor”, label:”Professor”, desc:”Intellect; calm authority.” },
{ id:”cowboy”, label:”Cowboy”, desc:”Frontier; grit; independence.” },
{ id:”urban_strategist”, label:”Urban strategist”, desc:”Modern power; chess mind.” },
{ id:”rogue”, label:”Rogue”, desc:”Edge; charm; unpredictability.” }
]
},
{
id: “what_leather_gives”,
title: “What does leather give him most?”,
help: “Pick what feels true in his body.”,
options: [
{ id:”structure”, label:”Structure”, desc:”Container; discipline; order.” },
{ id:”freedom”, label:”Freedom”, desc:”Release; expansion.” },
{ id:”belonging”, label:”Belonging”, desc:”Brotherhood; tribe.” },
{ id:”devotion”, label:”Devotion”, desc:”Bond; loyalty.” },
{ id:”authority”, label:”Authority”, desc:”Leadership; responsibility.” },
{ id:”play”, label:”Play”, desc:”Joy; experimentation.” }
]
},
{
id: “name_feel”,
title: “Do you want his name to feel…”,
help: “Choose up to 3 if needed.”,
options: [
{ id:”hard”, label:”Hard”, desc:”Blunt, unyielding.” },
{ id:”smooth”, label:”Smooth”, desc:”Polished, seductive.” },
{ id:”ancient”, label:”Ancient”, desc:”Old-world, timeless.” },
{ id:”sharp”, label:”Sharp”, desc:”Cutting, precise.” },
{ id:”grounded”, label:”Grounded”, desc:”Stable, rooted.” },
{ id:”dark”, label:”Dark”, desc:”Shadow, mystery, edge.” }
]
},
{
id: “known_as”,
title: “Would he rather be known as…”,
help: “Pick the narrative role.”,
options: [
{ id:”force”, label:”A force”, desc:”Impact; presence; inevitability.” },
{ id:”steady_presence”, label:”A steady presence”, desc:”Anchor; reliability.” },
{ id:”spark”, label:”A spark”, desc:”Ignition; inspiration.” },
{ id:”guide”, label:”A guide”, desc:”Mentor; teacher.” },
{ id:”protector2″, label:”A protector”, desc:”Guardian; shield.” },
{ id:”mystery”, label:”A mystery”, desc:”Intrigue; depth.” }
]
},
{
id: “marriage_role”,
title: “In your relationship dynamic, does he…”,
help: “Select what’s most accurate.”,
options: [
{ id:”anchor”, label:”Anchor you”, desc:”Stabilizes; holds.” },
{ id:”ignite”, label:”Ignite you”, desc:”Turns up heat; activates.” },
{ id:”challenge2″, label:”Challenge you”, desc:”Pushes growth.” },
{ id:”soften2″, label:”Soften you”, desc:”Brings gentleness.” },
{ id:”center”, label:”Center you”, desc:”Aligns; grounds.” }
]
},
{
id: “one_word”,
title: “When you think of him in leather space, what single word comes to mind?”,
help: “Pick the closest single-word energy.”,
options: [
{ id:”power”, label:”Power”, desc:”Commanding force.” },
{ id:”gravity”, label:”Gravity”, desc:”Weight; inevitability.” },
{ id:”presence2″, label:”Presence”, desc:”You feel him before he speaks.” },
{ id:”fire”, label:”Fire”, desc:”Heat; intensity.” },
{ id:”steel”, label:”Steel”, desc:”Edge; resilience.” },
{ id:”mercy”, label:”Mercy”, desc:”Strength with care.” }
]
},
{
id: “animal”,
title: “What animal energy fits him most?”,
help: “Choose the closest.”,
options: [
{ id:”lion”, label:”Lion”, desc:”Royal authority; protector.” },
{ id:”wolf”, label:”Wolf”, desc:”Pack leader; instinct.” },
{ id:”panther”, label:”Panther”, desc:”Silent, lethal elegance.” },
{ id:”bull”, label:”Bull”, desc:”Power; stamina.” },
{ id:”hawk”, label:”Hawk”, desc:”Precision; watchfulness.” },
{ id:”bear”, label:”Bear”, desc:”Warm strength; solidity.” }
]
},
{
id: “element”,
title: “What element fits him most?”,
help: “Pick one or up to 3 if it’s mixed.”,
options: [
{ id:”fire2″, label:”Fire”, desc:”Heat; drive.” },
{ id:”water”, label:”Water”, desc:”Depth; inevitability; pull.” },
{ id:”earth”, label:”Earth”, desc:”Grounding; stability.” },
{ id:”air”, label:”Air”, desc:”Mind; movement.” },
{ id:”metal”, label:”Metal”, desc:”Edge; structure.” }
]
},
{
id: “name_goal”,
title: “Does he want a name that…”,
help: “Choose the outcome of the name.”,
options: [
{ id:”commands”, label:”Commands”, desc:”Instant authority.” },
{ id:”intrigues”, label:”Intrigues”, desc:”Curiosity; pull.” },
{ id:”grounds”, label:”Grounds”, desc:”Stability; calm.” },
{ id:”seduces”, label:”Seduces”, desc:”Heat; allure.” },
{ id:”protects”, label:”Protects”, desc:”Guardian energy.” }
]
}
];

// ———- Name scoring model ———-
// Each answer contributes points to some names.
// Tune this to your culture/house style as needed.
const NAME_WEIGHTS = {
// Commanding, ancient, magnetic, strategist, seductive
cassian: {
rise:2, magnetic:3, eye_contact:3, dom:2, protector:2, strategic:3, lead:2,
warm:1, intelligent:2, ang_sharp:2, ang_controlled:2, modern:2, full_formal:2,
urban_strategist:3, rogue:2, authority:2, freedom:1, ancient:3, grounded:2,
force:2, power:2, lion:1, water:2, commands:2, seduces:3, intrigues:1, metal:1
},
// Imperial, force, classic dominance
magnus: {
rise:3, intense:2, magnetic:2, presence:2, eye_contact:1, dom:3, protector:2,
structured:2, strategic:2, lead:3, intimidating:2, intelligent:1, ang_sharp:1,
classic:1, full_formal:2, military:1, viking:1, authority:3, ancient:2, grounded:2,
force:3, gravity:2, power:2, lion:2, bull:1, metal:2, commands:3
},
// Lion-coded, sleek and relatable
leon: {
rise:2, magnetic:2, eye_contact:2, dom:2, protector:2, strategic:1, lead:2,
warm:1, sexy:2, ang_sharp:1, modern:2, minimal:1, full_formal:1, urban_strategist:2,
authority:2, freedom:1, ancient:2, grounded:1, force:2, power:2, lion:4, commands:2, seduces:2
},
// Urban empire / structure
roman: {
focus:2, controlled:2, presence:2, dom:2, structured:3, strategic:2, lead:2,
intelligent:2, ang_controlled:2, classic:1, full_formal:2, military:2, urban_strategist:2,
structure:2, authority:3, ancient:3, grounded:2, force:2, steel:1, metal:1, commands:2
},
// Regal, deep, seductive, water undertone
darius: {
rise:2, magnetic:2, eye_contact:1, dom:2, protector:1, strategic:2, lead:2,
mysterious:2, sexy:2, ang_controlled:1, modern:1, full_formal:1,
authority:2, freedom:1, ancient:3, grounded:2, force:1, power:1, water:3, lion:1,
intrigues:2, seduces:2
},
// Rogue strategist edge
rourke: {
rise:2, intense:1, magnetic:1, wit:2, eye_contact:1, dom:2, strategic:2,
challenge:2, rogue:3, urban_strategist:2, ang_sharp:2, ang_explosive:1,
modern:2, minimal:1, dark:2, force:2, power:1, intrigues:2, seduces:1
},
// Short, hard, high command
titus: {
rise:2, controlled:2, voice:1, presence:1, dom:3, structured:2, lead:2,
intimidating:2, military:2, full_formal:2, authority:3, ancient:3, hard:2, metal:1,
force:2, commands:3
}
};

// Friendly descriptions/tags for results
const NAME_PROFILES = {
cassian: {
display: “Cassian”,
desc: “Ancient, magnetic, strategic—commands through presence and precision.”,
tags: [“Ancient”, “Magnetic”, “Strategic”, “Seductive”]
},
magnus: {
display: “Magnus”,
desc: “Gravitas and authority—classic command energy with unmistakable weight.”,
tags: [“Command”, “Force”, “Old-world”, “Formal”]
},
leon: {
display: “Leon”,
desc: “Lion-hearted dominance—sleek, warm, and unmistakably in charge.”,
tags: [“Lion”, “Sleek”, “Protector”, “Approachable”]
},
roman: {
display: “Roman”,
desc: “Structured power—urban empire energy with discipline and leadership.”,
tags: [“Structured”, “Leader”, “Imperial”, “Grounded”]
},
darius: {
display: “Darius”,
desc: “Regal depth—seductive authority with calm, tidal strength.”,
tags: [“Regal”, “Deep”, “Water”, “Intrigue”]
},
rourke: {
display: “Rourke”,
desc: “Rogue strategist—sharp, modern, and dangerous in a controlled way.”,
tags: [“Rogue”, “Sharp”, “Urban”, “Edge”]
},
titus: {
display: “Titus”,
desc: “Hard command—old-world authority with a clean, forceful profile.”,
tags: [“Command”, “Ancient”, “Hard”, “Formal”]
}
};

// ———- App state ———-
const MAX_CHOICES = 3;
let currentIndex = 0;
const answers = {}; // {questionId: Set(optionIds)}

const main = document.getElementById(“main”);
const backBtn = document.getElementById(“backBtn”);
const nextBtn = document.getElementById(“nextBtn”);
const resetBtn = document.getElementById(“resetBtn”);
const counter = document.getElementById(“counter”);
const progressFill = document.getElementById(“progressFill”);
const selectionMeta = document.getElementById(“selectionMeta”);
const leftMeta = document.getElementById(“leftMeta”);

// ———- Helpers ———-
function clamp(n, a, b){ return Math.max(a, Math.min(b, n)); }

function getSelectedSet(qid){
if(!answers[qid]) answers[qid] = new Set();
return answers[qid];
}

function updateFooterMeta(){
const q = QUESTIONS[currentIndex];
const sel = getSelectedSet(q.id).size;
selectionMeta.textContent = `${sel} / ${MAX_CHOICES} selected`;
nextBtn.disabled = (sel === 0);
backBtn.disabled = (currentIndex === 0);
}

function updateProgress(){
const total = QUESTIONS.length;
const pct = ((currentIndex) / total) * 100;
progressFill.style.width = `${clamp(pct, 0, 100)}%`;
counter.textContent = `Question ${currentIndex + 1} of ${total}`;
}

function toggleChoice(qid, oid){
const set = getSelectedSet(qid);
if(set.has(oid)){
set.delete(oid);
} else {
if(set.size >= MAX_CHOICES) return; // enforce limit
set.add(oid);
}
}

function renderQuestion(){
updateProgress();
const q = QUESTIONS[currentIndex];
const set = getSelectedSet(q.id);

main.innerHTML = `
<div>
<h2 class=”qTitle”>${q.title}</h2>
<p class=”qHelp”>${q.help}</p>
<div class=”choices” role=”group” aria-label=”${q.title}”>
${q.options.map(opt => {
const checked = set.has(opt.id);
return `
<div class=”choice” role=”checkbox” tabindex=”0″
aria-checked=”${checked ? “true” : “false”}”
data-qid=”${q.id}” data-oid=”${opt.id}”>
<div class=”checkbox” aria-hidden=”true”><div class=”checkmark”></div></div>
<div class=”label”>
<strong>${opt.label}</strong>
<span>${opt.desc || “”}</span>
</div>
</div>
`;
}).join(“”)}
</div>
<div class=”note”>You can choose up to <strong>${MAX_CHOICES}</strong> answers per question. If you hit the limit, unselect one to choose another.</div>
</div>
`;

// click handlers
main.querySelectorAll(“.choice”).forEach(el => {
el.addEventListener(“click”, () => {
const qid = el.dataset.qid;
const oid = el.dataset.oid;
const setBefore = getSelectedSet(qid).size;
toggleChoice(qid, oid);
// if limit reached and tried to add, do nothing (no render needed)
const setAfter = getSelectedSet(qid).size;
if(setAfter === setBefore && !getSelectedSet(qid).has(oid)) return;

renderQuestion();
updateFooterMeta();
});

el.addEventListener(“keydown”, (e) => {
if(e.key === “Enter” || e.key === ” “){
e.preventDefault();
el.click();
}
});
});

updateFooterMeta();
}

function computeScores(){
const scores = {};
// initialize
Object.keys(NAME_PROFILES).forEach(k => scores[k] = 0);

// For each selected option across all questions, add weights
for(const q of QUESTIONS){
const set = answers[q.id] || new Set();
for(const optId of set){
for(const [nameKey, weights] of Object.entries(NAME_WEIGHTS)){
const add = weights[optId] || 0;
scores[nameKey] = (scores[nameKey] || 0) + add;
}
}
}

// normalize to 0..100 for display
const entries = Object.entries(scores);
const max = Math.max(…entries.map(([,v]) => v), 1);
const ranked = entries
.map(([k,v]) => ({ key:k, score:v, pct: Math.round((v/max)*100) }))
.sort((a,b) => b.score – a.score);

return ranked;
}

function renderResults(){
progressFill.style.width = “100%”;
counter.textContent = “Results”;
leftMeta.innerHTML = `
<div><span class=”kbd”>Done</span> Your top matches are based on your combined selections.</div>
<div style=”color:var(–muted);font-size:12.5px;”>Want to tune results? Edit <span class=”kbd”>NAME_WEIGHTS</span> in the script.</div>
`;

const ranked = computeScores();
const top = ranked.slice(0, 3);

main.innerHTML = `
<div class=”results”>
<div class=”resultTop”>
<h2>Your Top Bar Name Matches</h2>
<p>These are the strongest fits based on how you described him: presence, dominance style, archetype, and what you want the name to communicate.</p>
</div>

<div class=”names”>
${top.map(r => {
const p = NAME_PROFILES[r.key];
return `
<div class=”nameCard”>
<div class=”name”>${p.display}</div>
<div class=”bar” aria-label=”Match strength”><div style=”width:${r.pct}%”></div></div>
<div class=”desc”>${p.desc}</div>
<div class=”tagRow”>${p.tags.map(t => `<span class=”tag”>${t}</span>`).join(“”)}</div>
</div>
`;
}).join(“”)}
</div>

<div class=”note”>
If one name feels right, you can also test a natural shortening (e.g., “Cassian” → “Cass”).
The best name should feel like recognition, not costume.
</div>
</div>
`;

// Buttons state
backBtn.disabled = false;
nextBtn.textContent = “Restart”;
nextBtn.disabled = false;
}

function goNext(){
if(nextBtn.textContent === “Restart”){
resetAll();
return;
}
if(currentIndex < QUESTIONS.length – 1){
currentIndex++;
renderQuestion();
} else {
renderResults();
}
}

function goBack(){
if(nextBtn.textContent === “Restart”){
// If on results, go back to last question
nextBtn.textContent = “Next”;
currentIndex = QUESTIONS.length – 1;
renderQuestion();
return;
}
if(currentIndex > 0){
currentIndex–;
renderQuestion();
}
}

function resetAll(){
currentIndex = 0;
for(const k of Object.keys(answers)) delete answers[k];
nextBtn.textContent = “Next”;
renderQuestion();
updateProgress();
updateFooterMeta();
}

// ———- Wire up buttons ———-
nextBtn.addEventListener(“click”, goNext);
backBtn.addEventListener(“click”, goBack);
resetBtn.addEventListener(“click”, resetAll);

// ———- Start ———-
renderQuestion();
</script>
</body>
</html>