Files
code_of_conquest_dnd/mockups/Character Sheet.dc.html
Phillip Tarrant 49bc6b22c0 docs(mockups): add the UI/systems bible (11 screens + README)
High-fidelity HTML/CSS/JS design references for the tactical-CRPG direction —
title, character creation, character sheet, inventory, world map, quest log,
shop, pause/settings, dialogue, combat HUD, main exploration window. README is
the handoff spec (visual system, per-screen state models, Godot translation
notes). Not production code — the source of truth for the game's look + systems.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 16:06:23 -05:00

222 lines
13 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet data-dc-atomics>
<link href="https://fonts.googleapis.com/css2?family=Architects+Daughter&display=swap" rel="stylesheet">
<style>
body{margin:0;background:#0f0d0b;font-family:system-ui,sans-serif}
a{color:#8f3a34}a:hover{color:#6f2b26}
</style>
</helmet>
<div style="width:1920px;height:1080px;position:relative;display:flex">
<!-- ============ LEFT: PORTRAIT / VITALS ============ -->
<div style="width:560px;height:1080px;position:relative;overflow:hidden;background:repeating-linear-gradient(135deg,#26221c 0 16px,#221e18 16px 32px);display:flex;flex-direction:column">
<div style="position:absolute;inset:0;background:radial-gradient(120% 70% at 50% 38%,rgba(0,0,0,0) 32%,rgba(0,0,0,.62) 100%)"></div>
<div style="position:relative;padding:28px 34px 0;font:13px ui-monospace,monospace;letter-spacing:.18em;color:#8a7f6c">CHARACTER</div>
<!-- model -->
<div style="position:relative;flex:1;display:flex;align-items:center;justify-content:center">
<div style="width:230px;height:460px;border:1px dashed #5a5348;border-radius:16px;background:repeating-linear-gradient(135deg,#2c2620 0 14px,#282219 14px 28px);display:flex;align-items:center;justify-content:center;text-align:center;color:#6b6152;font:12px ui-monospace,monospace;letter-spacing:.12em">PORTRAIT</div>
</div>
<!-- nameplate + xp + vitals + conditions -->
<div style="position:relative;padding:0 34px 34px;display:flex;flex-direction:column;gap:16px">
<div>
<div style="font:600 36px 'Architects Daughter',cursive;color:#e8d9b6;line-height:1">Vexcca the Nameless</div>
<div style="font:14px ui-monospace,monospace;letter-spacing:.12em;color:#a9843f;margin-top:4px">HUMAN · SELLSWORD · LEVEL 4</div>
</div>
<!-- xp -->
<div>
<div style="display:flex;justify-content:space-between;font:10px ui-monospace,monospace;letter-spacing:.1em;color:#8a7f6c"><span>EXPERIENCE</span><span>3,450 / 5,000</span></div>
<div style="height:9px;border-radius:5px;background:#2a251f;border:1px solid #4a4238;overflow:hidden;margin-top:4px"><div style="width:69%;height:100%;background:#a9843f"></div></div>
</div>
<!-- vitals -->
<div style="display:flex;gap:10px">
<div style="flex:1"><div style="font:10px ui-monospace,monospace;color:#caa39c;margin-bottom:3px">HP 42 / 60</div><div style="height:11px;border-radius:6px;background:#2a251f;border:1px solid #4a4238;overflow:hidden"><div style="width:70%;height:100%;background:linear-gradient(90deg,#b8524a,#8f3a34)"></div></div></div>
<div style="flex:1"><div style="font:10px ui-monospace,monospace;color:#9caccb;margin-bottom:3px">MP 18 / 30</div><div style="height:11px;border-radius:6px;background:#2a251f;border:1px solid #4a4238;overflow:hidden"><div style="width:60%;height:100%;background:linear-gradient(90deg,#4f7ab8,#243f6f)"></div></div></div>
</div>
<!-- condition badges -->
<div style="display:flex;flex-wrap:wrap;gap:8px">
<span style="font:11px ui-monospace,monospace;letter-spacing:.04em;color:#e6b0aa;background:rgba(143,58,52,.24);border:1px solid #8f3a34;border-radius:6px;padding:5px 10px">⚠ Infected bite — left arm</span>
<span style="font:11px ui-monospace,monospace;letter-spacing:.04em;color:#e6c9a0;background:rgba(165,119,42,.22);border:1px solid #a5772a;border-radius:6px;padding:5px 10px">Hungover</span>
</div>
</div>
</div>
<!-- ============ RIGHT: SHEET ============ -->
<div style="width:1360px;height:1080px;background:linear-gradient(180deg,#ece2ca,#e4d8bd);border-left:4px solid #1a1512;box-sizing:border-box;padding:30px 40px;display:flex;flex-direction:column;gap:20px">
<!-- header -->
<div style="display:flex;align-items:flex-end;justify-content:space-between;border-bottom:2px solid #bfa878;padding-bottom:14px">
<div>
<div style="font:600 30px 'Architects Daughter',cursive;letter-spacing:.04em;color:#5a4326">Character Sheet</div>
<div style="font:12px ui-monospace,monospace;color:#8a7748;letter-spacing:.08em;margin-top:2px">WHAT YOU ARE, WRITTEN DOWN — AND WHAT'S WRONG WITH YOU</div>
</div>
<div style="display:flex;gap:20px">
<div style="text-align:center"><div style="font:10px ui-monospace,monospace;letter-spacing:.1em;color:#8a7748">PROF</div><div style="font:600 22px 'Architects Daughter',cursive;color:#5a4326">+2</div></div>
<div style="text-align:center"><div style="font:10px ui-monospace,monospace;letter-spacing:.1em;color:#8a7748">HIT DIE</div><div style="font:600 22px 'Architects Daughter',cursive;color:#5a4326">d10</div></div>
<div style="font:11px ui-monospace,monospace;color:#a99464;border:1px solid #cbb684;border-radius:6px;padding:6px 10px;cursor:pointer;align-self:center" style-hover="background:#e6d9b8">ESC ✕</div>
</div>
</div>
<!-- body: 3 columns -->
<div style="display:flex;gap:26px;flex:1;min-height:0">
<!-- COL A: attributes + saves -->
<div style="width:300px;flex:none;display:flex;flex-direction:column;gap:20px">
<div>
<div style="font:13px ui-monospace,monospace;letter-spacing:.16em;color:#8a7748;margin-bottom:11px">ATTRIBUTES</div>
<div style="display:flex;flex-direction:column;gap:9px">
<sc-for list="{{ stats }}" as="a" hint-placeholder-count="5">
<div style="display:flex;align-items:center;gap:14px;background:#f1e8d2;border:1px solid #bfa878;border-radius:10px;padding:10px 16px">
<div style="font:12px ui-monospace,monospace;letter-spacing:.14em;color:#8a7748;width:38px">{{ a.key }}</div>
<div style="font:600 30px 'Architects Daughter',cursive;color:#3a2f1c;width:56px">{{ a.mod }}</div>
<div style="margin-left:auto;font:13px ui-monospace,monospace;color:#a9885a">score {{ a.val }}</div>
</div>
</sc-for>
</div>
</div>
<div>
<div style="font:13px ui-monospace,monospace;letter-spacing:.16em;color:#8a7748;margin-bottom:11px">SAVING THROWS</div>
<div style="background:#f1e8d2;border:1px solid #bfa878;border-radius:10px;padding:6px 16px">
<sc-for list="{{ saves }}" as="s" hint-placeholder-count="5">
<div style="display:flex;align-items:center;gap:10px;padding:7px 0;border-bottom:1px solid #e0d3ac">
<span style="font:15px ui-monospace,monospace;color:{{ s.dotColor }}">{{ s.dot }}</span>
<span style="font:14px system-ui;color:#3a2f1c">{{ s.key }}</span>
<span style="margin-left:auto;font:600 15px ui-monospace,monospace;color:#5a4326">{{ s.val }}</span>
</div>
</sc-for>
</div>
</div>
</div>
<!-- COL B: combat + skills -->
<div style="flex:1;min-width:0;display:flex;flex-direction:column;gap:20px">
<div>
<div style="font:13px ui-monospace,monospace;letter-spacing:.16em;color:#8a7748;margin-bottom:11px">IN A FIGHT</div>
<div style="display:grid;grid-template-columns:repeat(4,1fr);gap:10px">
<sc-for list="{{ combat }}" as="c" hint-placeholder-count="8">
<div style="background:#f1e8d2;border:1px solid #bfa878;border-radius:10px;padding:12px 8px;text-align:center">
<div style="font:9px ui-monospace,monospace;letter-spacing:.08em;color:#8a7748">{{ c.label }}</div>
<div style="font:600 26px 'Architects Daughter',cursive;color:#3a2f1c;margin-top:3px">{{ c.val }}</div>
</div>
</sc-for>
</div>
</div>
<div style="flex:1;min-height:0;display:flex;flex-direction:column">
<div style="font:13px ui-monospace,monospace;letter-spacing:.16em;color:#8a7748;margin-bottom:11px">SKILLS</div>
<div style="background:#f1e8d2;border:1px solid #bfa878;border-radius:10px;padding:4px 16px;column-count:2;column-gap:26px">
<sc-for list="{{ skills }}" as="k" hint-placeholder-count="9">
<div style="display:flex;align-items:center;gap:9px;padding:7px 0;break-inside:avoid">
<span style="font:15px ui-monospace,monospace;color:{{ k.dotColor }}">{{ k.dot }}</span>
<span style="font:14px system-ui;color:#3a2f1c">{{ k.name }}</span>
<span style="font:10px ui-monospace,monospace;color:#a9885a">{{ k.abil }}</span>
<span style="margin-left:auto;font:600 14px ui-monospace,monospace;color:#5a4326">{{ k.val }}</span>
</div>
</sc-for>
</div>
</div>
</div>
<!-- COL C: talents + afflictions + bio -->
<div style="width:400px;flex:none;display:flex;flex-direction:column;gap:20px;min-height:0">
<div>
<div style="font:13px ui-monospace,monospace;letter-spacing:.16em;color:#8a7748;margin-bottom:11px">TALENTS</div>
<div style="display:flex;flex-direction:column;gap:9px">
<sc-for list="{{ talents }}" as="t" hint-placeholder-count="3">
<div style="background:#f1e8d2;border:1px solid #bfa878;border-radius:10px;padding:11px 15px">
<div style="font:600 15px system-ui;color:#3a2f1c">{{ t.name }}</div>
<div style="font:13px/1.45 Georgia,serif;color:#6a5a3a;margin-top:3px">{{ t.desc }}</div>
</div>
</sc-for>
</div>
</div>
<div>
<div style="font:13px ui-monospace,monospace;letter-spacing:.16em;color:#8f3a34;margin-bottom:11px">AFFLICTIONS</div>
<div style="display:flex;flex-direction:column;gap:9px">
<sc-for list="{{ afflictions }}" as="x" hint-placeholder-count="3">
<div style="background:#f1e8d2;border:1px solid {{ x.color }};border-left:4px solid {{ x.color }};border-radius:10px;padding:11px 15px">
<div style="font:600 15px system-ui;color:{{ x.color }}">{{ x.name }}</div>
<div style="font:13px/1.45 Georgia,serif;color:#6a5a3a;margin-top:3px">{{ x.desc }}</div>
</div>
</sc-for>
</div>
</div>
<div style="flex:1;min-height:0">
<div style="font:13px ui-monospace,monospace;letter-spacing:.16em;color:#8a7748;margin-bottom:11px">THE DM'S NOTES</div>
<div style="background:rgba(231,220,196,.6);border:1px dashed #a99464;border-radius:10px;padding:14px 16px;font:15px/1.55 Georgia,serif;font-style:italic;color:#5a4a2c">They call you Nameless because you burned the papers that said otherwise. Four contracts, three scars, and one debt that keeps finding you no matter which city you bleed in.</div>
</div>
</div>
</div>
</div>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props="{&quot;$preview&quot;:{&quot;width&quot;:1920,&quot;height&quot;:1080}}">
class Component extends DCLogic {
MODS = { STR: 2, DEX: 1, CON: 1, FTH: -1, MAG: -1 }; // LCK exists but is never shown
PROF = 2;
sign(n) { return (n >= 0 ? '+' : '') + n; }
renderVals() {
const scores = { STR: 15, DEX: 13, CON: 12, FTH: 9, MAG: 8 };
const stats = Object.keys(this.MODS).map(k => ({ key: k, val: scores[k], mod: this.sign(this.MODS[k]) }));
const saveProf = { STR: true, CON: true };
const saves = Object.keys(this.MODS).map(k => {
const v = this.MODS[k] + (saveProf[k] ? this.PROF : 0);
return { key: k, val: this.sign(v), dot: saveProf[k] ? '●' : '○', dotColor: saveProf[k] ? '#8f6a2a' : '#c9b78a' };
});
const skillDefs = [
{ name: 'Athletics', abil: 'STR', prof: true },
{ name: 'Intimidation', abil: 'STR', prof: true },
{ name: 'Stealth', abil: 'DEX', prof: true },
{ name: 'Sleight of Hand', abil: 'DEX', prof: false },
{ name: 'Acrobatics', abil: 'DEX', prof: false },
{ name: 'Endurance', abil: 'CON', prof: true },
{ name: 'Perception', abil: 'FTH', prof: false },
{ name: 'Faith-Lore', abil: 'FTH', prof: false },
{ name: 'Sorcery', abil: 'MAG', prof: false },
];
const skills = skillDefs.map(s => {
const v = this.MODS[s.abil] + (s.prof ? this.PROF : 0);
return { name: s.name, abil: s.abil, val: this.sign(v), dot: s.prof ? '●' : '○', dotColor: s.prof ? '#8f6a2a' : '#c9b78a' };
});
const combat = [
{ label: 'ARMOR', val: '14' },
{ label: 'INITIATIVE', val: '+1' },
{ label: 'SPEED', val: "30'" },
{ label: 'CARRY', val: '60' },
{ label: 'MELEE', val: '+4' },
{ label: 'RANGED', val: '+3' },
{ label: 'SPELL DC', val: '11' },
{ label: 'DEATH SVS', val: '0/0' },
];
const talents = [
{ name: 'Second Wind', desc: 'Once per rest, bite down and claw back 1d10+4 HP.' },
{ name: 'Reckless Swing', desc: 'Swing with advantage — but everything hits you easier until your next turn.' },
{ name: "Mercenary's Nose", desc: 'You can smell a contract going bad before the coin changes hands.' },
];
const afflictions = [
{ name: 'Infected Bite — left arm', desc: 'CON save each dawn or your max HP drops by 1 until it heals or takes you.', color: '#8f3a34' },
{ name: 'Hungover', desc: '1 to attack rolls and CON checks until midday. You did this to yourself.', color: '#a5772a' },
{ name: 'Old Knee', desc: 'Speed 5 in cold or wet weather. It always knows before you do.', color: '#a5772a' },
];
return { stats, saves, skills, combat, talents, afflictions };
}
}
</script>
</body>
</html>