diff --git a/fabula-ultima-sheet.css b/fabula-ultima-sheet.css new file mode 100644 index 0000000..4ad7cb5 --- /dev/null +++ b/fabula-ultima-sheet.css @@ -0,0 +1,1010 @@ +:root { + --bg: #0d0f0e; + --surface: #141816; + --surface2: #1b1f1d; + --surface3: #222826; + --border: #2e3830; + --border-bright: #3d4f47; + --teal: #4ecdc4; + --teal-dim: #2a6b66; + --gold: #c9a84c; + --gold-dim: #7a6130; + --red: #c0392b; + --text: #d4cfc4; + --text-dim: #7a8a82; + --text-bright: #ede8dc; + --crisis: #e74c3c; + --font-display: 'Cinzel', serif; + --font-body: 'Crimson Text', serif; + --font-mono: 'Inconsolata', monospace; +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + background: var(--bg); + color: var(--text); + font-family: var(--font-body); + font-size: 16px; + min-height: 100vh; + background-image: + radial-gradient(ellipse at 20% 10%, rgba(78, 205, 196, 0.04) 0%, transparent 50%), + radial-gradient(ellipse at 80% 90%, rgba(201, 168, 76, 0.04) 0%, transparent 50%); +} + +/* ── HEADER ─────────────────────────────────────── */ +header { + background: linear-gradient(135deg, var(--surface) 0%, #0f1614 100%); + border-bottom: 1px solid var(--border-bright); + padding: 20px 32px; + display: flex; + align-items: center; + justify-content: space-between; + position: sticky; + top: 0; + z-index: 100; + box-shadow: 0 4px 24px rgba(0, 0, 0, 0.5); +} + +.logo { + font-family: var(--font-display); + font-size: 1.1rem; + color: var(--teal); + letter-spacing: 0.15em; + text-transform: uppercase; + display: flex; + align-items: center; + gap: 10px; +} + +.logo::before { + content: '✦'; + color: var(--gold); + font-size: 0.9em; +} + +.tabs { + display: flex; + gap: 4px; +} + +.tab { + font-family: var(--font-display); + font-size: 0.65rem; + letter-spacing: 0.12em; + text-transform: uppercase; + padding: 7px 16px; + border: 1px solid var(--border); + background: transparent; + color: var(--text-dim); + cursor: pointer; + transition: all 0.2s; +} + +.tab:hover { + border-color: var(--teal-dim); + color: var(--teal); +} + +.tab.active { + background: var(--teal-dim); + border-color: var(--teal); + color: var(--text-bright); +} + +/* ── LAYOUT ──────────────────────────────────────── */ +.page { + display: none; + padding: 28px 32px; + max-width: 1400px; + margin: 0 auto; +} + +.page.active { + display: block; + animation: fadeIn 0.3s ease; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(6px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +.grid-2 { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 20px; +} + +.grid-3 { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + gap: 20px; +} + +.col-span-2 { + grid-column: span 2; +} + +/* ── SECTION ─────────────────────────────────────── */ +.section { + background: var(--surface); + border: 1px solid var(--border); + padding: 18px 20px; + position: relative; +} + +.section::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 3px; + height: 100%; + background: var(--teal-dim); +} + +.section-title { + font-family: var(--font-display); + font-size: 0.6rem; + letter-spacing: 0.2em; + text-transform: uppercase; + color: var(--teal); + margin-bottom: 14px; + padding-bottom: 8px; + border-bottom: 1px solid var(--border); + display: flex; + align-items: center; + gap: 8px; +} + +.section-title .icon { + color: var(--gold); +} + +/* ── FIELDS ──────────────────────────────────────── */ +.field { + margin-bottom: 14px; +} + +.field:last-child { + margin-bottom: 0; +} + +label { + display: block; + font-family: var(--font-display); + font-size: 0.55rem; + letter-spacing: 0.18em; + text-transform: uppercase; + color: var(--text-dim); + margin-bottom: 5px; +} + +input[type="text"], +input[type="number"], +textarea, +select { + width: 100%; + background: var(--surface2); + border: 1px solid var(--border); + color: var(--text-bright); + font-family: var(--font-body); + font-size: 1rem; + padding: 8px 11px; + outline: none; + transition: border-color 0.2s, box-shadow 0.2s; + -webkit-appearance: none; +} + +input[type="text"]:focus, +input[type="number"]:focus, +textarea:focus, +select:focus { + border-color: var(--teal); + box-shadow: 0 0 0 2px rgba(78, 205, 196, 0.12); +} + +textarea { + resize: vertical; + min-height: 70px; +} + +input[type="number"] { + font-family: var(--font-mono); +} + +.field-row { + display: flex; + gap: 12px; +} + +.field-row .field { + flex: 1; +} + +/* ── ATTRIBUTES ──────────────────────────────────── */ +.attr-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; +} + +.attr-block { + background: var(--surface2); + border: 1px solid var(--border); + padding: 12px 14px; + display: flex; + flex-direction: column; + gap: 8px; +} + +.attr-name { + font-family: var(--font-display); + font-size: 0.65rem; + letter-spacing: 0.15em; + text-transform: uppercase; + color: var(--gold); +} + +.attr-inputs { + display: flex; + gap: 8px; + align-items: center; +} + +.attr-inputs input { + font-family: var(--font-mono); + font-size: 1.2rem; + text-align: center; + width: 52px; + flex-shrink: 0; +} + +.attr-sep { + color: var(--text-dim); + font-size: 0.8rem; +} + +/* ── STATUS EFFECTS ──────────────────────────────── */ +.status-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 8px; +} + +.status-item { + display: flex; + align-items: center; + gap: 8px; + cursor: pointer; + padding: 7px 10px; + border: 1px solid var(--border); + background: var(--surface2); + transition: all 0.15s; + user-select: none; +} + +.status-item:hover { + border-color: var(--border-bright); +} + +.status-item.active-status { + border-color: var(--red); + background: rgba(192, 57, 43, 0.12); +} + +.status-check { + width: 14px; + height: 14px; + border: 1px solid var(--border-bright); + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + font-size: 0.7rem; + color: var(--red); + transition: all 0.15s; +} + +.status-item.active-status .status-check { + border-color: var(--red); + background: rgba(192, 57, 43, 0.2); +} + +.status-label { + font-family: var(--font-display); + font-size: 0.58rem; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--text-dim); +} + +.status-item.active-status .status-label { + color: var(--crisis); +} + +/* ── HP / MP / IP ────────────────────────────────── */ +.vital-block { + display: flex; + align-items: center; + gap: 16px; + background: var(--surface2); + border: 1px solid var(--border); + padding: 14px 16px; + margin-bottom: 10px; +} + +.vital-block:last-child { + margin-bottom: 0; +} + +.vital-label { + font-family: var(--font-display); + font-size: 1.2rem; + font-weight: 700; + width: 32px; + flex-shrink: 0; +} + +.vital-label.hp { + color: var(--red); +} + +.vital-label.mp { + color: var(--teal); +} + +.vital-label.ip { + color: var(--gold); +} + +.vital-inputs { + display: flex; + gap: 8px; + flex: 1; + align-items: center; +} + +.vital-inputs input { + text-align: center; + font-family: var(--font-mono); + font-size: 1.1rem; +} + +.vital-sep { + color: var(--text-dim); + font-size: 0.8rem; + flex-shrink: 0; +} + +.vital-formula { + font-size: 0.75rem; + color: var(--text-dim); + font-family: var(--font-mono); +} + +.crisis-badge { + font-family: var(--font-display); + font-size: 0.5rem; + letter-spacing: 0.15em; + text-transform: uppercase; + color: var(--crisis); + border: 1px solid var(--crisis); + padding: 2px 6px; + flex-shrink: 0; +} + +/* ── LEVEL / XP ──────────────────────────────────── */ +.level-display { + text-align: center; + padding: 20px; + background: var(--surface2); + border: 1px solid var(--border); +} + +.level-num { + font-family: var(--font-display); + font-size: 3.5rem; + color: var(--gold); + line-height: 1; + display: block; +} + +.level-text { + font-family: var(--font-display); + font-size: 0.55rem; + letter-spacing: 0.25em; + color: var(--text-dim); + text-transform: uppercase; + display: block; + margin-top: 4px; +} + +.xp-bar-wrap { + margin-top: 14px; + background: var(--surface3); + border: 1px solid var(--border); + height: 8px; + position: relative; + overflow: hidden; +} + +.xp-bar { + height: 100%; + background: linear-gradient(90deg, var(--gold-dim), var(--gold)); + transition: width 0.5s ease; +} + +.xp-label { + font-family: var(--font-mono); + font-size: 0.75rem; + color: var(--text-dim); + display: flex; + justify-content: space-between; + margin-top: 5px; +} + +/* ── FABULA POINTS ───────────────────────────────── */ +.fp-pips { + display: flex; + gap: 6px; + flex-wrap: wrap; + margin-top: 10px; +} + +.fp-pip { + width: 28px; + height: 28px; + border: 2px solid var(--border-bright); + border-radius: 50%; + cursor: pointer; + transition: all 0.15s; + background: var(--surface2); + display: flex; + align-items: center; + justify-content: center; +} + +.fp-pip.filled { + background: var(--teal); + border-color: var(--teal); + box-shadow: 0 0 8px rgba(78, 205, 196, 0.4); +} + +.fp-pip:hover { + border-color: var(--teal); +} + +.fp-rules { + margin-top: 14px; + border-top: 1px solid var(--border); + padding-top: 12px; +} + +.fp-rule { + font-size: 0.85rem; + color: var(--text-dim); + padding: 3px 0; + padding-left: 12px; + position: relative; +} + +.fp-rule::before { + content: '✦'; + position: absolute; + left: 0; + font-size: 0.5rem; + color: var(--gold); + top: 5px; +} + +.fp-rule strong { + color: var(--text); +} + +/* ── BONDS ───────────────────────────────────────── */ +.bond-block { + border: 1px solid var(--border); + padding: 14px; + background: var(--surface2); + margin-bottom: 10px; +} + +.bond-block:last-child { + margin-bottom: 0; +} + +.bond-header { + display: flex; + gap: 10px; + align-items: center; + margin-bottom: 10px; +} + +.bond-num { + font-family: var(--font-display); + font-size: 0.6rem; + color: var(--gold); + border: 1px solid var(--gold-dim); + width: 22px; + height: 22px; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.bond-header input { + flex: 1; +} + +.bond-feelings { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 5px; +} + +.bond-feeling { + display: flex; + align-items: center; + gap: 5px; + cursor: pointer; + font-size: 0.8rem; + color: var(--text-dim); + user-select: none; +} + +.bond-feeling.active { + color: var(--teal); +} + +.bond-feeling-box { + width: 12px; + height: 12px; + border: 1px solid var(--border-bright); + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + font-size: 0.6rem; + transition: all 0.15s; +} + +.bond-feeling.active .bond-feeling-box { + background: var(--teal); + border-color: var(--teal); + color: #000; +} + +/* ── EQUIPMENT ───────────────────────────────────── */ +.equip-row { + display: grid; + grid-template-columns: 120px 1fr; + gap: 0; + border-bottom: 1px solid var(--border); +} + +.equip-row:last-child { + border-bottom: none; +} + +.equip-slot { + font-family: var(--font-display); + font-size: 0.55rem; + letter-spacing: 0.15em; + text-transform: uppercase; + color: var(--gold); + background: var(--surface3); + padding: 10px 12px; + border-right: 1px solid var(--border); + display: flex; + align-items: center; +} + +.equip-fields { + display: flex; + flex-direction: column; + gap: 0; +} + +.equip-fields input { + border: none; + border-bottom: 1px solid var(--border); + font-size: 0.9rem; + padding: 7px 10px; +} + +.equip-fields input:last-child { + border-bottom: none; +} + +.equip-fields input::placeholder { + color: var(--border-bright); + font-style: italic; +} + +/* ── MARTIAL CHECKBOXES ──────────────────────────── */ +.martial-row { + display: flex; + gap: 16px; + flex-wrap: wrap; + margin-top: 10px; +} + +.martial-item { + display: flex; + align-items: center; + gap: 6px; + cursor: pointer; + user-select: none; +} + +.martial-box { + width: 14px; + height: 14px; + border: 1px solid var(--border-bright); + display: flex; + align-items: center; + justify-content: center; + font-size: 0.65rem; + color: var(--teal); + transition: all 0.15s; +} + +.martial-item.checked .martial-box { + background: var(--teal-dim); + border-color: var(--teal); +} + +.martial-item span { + font-family: var(--font-display); + font-size: 0.55rem; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--text-dim); +} + +/* ── CLASSES ─────────────────────────────────────── */ +.class-block { + border: 1px solid var(--border); + background: var(--surface2); + margin-bottom: 12px; +} + +.class-block:last-child { + margin-bottom: 0; +} + +.class-header { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 0; + border-bottom: 1px solid var(--border); +} + +.class-header input { + border: none; + border-right: 1px solid var(--border); + font-size: 0.9rem; +} + +.class-header input:last-child { + border-right: none; +} + +.class-skills { + padding: 0; +} + +.class-skills textarea { + border: none; + font-size: 0.85rem; + min-height: 80px; + background: transparent; +} + +/* ── SPELLS TABLE ────────────────────────────────── */ +.spells-table { + width: 100%; + border-collapse: collapse; +} + +.spells-table thead tr { + background: var(--surface3); +} + +.spells-table th { + font-family: var(--font-display); + font-size: 0.52rem; + letter-spacing: 0.15em; + text-transform: uppercase; + color: var(--teal); + padding: 8px 10px; + text-align: left; + border-bottom: 1px solid var(--border-bright); +} + +.spells-table td { + border-bottom: 1px solid var(--border); + vertical-align: top; +} + +.spells-table td input, +.spells-table td textarea { + border: none; + font-size: 0.9rem; + min-height: 32px; + padding: 6px 8px; +} + +.spells-table td textarea { + min-height: 55px; +} + +.spell-name-col { + width: 35%; +} + +.spell-mp-col { + width: 12%; +} + +.spell-targets-col { + width: 18%; +} + +.spell-dur-col { + width: 18%; +} + +.spell-del-col { + width: 40px; +} + +.spell-del-btn { + background: none; + border: none; + color: var(--text-dim); + cursor: pointer; + padding: 6px 8px; + font-size: 0.9rem; + transition: color 0.15s; +} + +.spell-del-btn:hover { + color: var(--red); +} + +.add-btn { + margin-top: 8px; + font-family: var(--font-display); + font-size: 0.55rem; + letter-spacing: 0.15em; + text-transform: uppercase; + color: var(--teal); + background: transparent; + border: 1px solid var(--teal-dim); + padding: 6px 14px; + cursor: pointer; + transition: all 0.15s; + display: inline-flex; + align-items: center; + gap: 6px; +} + +.add-btn:hover { + background: var(--teal-dim); + color: var(--text-bright); +} + +/* ── DISCIPLINES ─────────────────────────────────── */ +.disciplines-row { + display: flex; + gap: 12px; + flex-wrap: wrap; + margin-bottom: 14px; +} + +.disc-item { + display: flex; + align-items: center; + gap: 6px; + cursor: pointer; + user-select: none; +} + +.disc-box { + width: 13px; + height: 13px; + border: 1px solid var(--border-bright); + display: flex; + align-items: center; + justify-content: center; + font-size: 0.6rem; + color: var(--gold); + transition: all 0.15s; +} + +.disc-item.checked .disc-box { + background: var(--gold-dim); + border-color: var(--gold); +} + +.disc-item span { + font-family: var(--font-display); + font-size: 0.55rem; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--text-dim); +} + +.disc-item.checked span { + color: var(--gold); +} + +/* ── SAVE / LOAD ─────────────────────────────────── */ +.toolbar { + display: flex; + gap: 8px; + align-items: center; +} + +.btn-save, +.btn-load { + font-family: var(--font-display); + font-size: 0.55rem; + letter-spacing: 0.15em; + text-transform: uppercase; + padding: 7px 16px; + cursor: pointer; + border: 1px solid var(--gold-dim); + background: transparent; + color: var(--gold); + transition: all 0.2s; +} + +.btn-save:hover { + background: var(--gold-dim); + color: var(--text-bright); +} + +.btn-load { + border-color: var(--border-bright); + color: var(--text-dim); +} + +.btn-load:hover { + border-color: var(--teal-dim); + color: var(--teal); +} + +.btn-export { + border-color: var(--teal-dim); + color: var(--teal); +} + +.btn-export:hover { + background: var(--teal-dim); + color: var(--text-bright); +} + +.btn-import { + border-color: var(--border-bright); + color: var(--text-dim); +} + +.btn-import:hover { + border-color: var(--gold-dim); + color: var(--gold); +} + +.toolbar-sep { + width: 1px; + height: 20px; + background: var(--border); + margin: 0 4px; +} + +.save-status { + font-family: var(--font-mono); + font-size: 0.7rem; + color: var(--teal); + opacity: 0; + transition: opacity 0.3s; +} + +.save-status.show { + opacity: 1; +} + +/* ── ORNAMENTS ───────────────────────────────────── */ +.ornament { + text-align: center; + color: var(--gold-dim); + font-size: 0.8rem; + letter-spacing: 0.5em; + margin: 8px 0; +} + +.def-row { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 10px; + margin-bottom: 14px; +} + +.def-block { + background: var(--surface2); + border: 1px solid var(--border); + padding: 10px 12px; + text-align: center; +} + +.def-block label { + display: block; + margin-bottom: 6px; +} + +.def-block input { + text-align: center; + font-family: var(--font-mono); + font-size: 1.2rem; + font-weight: 600; +} + +/* ── RESPONSIVE ──────────────────────────────────── */ +@media (max-width: 900px) { + + .grid-2, + .grid-3 { + grid-template-columns: 1fr; + } + + .col-span-2 { + grid-column: span 1; + } + + header { + flex-direction: column; + gap: 12px; + } + + .tabs { + flex-wrap: wrap; + } +} + +/* ── TOOLTIP ─────────────────────────────────────── */ +[title] { + cursor: help; +} + +/* scrollbar */ +::-webkit-scrollbar { + width: 6px; + height: 6px; +} + +::-webkit-scrollbar-track { + background: var(--bg); +} + +::-webkit-scrollbar-thumb { + background: var(--border-bright); +} + +::-webkit-scrollbar-thumb:hover { + background: var(--teal-dim); +} diff --git a/fabula-ultima-sheet.html b/fabula-ultima-sheet.html index 8ab8beb..7356d8e 100644 --- a/fabula-ultima-sheet.html +++ b/fabula-ultima-sheet.html @@ -8,1018 +8,7 @@ - +