Files
TheriapolisV3/_design_handoff/character_creation/from_design/index.html
T

961 lines
32 KiB
HTML
Raw Normal View History

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Theriapolis — Character Creation</title>
<meta name="viewport" content="width=1440" />
<style>
/* === Theriapolis — Hand-bound Bestiary === */
:root {
/* Parchment theme (default) */
--bg: #e8dcc0;
--bg-2: #d9c9a6;
--bg-deep: #c7b48b;
--ink: #2b1d10;
--ink-soft: #5a4527;
--ink-mute: #8a6f48;
--rule: #8a6f48;
--gild: #b48a3c; /* foil */
--seal: #7a1f12; /* wax seal red */
--seal-2: #5a160c;
--accent: #6b4a1e;
--shadow: 0 2px 0 rgba(43,29,16,0.06), 0 18px 40px -28px rgba(43,29,16,0.45);
--paper-grain:
radial-gradient(1200px 800px at 30% 20%, rgba(255,250,235,0.55), transparent 60%),
radial-gradient(900px 700px at 80% 80%, rgba(120,80,30,0.10), transparent 60%),
radial-gradient(2px 2px at 24% 33%, rgba(70,45,20,0.08), transparent 60%),
radial-gradient(1px 1px at 67% 51%, rgba(70,45,20,0.10), transparent 60%),
radial-gradient(2px 2px at 12% 78%, rgba(70,45,20,0.10), transparent 60%),
radial-gradient(1px 1px at 88% 28%, rgba(70,45,20,0.08), transparent 60%);
--serif-display: 'Cormorant Garamond', 'EB Garamond', Garamond, serif;
--serif-body: 'Crimson Pro', 'EB Garamond', Garamond, serif;
--mono: 'JetBrains Mono', ui-monospace, Menlo, monospace;
--gap: 24px;
--pad: 28px;
--radius: 2px;
}
/* Dark theme — leather & candlelight */
[data-theme="dark"] {
--bg: #1c1410;
--bg-2: #261b14;
--bg-deep: #100a07;
--ink: #f0e2c4;
--ink-soft: #d4be90;
--ink-mute: #8c7651;
--rule: #6b5635;
--gild: #d8a84a;
--seal: #b03021;
--seal-2: #7a1f12;
--accent: #d8a84a;
--paper-grain:
radial-gradient(1200px 800px at 30% 20%, rgba(80,55,30,0.35), transparent 60%),
radial-gradient(900px 700px at 80% 80%, rgba(255,200,120,0.06), transparent 60%);
}
/* Blood-warm theme */
[data-theme="blood"] {
--bg: #2a0e0a;
--bg-2: #391410;
--bg-deep: #170604;
--ink: #f3e0c5;
--ink-soft: #e3bf94;
--ink-mute: #a07853;
--rule: #7a3225;
--gild: #e2a13a;
--seal: #c83426;
--seal-2: #8c1a10;
--accent: #e2a13a;
--paper-grain:
radial-gradient(1200px 800px at 30% 20%, rgba(180,60,40,0.18), transparent 60%),
radial-gradient(900px 700px at 80% 80%, rgba(255,200,120,0.08), transparent 60%);
}
/* Compact density */
[data-density="compact"] {
--gap: 14px;
--pad: 18px;
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; background: var(--bg-deep); color: var(--ink); font-family: var(--serif-body); }
body {
min-height: 100vh;
background:
var(--paper-grain),
var(--bg);
background-attachment: fixed;
}
::selection { background: var(--gild); color: var(--bg); }
/* App shell */
#app { min-height: 100vh; padding: 28px 36px 80px; }
.app-frame {
max-width: 1340px; margin: 0 auto;
border: 1px solid var(--rule);
background:
linear-gradient(180deg, rgba(255,250,235,0.04), transparent 30%),
var(--bg);
box-shadow: var(--shadow);
position: relative;
}
.app-frame::before, .app-frame::after {
content: ""; position: absolute; pointer-events: none;
border: 1px solid var(--rule);
inset: 8px;
}
.app-frame::after { inset: 14px; border-color: color-mix(in oklab, var(--rule) 45%, transparent); }
.codex-header {
padding: 22px 36px 18px;
border-bottom: 1px solid var(--rule);
display: flex; align-items: flex-end; justify-content: space-between;
gap: 24px; position: relative; z-index: 1;
}
.codex-title {
font-family: var(--serif-display);
font-weight: 500;
font-size: 28px;
letter-spacing: 0.08em;
text-transform: uppercase;
margin: 0;
color: var(--ink);
}
.codex-title em {
font-style: italic; color: var(--ink-mute); font-weight: 400;
text-transform: none; letter-spacing: 0.01em;
}
.codex-sub {
font-family: var(--mono);
font-size: 11px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--ink-mute);
}
/* Stepper */
.stepper {
display: grid; grid-template-columns: repeat(7, 1fr);
border-top: 1px solid var(--rule);
border-bottom: 1px solid var(--rule);
background: linear-gradient(180deg, transparent, rgba(0,0,0,0.04));
}
.step {
padding: 14px 12px; text-align: center; cursor: pointer;
border-right: 1px solid color-mix(in oklab, var(--rule) 50%, transparent);
transition: background .2s;
position: relative;
}
.step:last-child { border-right: none; }
.step:hover { background: color-mix(in oklab, var(--gild) 8%, transparent); }
.step .num {
font-family: var(--serif-display);
font-size: 22px; font-style: italic; color: var(--ink-mute);
line-height: 1;
}
.step .name {
font-family: var(--mono);
font-size: 10px; letter-spacing: 0.22em; text-transform: uppercase;
color: var(--ink-mute); margin-top: 4px;
}
.step.active .num, .step.active .name { color: var(--ink); }
.step.active::after {
content: ""; position: absolute; left: 14%; right: 14%; bottom: -1px; height: 2px;
background: var(--gild);
}
.step.complete .num { color: var(--seal); }
.step.complete .num::before {
content: "✓ "; font-style: normal; color: var(--seal); font-size: 14px;
}
.step.locked { cursor: not-allowed; opacity: 0.45; }
.step.locked:hover { background: transparent; }
.step.locked .num { color: var(--ink-mute); font-size: 16px; font-style: normal; }
/* Page body */
.page {
display: grid;
grid-template-columns: 1fr 380px;
gap: 0;
min-height: 720px;
position: relative;
z-index: 1;
}
.page-main {
padding: var(--pad) 36px;
border-right: 1px solid var(--rule);
}
.page-aside {
padding: var(--pad) 28px;
background:
repeating-linear-gradient(0deg, transparent 0 27px, color-mix(in oklab, var(--rule) 18%, transparent) 27px 28px),
linear-gradient(180deg, transparent, rgba(0,0,0,0.03));
}
/* Headings */
h1, h2, h3, h4 { font-family: var(--serif-display); font-weight: 500; color: var(--ink); margin: 0; }
h1 { font-size: 38px; letter-spacing: 0.02em; }
h2 { font-size: 28px; letter-spacing: 0.02em; }
h3 { font-size: 20px; letter-spacing: 0.04em; }
h4 { font-size: 14px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-mute); font-weight: 600; }
.drop-cap::first-letter {
font-family: var(--serif-display);
font-size: 64px; float: left; line-height: 0.85;
padding: 6px 10px 0 0; color: var(--seal);
font-weight: 500;
}
/* Step page intro */
.page-intro { display: flex; align-items: baseline; justify-content: space-between; gap: 24px; margin-bottom: 18px; }
.page-intro .eyebrow {
font-family: var(--mono); font-size: 11px; letter-spacing: 0.24em;
color: var(--ink-mute); text-transform: uppercase;
}
.page-intro p { color: var(--ink-soft); max-width: 60ch; line-height: 1.55; font-size: 15px; margin: 6px 0 0; }
/* Cards & grids */
.card-grid {
display: grid; gap: var(--gap);
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.card {
border: 1px solid var(--rule);
background: linear-gradient(180deg, rgba(255,250,235,0.05), transparent), var(--bg-2);
padding: 18px 18px 16px;
cursor: pointer;
position: relative;
transition: transform .18s, box-shadow .18s, border-color .18s;
overflow: hidden;
}
.card:hover { border-color: var(--gild); }
.card.selected {
border-color: var(--seal);
box-shadow: 0 0 0 1px var(--seal) inset, 0 14px 36px -22px rgba(122,31,18,0.6);
}
.card.selected::after {
content: "";
position: absolute; top: -10px; right: -10px;
width: 44px; height: 44px;
border-radius: 50%;
background: radial-gradient(circle at 35% 35%, var(--seal) 0 60%, var(--seal-2) 65%, var(--seal-2) 100%);
box-shadow: inset -2px -3px 4px rgba(0,0,0,0.4), 0 2px 4px rgba(0,0,0,0.3);
}
.card.selected::before {
content: "✕"; /* sealed mark, will be overridden per-step with sigil */
position: absolute; top: 0; right: 0;
width: 24px; height: 24px; line-height: 24px; text-align: center;
color: var(--bg); font-family: var(--serif-display);
font-size: 14px;
transform: translate(-2px, 4px) rotate(-8deg);
z-index: 1;
}
.card .name {
font-family: var(--serif-display);
font-size: 22px; font-weight: 500;
margin: 0 0 6px;
}
.card .meta {
font-family: var(--mono); font-size: 10px; letter-spacing: 0.2em;
text-transform: uppercase; color: var(--ink-mute);
margin-bottom: 10px;
}
.card .body { font-size: 14px; color: var(--ink-soft); line-height: 1.5; }
/* Sigil — clade glyph */
.sigil {
width: 56px; height: 56px;
border: 1px solid var(--rule);
border-radius: 50%;
display: grid; place-items: center;
background:
radial-gradient(circle at 30% 30%, rgba(255,250,235,0.4), transparent 60%),
var(--bg);
color: var(--ink);
margin-bottom: 12px;
flex-shrink: 0;
}
.sigil svg { width: 30px; height: 30px; }
/* Ability mod chips */
.mods { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.mod {
font-family: var(--mono); font-size: 10px; letter-spacing: 0.16em;
padding: 3px 7px; border: 1px solid var(--rule);
color: var(--ink-soft); background: var(--bg);
}
.mod.pos { color: var(--seal); border-color: var(--seal); }
.mod.neg { color: var(--ink-mute); border-style: dashed; }
/* Trait list */
.trait-list { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.trait {
border-left: 2px solid var(--gild);
padding: 4px 0 4px 10px;
font-size: 13px; color: var(--ink-soft);
}
.trait.detriment { border-left-color: var(--seal); }
.trait .t-name {
font-family: var(--serif-display); font-style: italic;
font-weight: 600; color: var(--ink); margin-right: 6px; font-size: 14px;
}
/* Buttons */
.btn {
font-family: var(--serif-display);
font-size: 16px; letter-spacing: 0.04em;
padding: 10px 22px;
background: var(--bg);
color: var(--ink);
border: 1px solid var(--ink);
cursor: pointer;
transition: all .18s;
}
.btn:hover { background: var(--ink); color: var(--bg); }
.btn[disabled] { opacity: 0.4; cursor: not-allowed; }
.btn.primary {
background: var(--seal); border-color: var(--seal); color: var(--bg);
font-weight: 500;
}
.btn.primary:hover { background: var(--seal-2); border-color: var(--seal-2); }
.btn.ghost { background: transparent; border-color: var(--rule); color: var(--ink-soft); }
.btn.small { padding: 6px 12px; font-size: 13px; }
.btn.icon { padding: 6px 10px; }
/* Footer nav */
.nav-bar {
display: flex; justify-content: space-between; align-items: center;
padding: 16px 36px;
border-top: 1px solid var(--rule);
background: linear-gradient(0deg, rgba(0,0,0,0.04), transparent);
}
.nav-progress {
font-family: var(--mono); font-size: 11px; letter-spacing: 0.2em;
color: var(--ink-mute); text-transform: uppercase;
}
.validation { color: var(--seal); font-style: italic; font-family: var(--serif-display); font-size: 14px; }
.validation.ok { color: var(--ink-mute); font-style: normal; font-family: var(--mono); font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; }
/* Aside summary */
.summary-block { margin-bottom: 22px; }
.summary-block h4 { margin-bottom: 6px; }
.summary-block .v {
font-family: var(--serif-display);
font-size: 18px; font-weight: 500; color: var(--ink);
line-height: 1.3;
}
.summary-block .v small {
display: block; font-family: var(--mono); font-size: 10px;
letter-spacing: 0.18em; color: var(--ink-mute); text-transform: uppercase;
margin-top: 2px; font-weight: 400;
}
.summary-block.empty .v { color: var(--ink-mute); font-style: italic; }
.stat-strip { display: grid; grid-template-columns: repeat(6, 1fr); gap: 4px; margin-top: 6px; }
.stat-strip .cell {
border: 1px solid var(--rule);
padding: 6px 4px; text-align: center;
background: var(--bg);
}
.stat-strip .cell .ab {
font-family: var(--mono); font-size: 9px; letter-spacing: 0.2em;
color: var(--ink-mute); text-transform: uppercase;
}
.stat-strip .cell .sc {
font-family: var(--serif-display); font-size: 18px; color: var(--ink);
font-weight: 500;
}
.stat-strip .cell .md {
font-family: var(--mono); font-size: 10px;
color: var(--seal);
}
.stat-strip .cell .md.neg { color: var(--ink-mute); }
/* Predator/Prey divider */
.clade-group-label {
font-family: var(--mono); font-size: 11px; letter-spacing: 0.24em;
text-transform: uppercase; color: var(--ink-mute);
margin: 18px 0 12px; display: flex; align-items: center; gap: 12px;
}
.clade-group-label::after {
content: ""; flex: 1; height: 1px; background: var(--rule);
}
.clade-group-label:first-child { margin-top: 0; }
/* Scent aura */
.card.scented { position: relative; }
.scent-aura {
position: absolute; inset: -8px; pointer-events: none; opacity: 0;
transition: opacity .35s;
background:
radial-gradient(circle at 50% 50%, color-mix(in oklab, var(--gild) 30%, transparent), transparent 60%);
filter: blur(10px);
animation: scent-drift 4s ease-in-out infinite;
}
.card:hover .scent-aura { opacity: 1; }
@keyframes scent-drift {
0%, 100% { transform: translate(0, 0) scale(1); }
50% { transform: translate(2px, -4px) scale(1.04); }
}
/* Recommendation badge */
.badge-rec {
display: inline-flex; align-items: center; gap: 4px;
font-family: var(--mono); font-size: 9px; letter-spacing: 0.18em;
text-transform: uppercase; color: var(--gild);
padding: 2px 6px; border: 1px solid var(--gild);
margin-left: 6px;
background: color-mix(in oklab, var(--gild) 8%, transparent);
}
/* Stat tabs */
.stat-tabs {
display: flex; gap: 0; border-bottom: 1px solid var(--rule); margin-bottom: 18px;
}
.stat-tab {
padding: 10px 18px; cursor: pointer;
font-family: var(--serif-display); font-size: 16px;
color: var(--ink-mute); border-bottom: 2px solid transparent;
margin-bottom: -1px;
}
.stat-tab.active { color: var(--ink); border-bottom-color: var(--gild); }
.pool {
display: flex; gap: 10px; flex-wrap: wrap;
padding: 14px; border: 1px dashed var(--rule); margin-bottom: 18px;
background: color-mix(in oklab, var(--gild) 3%, transparent);
}
.die {
width: 56px; height: 56px;
display: grid; place-items: center;
border: 1px solid var(--rule);
background: var(--bg);
font-family: var(--serif-display); font-size: 26px; font-weight: 500;
cursor: grab;
user-select: none;
transition: all .15s;
}
.die:hover { border-color: var(--gild); transform: translateY(-2px); }
.die.assigned { opacity: 0.3; cursor: default; pointer-events: none; }
.die.dragging { cursor: grabbing; opacity: 0.5; }
.ability-row {
display: grid;
grid-template-columns: 80px 60px 80px 90px 1fr;
align-items: center; gap: 12px;
padding: 12px 6px;
border-bottom: 1px solid color-mix(in oklab, var(--rule) 40%, transparent);
}
.ability-row .ab-name {
font-family: var(--serif-display); font-size: 18px; font-weight: 500;
}
.ability-row .ab-name small {
display: block; font-family: var(--mono); font-size: 9px;
letter-spacing: 0.2em; color: var(--ink-mute); text-transform: uppercase;
}
.slot {
height: 44px; border: 1px dashed var(--rule);
display: grid; place-items: center;
font-family: var(--serif-display); font-size: 22px;
background: var(--bg);
cursor: pointer;
transition: all .15s;
}
.slot.filled { border-style: solid; border-color: var(--ink-soft); background: color-mix(in oklab, var(--gild) 6%, var(--bg)); cursor: grab; }
.slot.filled:active { cursor: grabbing; }
.slot.drag-over { border-color: var(--seal); background: color-mix(in oklab, var(--seal) 10%, var(--bg)); }
.pool.drag-over { background: color-mix(in oklab, var(--seal) 6%, transparent); border-color: var(--seal); }
.ability-row .mod-final { font-family: var(--mono); font-size: 14px; color: var(--seal); }
.ability-row .mod-final.neg { color: var(--ink-mute); }
.ability-row .bar {
height: 6px; background: var(--bg); border: 1px solid var(--rule); position: relative;
}
.ability-row .bar-fill { position: absolute; inset: 0; right: auto; background: var(--gild); }
.ability-row .formula {
font-family: var(--mono); font-size: 10px; letter-spacing: 0.1em;
color: var(--ink-mute);
}
/* Skills */
.skill-grid-by-ability {
display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px;
}
.skill-group {
border: 1px solid var(--rule);
background: var(--bg-2);
padding: 14px 16px;
}
.skill-group h5 {
font-family: var(--serif-display); font-size: 16px; font-weight: 500;
margin: 0 0 8px;
display: flex; align-items: center; justify-content: space-between;
}
.skill-group h5 small {
font-family: var(--mono); font-size: 10px; letter-spacing: 0.2em;
color: var(--ink-mute); text-transform: uppercase;
}
.skill-row {
display: flex; align-items: center; justify-content: space-between;
padding: 6px 0;
border-bottom: 1px solid color-mix(in oklab, var(--rule) 30%, transparent);
font-size: 14px;
cursor: pointer;
}
.skill-row:last-child { border: none; }
.skill-row .label { display: flex; align-items: center; gap: 8px; }
.skill-row .check {
width: 18px; height: 18px;
border: 1px solid var(--ink-mute);
display: grid; place-items: center;
font-family: var(--serif-display); font-size: 14px;
color: transparent;
}
.skill-row.checked .check {
background: var(--seal); border-color: var(--seal); color: var(--bg);
}
.skill-row.locked .check { background: var(--gild); border-color: var(--gild); color: var(--bg); cursor: not-allowed; }
.skill-row.locked { opacity: 0.85; cursor: default; }
.skill-row .source-tag {
font-family: var(--mono); font-size: 9px; letter-spacing: 0.18em;
color: var(--ink-mute); text-transform: uppercase;
}
.skill-row.unavailable { opacity: 0.35; cursor: default; }
/* Skill name chip inside a row — drop the pill chrome, keep hover affordance */
.skill-row .label .t-name {
border: 0;
background: transparent;
padding: 0;
font-family: var(--serif-body);
font-style: normal;
font-size: 14px;
color: var(--ink);
text-transform: none;
letter-spacing: 0;
border-bottom: 1px dotted var(--rule);
}
.skill-row.checked .label .t-name { color: var(--seal); }
.skill-row.locked .label .t-name { color: var(--gild); }
.skill-row .label .t-name:hover {
background: transparent;
border-bottom-color: var(--gild);
color: var(--gild);
}
.skill-row.unavailable .label .t-name { border-bottom-style: dashed; }
/* Aside summary skill chips — small, colored by source */
.aside-skills .t-name {
font-size: 10px;
padding: 2px 7px;
}
.aside-skills .t-name.from-bg {
border-color: color-mix(in oklab, var(--gild) 60%, transparent);
background: color-mix(in oklab, var(--gild) 6%, var(--bg));
color: var(--gild);
}
.aside-skills .t-name.from-bg:hover {
background: color-mix(in oklab, var(--gild) 18%, var(--bg));
}
.aside-skills .t-name.from-cls {
border-color: color-mix(in oklab, var(--seal) 55%, transparent);
background: color-mix(in oklab, var(--seal) 6%, var(--bg));
color: var(--seal);
}
.aside-skills .t-name.from-cls:hover {
background: color-mix(in oklab, var(--seal) 18%, var(--bg));
}
/* Background-card feature chip — slightly louder than a default trait chip */
.bg-feat-row .t-name {
border-color: color-mix(in oklab, var(--seal) 55%, transparent);
background: color-mix(in oklab, var(--seal) 8%, var(--bg));
color: var(--seal);
}
.bg-feat-row .t-name:hover {
background: color-mix(in oklab, var(--seal) 18%, var(--bg));
border-color: var(--seal);
}
/* Inputs */
input[type="text"], textarea {
font-family: var(--serif-display); font-size: 22px;
background: transparent; border: none;
border-bottom: 1px solid var(--rule);
color: var(--ink);
padding: 10px 0;
width: 100%; outline: none;
}
input[type="text"]:focus { border-bottom-color: var(--gild); }
/* Drop cap intro */
.intro-block {
border-left: 4px solid var(--seal);
padding: 8px 0 8px 18px;
margin: 16px 0 22px;
font-size: 16px; line-height: 1.65;
color: var(--ink-soft);
font-style: italic;
font-family: var(--serif-display);
max-width: 65ch;
}
/* Hover detail panel (on aside) */
.hover-panel {
border: 1px solid var(--rule);
background: var(--bg-2);
padding: 16px;
margin-top: 16px;
}
.hover-panel h4 { margin-bottom: 6px; }
/* Final review */
.review-grid {
display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap);
}
.review-block {
border: 1px solid var(--rule);
padding: 18px 20px;
background: var(--bg-2);
}
.review-block .head {
display: flex; align-items: center; justify-content: space-between;
margin-bottom: 10px;
}
.review-block .edit-link {
font-family: var(--mono); font-size: 10px; letter-spacing: 0.2em;
text-transform: uppercase; color: var(--gild); cursor: pointer;
background: none; border: none; padding: 0;
}
.kit-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; }
.kit-item {
border: 1px solid var(--rule);
background: var(--bg);
padding: 8px 10px;
font-size: 13px;
}
.kit-item .qty { font-family: var(--mono); font-size: 10px; color: var(--ink-mute); letter-spacing: 0.18em; }
.kit-item.equipped { border-color: var(--gild); }
.kit-item.equipped .equipped-tag {
font-family: var(--mono); font-size: 9px; letter-spacing: 0.18em;
color: var(--gild); text-transform: uppercase; margin-top: 2px;
display: block;
}
/* Reading box (plain language) */
.reading {
border: 1px solid var(--gild);
background: color-mix(in oklab, var(--gild) 6%, var(--bg-2));
padding: 12px 14px;
margin-top: 12px;
font-size: 13px;
color: var(--ink-soft);
line-height: 1.55;
font-family: var(--serif-body);
}
.reading::before {
content: "Plainly Reading"; display: block;
font-family: var(--mono); font-size: 9px; letter-spacing: 0.24em;
color: var(--gild); text-transform: uppercase; margin-bottom: 4px;
}
/* Portrait variants */
.portrait-frame {
border: 1px solid var(--rule);
background:
radial-gradient(circle at 30% 25%, rgba(255,250,235,0.18), transparent 60%),
var(--bg-2);
padding: 18px;
margin-bottom: 18px;
position: relative;
aspect-ratio: 1 / 1.1;
display: grid; place-items: center;
overflow: hidden;
}
.portrait-frame::before, .portrait-frame::after {
content: ""; position: absolute; pointer-events: none;
border: 1px solid color-mix(in oklab, var(--rule) 50%, transparent);
inset: 6px;
}
.portrait-style-toggle {
display: flex; gap: 0;
margin-bottom: 8px;
border: 1px solid var(--rule);
}
.portrait-style-toggle button {
flex: 1; padding: 6px 4px;
font-family: var(--mono); font-size: 9px; letter-spacing: 0.18em;
text-transform: uppercase; color: var(--ink-mute);
background: transparent; border: none; cursor: pointer;
border-right: 1px solid var(--rule);
}
.portrait-style-toggle button:last-child { border-right: none; }
.portrait-style-toggle button.active {
background: var(--ink); color: var(--bg);
}
/* Responsive guard for very small windows */
@media (max-width: 1080px) {
.page { grid-template-columns: 1fr; }
.page-aside { border-top: 1px solid var(--rule); }
.page-main { border-right: none; }
}
/* Subtle paper edge */
.app-frame { border-radius: var(--radius); }
/* Trait hint hover popover */
.trait-trigger {
cursor: help;
border-bottom: 1px dotted var(--gild);
transition: color .15s, background .15s;
padding: 0 1px;
}
.trait-trigger:hover {
color: var(--gild);
background: color-mix(in oklab, var(--gild) 10%, transparent);
}
.trait-trigger.detriment {
border-bottom-color: var(--seal);
}
.trait-trigger.detriment:hover {
color: var(--seal);
background: color-mix(in oklab, var(--seal) 10%, transparent);
}
.trait-hint {
position: absolute;
z-index: 1000;
width: 320px;
max-width: calc(100vw - 16px);
background: var(--bg-2);
border: 1px solid var(--gild);
box-shadow:
0 0 0 1px color-mix(in oklab, var(--gild) 30%, transparent),
0 18px 40px -12px rgba(0,0,0,0.45);
padding: 14px 16px 12px;
color: var(--ink-soft);
font-family: var(--serif-body);
font-size: 14px;
line-height: 1.55;
pointer-events: auto;
animation: hint-in 0.14s ease-out;
}
.trait-hint.detriment {
border-color: var(--seal);
box-shadow:
0 0 0 1px color-mix(in oklab, var(--seal) 30%, transparent),
0 18px 40px -12px rgba(0,0,0,0.45);
}
.trait-hint::before {
content: "";
position: absolute;
top: -7px; left: var(--arrow-left, 18px);
width: 12px; height: 12px;
background: var(--bg-2);
border-top: 1px solid var(--gild);
border-left: 1px solid var(--gild);
transform: rotate(45deg);
}
.trait-hint.above::before {
top: auto;
bottom: -7px;
border-top: none;
border-left: none;
border-bottom: 1px solid var(--gild);
border-right: 1px solid var(--gild);
}
.trait-hint.detriment::before {
border-color: var(--seal);
}
.trait-hint.detriment.above::before {
border-top: none;
border-left: none;
border-bottom: 1px solid var(--seal);
border-right: 1px solid var(--seal);
}
.trait-hint-name {
font-family: var(--serif-display);
font-style: italic;
font-weight: 600;
font-size: 17px;
color: var(--ink);
margin-bottom: 6px;
display: flex; align-items: center; gap: 8px;
}
.trait-hint-tag {
font-family: var(--mono);
font-size: 9px; letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--seal);
border: 1px solid var(--seal);
padding: 2px 6px;
font-style: normal;
font-weight: 400;
}
.trait-hint-desc {
color: var(--ink-soft);
}
.trait-hint-reading {
margin-top: 8px;
padding-top: 8px;
border-top: 1px solid color-mix(in oklab, var(--rule) 50%, transparent);
color: var(--ink-mute);
font-style: italic;
font-size: 13px;
}
@keyframes hint-in {
from { opacity: 0; transform: translateY(-4px); }
to { opacity: 1; transform: translateY(0); }
}
/* Trait chips — for compact clade-card / sidebar trait listing */
.trait-chips {
display: flex; flex-wrap: wrap;
gap: 6px 6px;
margin-top: 10px;
}
.trait-chips .t-name {
font-family: var(--serif-display);
font-style: italic;
font-weight: 600;
color: var(--ink);
font-size: 13px;
line-height: 1.3;
white-space: nowrap;
display: inline-block;
margin-right: 0;
padding: 3px 9px;
border: 1px solid color-mix(in oklab, var(--gild) 55%, transparent);
background: color-mix(in oklab, var(--gild) 7%, var(--bg));
}
.trait-chips .t-name:hover {
background: color-mix(in oklab, var(--gild) 18%, var(--bg));
border-color: var(--gild);
}
.trait-chips .t-name.detriment {
border-color: color-mix(in oklab, var(--seal) 55%, transparent);
background: color-mix(in oklab, var(--seal) 8%, var(--bg));
color: var(--ink);
}
.trait-chips .t-name.detriment:hover {
background: color-mix(in oklab, var(--seal) 18%, var(--bg));
border-color: var(--seal);
}
/* The chip styling already creates visual separation, so kill the dotted underline inside chips */
.trait-chips .trait-trigger {
border-bottom: none;
}
/* Bonus pill — small inline +N badge next to ability names, hoverable */
.t-name.bonus-pill {
font-family: var(--mono);
font-style: normal;
font-weight: 500;
font-size: 11px;
letter-spacing: 0.06em;
line-height: 1;
padding: 3px 6px 3px 6px;
border: 1px solid var(--seal);
color: var(--seal);
background: color-mix(in oklab, var(--seal) 8%, transparent);
border-bottom: 1px solid var(--seal); /* override dotted */
cursor: help;
}
.t-name.bonus-pill.neg {
border-color: var(--ink-mute);
color: var(--ink-mute);
background: color-mix(in oklab, var(--ink-mute) 6%, transparent);
}
.t-name.bonus-pill:hover {
background: color-mix(in oklab, var(--seal) 18%, transparent);
}
.t-name.bonus-pill.neg:hover {
background: color-mix(in oklab, var(--ink-mute) 14%, transparent);
}
/* Language chips — a different palette so they read as different from traits */
.trait-chips.lang-chips .t-name {
font-style: normal;
font-family: var(--mono);
font-weight: 500;
font-size: 10px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--ink-soft);
border: 1px solid var(--rule);
background: transparent;
padding: 4px 9px;
}
.trait-chips.lang-chips .t-name::before {
content: "❝ ";
margin-right: 2px;
color: var(--ink-mute);
letter-spacing: 0;
}
.trait-chips.lang-chips .t-name:hover {
border-color: var(--ink-soft);
color: var(--ink);
background: color-mix(in oklab, var(--ink) 6%, transparent);
}
.trait-chips-label {
font-family: var(--mono); font-size: 9px; letter-spacing: 0.2em;
text-transform: uppercase; color: var(--ink-mute);
margin-top: 12px; margin-bottom: 4px;
}
/* Backgrounds extra styling */
.bg-card .flavor {
font-style: italic; color: var(--ink-soft); margin: 8px 0 10px;
line-height: 1.55; font-family: var(--serif-display); font-size: 14px;
}
.bg-card .feat-name {
font-family: var(--serif-display); font-style: italic; font-weight: 600;
color: var(--seal); font-size: 14px; margin-right: 6px;
}
/* Skills meta */
.skills-meta {
display: flex; align-items: center; justify-content: space-between;
margin: 16px 0 14px;
padding: 12px 14px;
border: 1px solid var(--rule); background: var(--bg-2);
}
.skills-meta .count {
font-family: var(--serif-display); font-size: 22px; color: var(--ink);
}
.skills-meta .count em { font-style: italic; color: var(--seal); }
/* Filters for species */
.species-filter {
display: flex; gap: 8px; flex-wrap: wrap;
margin-bottom: 16px;
}
.filter-chip {
font-family: var(--mono); font-size: 10px; letter-spacing: 0.18em;
text-transform: uppercase;
padding: 5px 10px; border: 1px solid var(--rule);
color: var(--ink-soft); background: transparent;
cursor: pointer;
}
.filter-chip.active { background: var(--ink); color: var(--bg); border-color: var(--ink); }
</style>
<!-- React + Babel -->
<script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
<script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
<script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600&family=Crimson+Pro:ital,wght@0,400;0,500;0,600;1,400&family=EB+Garamond:ital,wght@0,400;0,500;0,600;1,400&family=Cinzel:wght@400;500;600&family=Spectral:ital,wght@0,400;0,500;0,600;1,400&family=Uncial+Antiqua&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
</head>
<body>
<div id="app"></div>
<script type="text/babel" src="src/sigils.jsx"></script>
<script type="text/babel" src="src/data.jsx"></script>
<script type="text/babel" src="src/trait-hint.jsx"></script>
<script type="text/babel" src="src/portrait.jsx"></script>
<script type="text/babel" src="src/steps.jsx"></script>
<script type="text/babel" src="src/app.jsx"></script>
<script type="text/babel" src="tweaks-panel.jsx"></script>
<script type="text/babel" src="src/tweaks.jsx"></script>
<script type="text/babel" src="src/main.jsx"></script>
</body>
</html>