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>
222 lines
13 KiB
HTML
222 lines
13 KiB
HTML
<!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="{"$preview":{"width":1920,"height":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>
|