Medieval visual theme with 4 switchable color schemes

- Cinzel + Alegreya fonts for old-tome D&D book feel
- Dark parchment (default), light parchment, white, and abyss themes
- CSS custom properties system for all colors, borders, shadows
- Generated PNG textures for parchment grain, speckle, and wood grain
- Ornamental gold gradient separators and decorative header lines
- Deep dramatic shadows and gold-tinted borders on all panels
- ThemeToggle component with localStorage persistence
- Embossed gold buttons with gradient and inner shadow

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Aaron Wood 2026-04-09 17:06:50 -04:00
parent f552a475c1
commit ff9203f754
35 changed files with 996 additions and 359 deletions

View file

@ -1,9 +1,15 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Shadowdark Character Manager</title> <title>Shadowdark Character Manager</title>
<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=Alegreya:ital,wght@0,400;0,500;0,600;0,700;1,400&family=Cinzel:wght@400;500;600;700&display=swap"
rel="stylesheet"
/>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View file

@ -5,9 +5,21 @@
} }
body { body {
font-family: "Segoe UI", system-ui, -apple-system, sans-serif; font-family: "Alegreya", Georgia, serif;
background: #1a1a2e; background-color: var(--bg-body);
color: #e0e0e0; background-image:
radial-gradient(
ellipse at center,
var(--bg-body-vignette) 0%,
transparent 70%
),
var(--texture-body), var(--texture-speckle);
background-size:
100% 100%,
512px 512px,
128px 128px;
background-repeat: no-repeat, repeat, repeat;
color: var(--text-primary);
min-height: 100vh; min-height: 100vh;
} }
@ -19,14 +31,42 @@ body {
.header { .header {
text-align: center; text-align: center;
padding: 1rem 0; padding: 1.25rem 0;
border-bottom: 1px solid #333;
margin-bottom: 1.5rem; margin-bottom: 1.5rem;
position: relative;
z-index: 9999;
}
.header::before,
.header::after {
content: "";
display: block;
height: 1px;
background: linear-gradient(
90deg,
transparent 10%,
rgba(var(--gold-rgb), 0.3) 35%,
rgba(var(--gold-rgb), 0.5) 50%,
rgba(var(--gold-rgb), 0.3) 65%,
transparent 90%
);
}
.header::before {
margin-bottom: 1rem;
}
.header::after {
margin-top: 0.5rem;
} }
.header h1 { .header h1 {
font-size: 1.8rem; font-family: "Cinzel", Georgia, serif;
color: #c9a84c; font-size: 2rem;
color: var(--gold);
font-variant: small-caps; font-variant: small-caps;
letter-spacing: 0.05em; letter-spacing: 0.15em;
text-shadow:
0 0 30px rgba(var(--gold-rgb), 0.25),
0 2px 4px rgba(var(--shadow-rgb), 0.5);
} }

View file

@ -1,6 +1,7 @@
import { BrowserRouter, Routes, Route } from "react-router-dom"; import { BrowserRouter, Routes, Route } from "react-router-dom";
import CampaignList from "./pages/CampaignList"; import CampaignList from "./pages/CampaignList";
import CampaignView from "./pages/CampaignView"; import CampaignView from "./pages/CampaignView";
import ThemeToggle from "./components/ThemeToggle";
import styles from "./App.module.css"; import styles from "./App.module.css";
export default function App() { export default function App() {
@ -9,6 +10,7 @@ export default function App() {
<div className={styles.app}> <div className={styles.app}>
<header className={styles.header}> <header className={styles.header}>
<h1>Shadowdark</h1> <h1>Shadowdark</h1>
<ThemeToggle />
</header> </header>
<Routes> <Routes>
<Route path="/" element={<CampaignList />} /> <Route path="/" element={<CampaignList />} />

View file

@ -5,28 +5,31 @@
} }
.label { .label {
font-family: "Cinzel", Georgia, serif;
font-size: 0.75rem; font-size: 0.75rem;
color: #888; color: var(--text-secondary);
text-transform: uppercase; text-transform: uppercase;
font-weight: 600; font-weight: 600;
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.3);
} }
.value { .value {
font-family: "Cinzel", Georgia, serif;
font-size: 1.4rem; font-size: 1.4rem;
font-weight: 700; font-weight: 700;
color: #5dade2; color: var(--ac);
cursor: pointer; cursor: pointer;
min-width: 2rem; min-width: 2rem;
text-align: center; text-align: center;
} }
.value.overridden { .value.overridden {
color: #c9a84c; color: var(--gold);
} }
.source { .source {
font-size: 0.7rem; font-size: 0.7rem;
color: #666; color: var(--text-tertiary);
} }
.override { .override {
@ -37,30 +40,31 @@
.overrideIndicator { .overrideIndicator {
font-size: 0.65rem; font-size: 0.65rem;
color: #c9a84c; color: var(--gold);
cursor: pointer; cursor: pointer;
background: rgba(201, 168, 76, 0.15); background: rgba(var(--gold-rgb), 0.15);
border: none; border: none;
border-radius: 3px; border-radius: 3px;
padding: 0.1rem 0.3rem; padding: 0.1rem 0.3rem;
} }
.overrideIndicator:hover { .overrideIndicator:hover {
background: rgba(201, 168, 76, 0.3); background: rgba(var(--gold-rgb), 0.3);
} }
.calculatedHint { .calculatedHint {
font-size: 0.65rem; font-size: 0.65rem;
color: #555; color: var(--text-faint);
} }
.editInput { .editInput {
width: 3rem; width: 3rem;
padding: 0.2rem 0.3rem; padding: 0.2rem 0.3rem;
background: #0f1a30; background: var(--bg-inset);
border: 1px solid #c9a84c; border: 1px solid rgba(var(--gold-rgb), 0.2);
border-radius: 4px; border-radius: 4px;
color: #e0e0e0; color: var(--text-primary);
font-family: "Cinzel", Georgia, serif;
font-size: 1.2rem; font-size: 1.2rem;
font-weight: 700; font-weight: 700;
text-align: center; text-align: center;

View file

@ -3,12 +3,14 @@
} }
.title { .title {
font-family: "Cinzel", Georgia, serif;
font-size: 0.9rem; font-size: 0.9rem;
font-weight: 700; font-weight: 700;
color: #c9a84c; color: var(--gold);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.05em; letter-spacing: 0.05em;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.3);
} }
.list { .list {
@ -21,40 +23,43 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
background: #0f1a30; background: var(--bg-inset);
border-radius: 6px; border-radius: 4px;
padding: 0.35rem 0.6rem; padding: 0.35rem 0.6rem;
font-size: 0.85rem; font-size: 0.85rem;
border-left: 2px solid rgba(var(--gold-rgb), 0.2);
} }
.weaponName { .weaponName {
font-family: "Cinzel", Georgia, serif;
font-weight: 700; font-weight: 700;
text-transform: uppercase; text-transform: uppercase;
color: #e0e0e0; color: var(--text-primary);
letter-spacing: 0.03em;
} }
.stats { .stats {
color: #888; color: var(--text-secondary);
} }
.modifier { .modifier {
color: #c9a84c; color: var(--gold);
font-weight: 600; font-weight: 600;
} }
.damage { .damage {
color: #e0e0e0; color: var(--text-primary);
} }
.tags { .tags {
font-size: 0.7rem; font-size: 0.7rem;
color: #666; color: var(--text-tertiary);
margin-left: 0.3rem; margin-left: 0.3rem;
} }
.talentLine { .talentLine {
font-style: italic; font-style: italic;
color: #888; color: var(--text-secondary);
font-size: 0.8rem; font-size: 0.8rem;
padding: 0.25rem 0.6rem; padding: 0.25rem 0.6rem;
} }
@ -62,7 +67,7 @@
.rollSpace { .rollSpace {
width: 2.5rem; width: 2.5rem;
text-align: center; text-align: center;
color: #444; color: var(--text-faint);
font-size: 0.75rem; font-size: 0.75rem;
} }
@ -73,6 +78,6 @@
.empty { .empty {
font-size: 0.8rem; font-size: 0.8rem;
color: #555; color: var(--text-faint);
font-style: italic; font-style: italic;
} }

View file

@ -1,17 +1,32 @@
.card { .card {
background: #16213e; background-color: var(--bg-surface);
border: 1px solid #333; background-image: var(--texture-surface), var(--texture-speckle);
border-radius: 10px; background-size:
256px 256px,
128px 128px;
background-repeat: repeat, repeat;
border: 1px solid rgba(var(--gold-rgb), 0.2);
border-radius: 4px;
padding: 1rem; padding: 1rem;
cursor: pointer; cursor: pointer;
box-shadow:
0 4px 12px rgba(var(--shadow-rgb), 0.5),
0 1px 4px rgba(var(--shadow-rgb), 0.3),
inset 0 1px 0 rgba(var(--gold-rgb), 0.06);
transition: transition:
border-color 0.15s, border-color 0.15s,
transform 0.1s; transform 0.1s,
box-shadow 0.15s;
} }
.card:hover { .card:hover {
border-color: #c9a84c; border-color: rgba(var(--gold-rgb), 0.5);
transform: translateY(-2px); transform: translateY(-2px);
box-shadow:
0 8px 20px rgba(var(--shadow-rgb), 0.6),
0 2px 6px rgba(var(--shadow-rgb), 0.4),
inset 0 1px 0 rgba(var(--gold-rgb), 0.1),
0 0 15px rgba(var(--gold-rgb), 0.05);
} }
.cardHeader { .cardHeader {
@ -22,19 +37,20 @@
} }
.name { .name {
font-family: "Cinzel", Georgia, serif;
font-size: 1.1rem; font-size: 1.1rem;
font-weight: 700; font-weight: 700;
color: #e0e0e0; color: var(--text-primary);
} }
.level { .level {
font-size: 0.8rem; font-size: 0.8rem;
color: #888; color: var(--text-secondary);
} }
.meta { .meta {
font-size: 0.8rem; font-size: 0.8rem;
color: #666; color: var(--text-tertiary);
margin-bottom: 0.75rem; margin-bottom: 0.75rem;
} }
@ -53,26 +69,27 @@
} }
.acLabel { .acLabel {
font-family: "Cinzel", Georgia, serif;
font-size: 0.75rem; font-size: 0.75rem;
color: #888; color: var(--text-secondary);
text-transform: uppercase; text-transform: uppercase;
font-weight: 600; font-weight: 600;
} }
.acValue { .acValue {
font-size: 1.1rem; font-size: 1.1rem;
color: #5dade2; color: var(--ac);
} }
.gearSummary { .gearSummary {
font-size: 0.75rem; font-size: 0.75rem;
color: #666; color: var(--text-tertiary);
text-align: right; text-align: right;
margin-top: 0.5rem; margin-top: 0.5rem;
} }
.xp { .xp {
font-size: 0.75rem; font-size: 0.75rem;
color: #888; color: var(--text-secondary);
text-align: right; text-align: right;
} }

View file

@ -1,7 +1,7 @@
.overlay { .overlay {
position: absolute; position: absolute;
inset: 0; inset: 0;
background: rgba(0, 0, 0, 0.7); background: var(--bg-overlay);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@ -10,9 +10,14 @@
} }
.modal { .modal {
background: #1a1a2e; background-color: var(--bg-modal);
border: 1px solid #333; background-image: var(--texture-surface), var(--texture-speckle);
border-radius: 12px; background-size:
256px 256px,
128px 128px;
background-repeat: repeat, repeat;
border: 2px solid rgba(var(--gold-rgb), 0.3);
border-radius: 4px;
width: 100%; width: 100%;
max-width: 900px; max-width: 900px;
max-height: 90vh; max-height: 90vh;
@ -20,7 +25,12 @@
overflow-x: hidden; overflow-x: hidden;
padding: 1.5rem; padding: 1.5rem;
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: #333 transparent; scrollbar-color: rgba(var(--gold-rgb), 0.2) transparent;
box-shadow:
0 8px 40px rgba(var(--shadow-rgb), 0.7),
0 2px 8px rgba(var(--shadow-rgb), 0.5),
inset 0 1px 0 rgba(var(--gold-rgb), 0.1),
inset 0 0 60px rgba(var(--shadow-rgb), 0.2);
} }
.modal::-webkit-scrollbar { .modal::-webkit-scrollbar {
@ -32,12 +42,12 @@
} }
.modal::-webkit-scrollbar-thumb { .modal::-webkit-scrollbar-thumb {
background: #333; background: rgba(var(--gold-rgb), 0.2);
border-radius: 3px; border-radius: 3px;
} }
.modal::-webkit-scrollbar-thumb:hover { .modal::-webkit-scrollbar-thumb:hover {
background: #555; background: rgba(var(--gold-rgb), 0.35);
} }
.topBar { .topBar {
@ -49,34 +59,39 @@
} }
.editBtn { .editBtn {
font-family: "Cinzel", Georgia, serif;
padding: 0.35rem 0.75rem; padding: 0.35rem 0.75rem;
background: transparent; background: transparent;
border: 1px solid #c9a84c; border: 1px solid rgba(var(--gold-rgb), 0.4);
border-radius: 5px; border-radius: 3px;
color: #c9a84c; color: var(--gold);
cursor: pointer; cursor: pointer;
font-size: 0.8rem; font-size: 0.8rem;
font-weight: 600; font-weight: 600;
letter-spacing: 0.05em;
transition: all 0.15s;
} }
.editBtn:hover { .editBtn:hover {
background: rgba(201, 168, 76, 0.15); background: rgba(var(--gold-rgb), 0.1);
box-shadow: 0 0 8px rgba(var(--gold-rgb), 0.15);
} }
.editBtn.active { .editBtn.active {
background: #c9a84c; background: rgba(var(--gold-rgb), 0.9);
color: #1a1a2e; color: var(--btn-active-text);
text-shadow: none;
} }
.closeBtn { .closeBtn {
background: none; background: none;
border: none; border: none;
color: #888; color: var(--text-secondary);
font-size: 1.5rem; font-size: 1.5rem;
cursor: pointer; cursor: pointer;
padding: 0.25rem 0.5rem; padding: 0.25rem 0.5rem;
} }
.closeBtn:hover { .closeBtn:hover {
color: #e0e0e0; color: var(--text-primary);
} }

View file

@ -2,11 +2,20 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
background: linear-gradient(135deg, #16213e, #0f1a30); background-color: var(--bg-surface);
border: 1px solid #333; background-image: var(--texture-surface), var(--texture-speckle);
border-radius: 8px; background-size:
256px 256px,
128px 128px;
background-repeat: repeat, repeat;
border: 1px solid rgba(var(--gold-rgb), 0.3);
border-radius: 4px;
padding: 0.75rem 1rem; padding: 0.75rem 1rem;
margin-bottom: 1rem; margin-bottom: 1rem;
box-shadow:
0 3px 12px rgba(var(--shadow-rgb), 0.4),
inset 0 1px 0 rgba(var(--gold-rgb), 0.1),
inset 0 0 20px rgba(var(--shadow-rgb), 0.15);
} }
.identity { .identity {
@ -14,18 +23,20 @@
} }
.name { .name {
font-family: "Cinzel", Georgia, serif;
font-size: 1.4rem; font-size: 1.4rem;
font-weight: 700; font-weight: 700;
color: #c9a84c; color: var(--gold);
letter-spacing: 0.03em;
} }
.title { .title {
color: #888; color: var(--text-secondary);
font-size: 0.9rem; font-size: 0.9rem;
} }
.subtitle { .subtitle {
color: #666; color: var(--text-tertiary);
font-size: 0.8rem; font-size: 0.8rem;
margin-top: 0.15rem; margin-top: 0.15rem;
} }
@ -46,16 +57,17 @@
} }
.hp { .hp {
color: #4caf50; color: var(--hp);
} }
.ac { .ac {
color: #5dade2; color: var(--ac);
} }
.vitalLabel { .vitalLabel {
font-family: "Cinzel", Georgia, serif;
font-size: 0.75rem; font-size: 0.75rem;
color: #888; color: var(--text-secondary);
text-transform: uppercase; text-transform: uppercase;
font-weight: 600; font-weight: 600;
} }
@ -67,37 +79,38 @@
} }
.hpSlash { .hpSlash {
color: #666; color: var(--text-tertiary);
font-size: 0.9rem; font-size: 0.9rem;
} }
.hpMax { .hpMax {
color: #888; color: var(--text-secondary);
font-weight: 600; font-weight: 600;
} }
.hpBonus { .hpBonus {
color: #4caf50; color: var(--hp);
font-size: 0.65rem; font-size: 0.65rem;
margin-left: 0.15rem; margin-left: 0.15rem;
} }
.xpThreshold { .xpThreshold {
font-size: 0.75rem; font-size: 0.75rem;
color: #666; color: var(--text-tertiary);
} }
.xpCurrent { .xpCurrent {
color: #c9a84c; color: var(--gold);
font-weight: 600; font-weight: 600;
} }
.nameInput { .nameInput {
font-family: "Cinzel", Georgia, serif;
font-size: 1.3rem; font-size: 1.3rem;
font-weight: 700; font-weight: 700;
color: #c9a84c; color: var(--gold);
background: #0f1a30; background: var(--bg-input);
border: 1px solid #333; border: 1px solid rgba(var(--gold-rgb), 0.2);
border-radius: 5px; border-radius: 5px;
padding: 0.2rem 0.4rem; padding: 0.2rem 0.4rem;
width: 10rem; width: 10rem;
@ -105,23 +118,24 @@
.nameInput:focus { .nameInput:focus {
outline: none; outline: none;
border-color: #c9a84c; border-color: var(--gold);
} }
.titleInput { .titleInput {
font-size: 0.85rem; font-size: 0.85rem;
color: #888; color: var(--text-secondary);
background: #0f1a30; background: var(--bg-input);
border: 1px solid #333; border: 1px solid rgba(var(--gold-rgb), 0.2);
border-radius: 5px; border-radius: 5px;
padding: 0.15rem 0.4rem; padding: 0.15rem 0.4rem;
width: 8rem; width: 8rem;
margin-left: 0.3rem; margin-left: 0.3rem;
font-family: "Alegreya", Georgia, serif;
} }
.titleInput:focus { .titleInput:focus {
outline: none; outline: none;
border-color: #c9a84c; border-color: var(--gold);
} }
.panels { .panels {
@ -145,19 +159,19 @@
.deleteSection { .deleteSection {
margin-top: 1rem; margin-top: 1rem;
padding-top: 0.75rem; padding-top: 0.75rem;
border-top: 1px solid #333; border-top: 1px solid rgba(var(--gold-rgb), 0.15);
} }
.deleteBtn { .deleteBtn {
padding: 0.4rem 0.75rem; padding: 0.4rem 0.75rem;
background: transparent; background: transparent;
border: 1px solid #e74c3c; border: 1px solid var(--danger);
border-radius: 5px; border-radius: 5px;
color: #e74c3c; color: var(--danger);
cursor: pointer; cursor: pointer;
font-size: 0.8rem; font-size: 0.8rem;
} }
.deleteBtn:hover { .deleteBtn:hover {
background: rgba(231, 76, 60, 0.1); background: rgba(var(--danger-rgb), 0.1);
} }

View file

@ -12,44 +12,47 @@
} }
.coinLabel { .coinLabel {
font-family: "Cinzel", Georgia, serif;
font-size: 0.75rem; font-size: 0.75rem;
font-weight: 600; font-weight: 600;
text-transform: uppercase; text-transform: uppercase;
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.3);
} }
.gp { .gp {
color: #c9a84c; color: var(--gold);
} }
.sp { .sp {
color: #a0a0a0; color: var(--silver);
} }
.cp { .cp {
color: #b87333; color: var(--copper);
} }
.coinInput { .coinInput {
width: 3.5rem; width: 3.5rem;
padding: 0.25rem 0.4rem; padding: 0.25rem 0.4rem;
background: #0f1a30; background: var(--bg-inset);
border: 1px solid #333; border: 1px solid rgba(var(--gold-rgb), 0.15);
border-radius: 4px; border-radius: 4px;
color: #e0e0e0; color: var(--text-primary);
font-size: 0.85rem; font-size: 0.85rem;
text-align: center; text-align: center;
font-family: "Alegreya", Georgia, serif;
} }
.coinInput:focus { .coinInput:focus {
outline: none; outline: none;
border-color: #c9a84c; border-color: var(--gold);
} }
.coinBtn { .coinBtn {
width: 20px; width: 20px;
height: 20px; height: 20px;
border-radius: 50%; border-radius: 50%;
border: 1px solid #444; border: 1px solid rgba(var(--gold-rgb), 0.25);
background: #16213e; background: var(--bg-inset);
color: #e0e0e0; color: var(--text-primary);
cursor: pointer; cursor: pointer;
font-size: 0.75rem; font-size: 0.75rem;
display: flex; display: flex;
@ -58,8 +61,8 @@
} }
.coinBtn:hover { .coinBtn:hover {
border-color: #c9a84c; border-color: var(--gold);
color: #c9a84c; color: var(--gold);
} }
.coinValue { .coinValue {

View file

@ -2,9 +2,9 @@
width: 22px; width: 22px;
height: 22px; height: 22px;
border-radius: 4px; border-radius: 4px;
border: 1px solid #444; border: 1px solid rgba(var(--gold-rgb), 0.25);
background: #16213e; background: var(--bg-inset);
color: #888; color: var(--text-secondary);
cursor: pointer; cursor: pointer;
font-size: 0.75rem; font-size: 0.75rem;
display: flex; display: flex;
@ -13,31 +13,37 @@
transition: transition:
border-color 0.15s, border-color 0.15s,
color 0.15s, color 0.15s,
background 0.15s; background 0.15s,
box-shadow 0.15s;
box-shadow: inset 0 1px 2px rgba(var(--shadow-rgb), 0.3);
} }
.btn:hover { .btn:hover {
border-color: #c9a84c; border-color: rgba(var(--gold-rgb), 0.6);
color: #c9a84c; color: var(--gold);
background: rgba(201, 168, 76, 0.1); background: rgba(var(--gold-rgb), 0.08);
box-shadow:
0 0 6px rgba(var(--gold-rgb), 0.15),
inset 0 1px 2px rgba(var(--shadow-rgb), 0.2);
} }
.btn:active { .btn:active {
background: rgba(201, 168, 76, 0.25); background: rgba(var(--gold-rgb), 0.15);
} }
.btn.crit { .btn.crit {
border-color: #ffd700; border-color: var(--crit);
color: #ffd700; color: var(--crit);
animation: critPulse 1s ease-in-out infinite; animation: critPulse 1s ease-in-out infinite;
box-shadow: 0 0 8px rgba(var(--crit-rgb), 0.3);
} }
@keyframes critPulse { @keyframes critPulse {
0%, 0%,
100% { 100% {
box-shadow: 0 0 4px rgba(255, 215, 0, 0.3); box-shadow: 0 0 4px rgba(var(--crit-rgb), 0.3);
} }
50% { 50% {
box-shadow: 0 0 8px rgba(255, 215, 0, 0.6); box-shadow: 0 0 12px rgba(var(--crit-rgb), 0.6);
} }
} }

View file

@ -10,11 +10,13 @@
} }
.title { .title {
font-family: "Cinzel", Georgia, serif;
font-size: 0.9rem; font-size: 0.9rem;
font-weight: 700; font-weight: 700;
color: #c9a84c; color: var(--gold);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.05em; letter-spacing: 0.1em;
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.3);
} }
.slotCounter { .slotCounter {
@ -23,13 +25,13 @@
} }
.slotCounter.normal { .slotCounter.normal {
color: #4caf50; color: var(--hp);
} }
.slotCounter.warning { .slotCounter.warning {
color: #ff9800; color: var(--warning);
} }
.slotCounter.over { .slotCounter.over {
color: #e74c3c; color: var(--danger);
} }
.table { .table {
@ -38,13 +40,15 @@
} }
.tableHeader { .tableHeader {
font-family: "Cinzel", Georgia, serif;
font-size: 0.7rem; font-size: 0.7rem;
color: #666; color: var(--text-tertiary);
text-transform: uppercase; text-transform: uppercase;
font-weight: 600; font-weight: 600;
text-align: left; text-align: left;
padding: 0.25rem 0.5rem; padding: 0.25rem 0.5rem;
border-bottom: 1px solid #333; border-bottom: 1px solid rgba(var(--gold-rgb), 0.2);
letter-spacing: 0.05em;
} }
.right { .right {
@ -55,11 +59,11 @@
} }
.row { .row {
border-bottom: 1px solid #222; border-bottom: 1px solid rgba(var(--gold-rgb), 0.06);
} }
.row:hover { .row:hover {
background: rgba(201, 168, 76, 0.05); background: rgba(var(--gold-rgb), 0.06);
} }
.cell { .cell {
@ -75,14 +79,14 @@
.removeBtn { .removeBtn {
background: none; background: none;
border: none; border: none;
color: #555; color: var(--text-faint);
cursor: pointer; cursor: pointer;
font-size: 0.9rem; font-size: 0.9rem;
padding: 0.1rem 0.3rem; padding: 0.1rem 0.3rem;
} }
.removeBtn:hover { .removeBtn:hover {
color: #e74c3c; color: var(--danger);
} }
.addArea { .addArea {
@ -91,25 +95,34 @@
.addBtn { .addBtn {
padding: 0.4rem 0.75rem; padding: 0.4rem 0.75rem;
background: #c9a84c; background: var(--btn-gold-bg);
color: #1a1a2e; color: var(--btn-active-text);
border: none; border: none;
border-radius: 6px; border-radius: 4px;
font-weight: 600; font-weight: 600;
cursor: pointer; cursor: pointer;
font-size: 0.8rem; font-size: 0.8rem;
box-shadow:
0 2px 4px rgba(var(--shadow-rgb), 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.1);
text-shadow: 0 1px 1px rgba(var(--shadow-rgb), 0.2);
} }
.addBtn:hover { .addBtn:hover {
background: #d4b65a; background: linear-gradient(
180deg,
var(--gold-bright),
var(--gold-hover) 40%,
var(--gold)
);
} }
.cancelBtn { .cancelBtn {
padding: 0.4rem 0.75rem; padding: 0.4rem 0.75rem;
background: #333; background: var(--bg-inset);
color: #888; color: var(--text-secondary);
border: none; border: 1px solid rgba(var(--gold-rgb), 0.15);
border-radius: 6px; border-radius: 4px;
font-weight: 600; font-weight: 600;
cursor: pointer; cursor: pointer;
font-size: 0.8rem; font-size: 0.8rem;
@ -124,30 +137,32 @@
.customInput { .customInput {
flex: 1; flex: 1;
padding: 0.4rem 0.6rem; padding: 0.4rem 0.6rem;
background: #0f1a30; background: var(--bg-inset);
border: 1px solid #333; border: 1px solid rgba(var(--gold-rgb), 0.15);
border-radius: 6px; border-radius: 4px;
color: #e0e0e0; color: var(--text-primary);
font-size: 0.85rem; font-size: 0.85rem;
font-family: "Alegreya", Georgia, serif;
} }
.customInput:focus { .customInput:focus {
outline: none; outline: none;
border-color: #c9a84c; border-color: var(--gold);
} }
.customSelect { .customSelect {
padding: 0.4rem 0.6rem; padding: 0.4rem 0.6rem;
background: #0f1a30; background: var(--bg-inset);
border: 1px solid #333; border: 1px solid rgba(var(--gold-rgb), 0.15);
border-radius: 6px; border-radius: 4px;
color: #e0e0e0; color: var(--text-primary);
font-size: 0.85rem; font-size: 0.85rem;
font-family: "Alegreya", Georgia, serif;
} }
.empty { .empty {
font-size: 0.8rem; font-size: 0.8rem;
color: #555; color: var(--text-faint);
font-style: italic; font-style: italic;
padding: 0.5rem; padding: 0.5rem;
} }

View file

@ -1,6 +1,16 @@
.panel { .panel {
background: #16213e; background-color: var(--bg-surface);
border: 1px solid #333; background-image: var(--texture-surface), var(--texture-speckle);
border-radius: 8px; background-size:
256px 256px,
128px 128px;
background-repeat: repeat, repeat;
border: 1px solid rgba(var(--gold-rgb), 0.2);
border-radius: 4px;
padding: 0.75rem; padding: 0.75rem;
box-shadow:
0 4px 16px rgba(var(--shadow-rgb), 0.5),
0 1px 4px rgba(var(--shadow-rgb), 0.4),
inset 0 1px 0 rgba(var(--gold-rgb), 0.06),
inset 0 0 30px rgba(var(--shadow-rgb), 0.15);
} }

View file

@ -5,10 +5,12 @@
} }
.label { .label {
font-family: "Cinzel", Georgia, serif;
font-size: 0.75rem; font-size: 0.75rem;
color: #888; color: var(--text-secondary);
text-transform: uppercase; text-transform: uppercase;
font-weight: 600; font-weight: 600;
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.3);
} }
.values { .values {
@ -20,32 +22,32 @@
} }
.current { .current {
color: #4caf50; color: var(--hp);
} }
.current.hurt { .current.hurt {
color: #ff9800; color: var(--warning);
} }
.current.critical { .current.critical {
color: #e74c3c; color: var(--danger);
} }
.slash { .slash {
color: #666; color: var(--text-tertiary);
} }
.max { .max {
color: #888; color: var(--text-secondary);
} }
.btn { .btn {
width: 24px; width: 24px;
height: 24px; height: 24px;
border-radius: 50%; border-radius: 50%;
border: 1px solid #444; border: 1px solid rgba(var(--gold-rgb), 0.25);
background: #16213e; background: var(--bg-inset);
color: #e0e0e0; color: var(--text-primary);
cursor: pointer; cursor: pointer;
font-size: 0.9rem; font-size: 0.9rem;
display: flex; display: flex;
@ -55,6 +57,6 @@
} }
.btn:hover { .btn:hover {
border-color: #c9a84c; border-color: var(--gold);
color: #c9a84c; color: var(--gold);
} }

View file

@ -14,33 +14,35 @@
.current { .current {
font-size: 1.4rem; font-size: 1.4rem;
font-weight: 700; font-weight: 700;
color: #4caf50; color: var(--hp);
} }
.current.hurt { .current.hurt {
color: #ff9800; color: var(--warning);
} }
.current.critical { .current.critical {
color: #e74c3c; color: var(--danger);
} }
.slash { .slash {
color: #666; color: var(--text-tertiary);
font-size: 0.9rem; font-size: 0.9rem;
} }
.max { .max {
color: #888; color: var(--text-secondary);
font-weight: 600; font-weight: 600;
font-size: 1rem; font-size: 1rem;
} }
.label { .label {
font-family: "Cinzel", Georgia, serif;
font-size: 0.65rem; font-size: 0.65rem;
color: #888; color: var(--text-secondary);
text-transform: uppercase; text-transform: uppercase;
font-weight: 600; font-weight: 600;
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.3);
} }
.buttons { .buttons {
@ -51,9 +53,9 @@
.healBtn { .healBtn {
padding: 0.15rem 0.5rem; padding: 0.15rem 0.5rem;
background: rgba(76, 175, 80, 0.15); background: rgba(76, 175, 80, 0.15);
border: 1px solid #4caf50; border: 1px solid var(--hp);
border-radius: 4px; border-radius: 4px;
color: #4caf50; color: var(--hp);
cursor: pointer; cursor: pointer;
font-size: 0.65rem; font-size: 0.65rem;
font-weight: 600; font-weight: 600;
@ -66,10 +68,10 @@
.dmgBtn { .dmgBtn {
padding: 0.15rem 0.5rem; padding: 0.15rem 0.5rem;
background: rgba(231, 76, 60, 0.15); background: rgba(var(--danger-rgb), 0.15);
border: 1px solid #e74c3c; border: 1px solid var(--danger);
border-radius: 4px; border-radius: 4px;
color: #e74c3c; color: var(--danger);
cursor: pointer; cursor: pointer;
font-size: 0.65rem; font-size: 0.65rem;
font-weight: 600; font-weight: 600;
@ -77,7 +79,7 @@
} }
.dmgBtn:hover { .dmgBtn:hover {
background: rgba(231, 76, 60, 0.3); background: rgba(var(--danger-rgb), 0.3);
} }
.inputRow { .inputRow {
@ -89,10 +91,10 @@
.amountInput { .amountInput {
width: 2.5rem; width: 2.5rem;
padding: 0.2rem 0.3rem; padding: 0.2rem 0.3rem;
background: #0f1a30; background: var(--bg-inset);
border: 1px solid #444; border: 1px solid rgba(var(--gold-rgb), 0.2);
border-radius: 4px; border-radius: 4px;
color: #e0e0e0; color: var(--text-primary);
font-size: 0.85rem; font-size: 0.85rem;
text-align: center; text-align: center;
font-weight: 600; font-weight: 600;
@ -103,11 +105,11 @@
} }
.amountInput.healing { .amountInput.healing {
border-color: #4caf50; border-color: var(--hp);
} }
.amountInput.damage { .amountInput.damage {
border-color: #e74c3c; border-color: var(--danger);
} }
.applyBtn { .applyBtn {
@ -120,24 +122,24 @@
} }
.applyBtn.healing { .applyBtn.healing {
background: #4caf50; background: var(--hp);
color: #1a1a2e; color: var(--btn-active-text);
} }
.applyBtn.damage { .applyBtn.damage {
background: #e74c3c; background: var(--danger);
color: #fff; color: #fff;
} }
.cancelBtn { .cancelBtn {
background: none; background: none;
border: none; border: none;
color: #666; color: var(--text-tertiary);
cursor: pointer; cursor: pointer;
font-size: 0.85rem; font-size: 0.85rem;
padding: 0 0.2rem; padding: 0 0.2rem;
} }
.cancelBtn:hover { .cancelBtn:hover {
color: #e0e0e0; color: var(--text-primary);
} }

View file

@ -1,17 +1,29 @@
.panel { .panel {
background: #16213e; background-color: var(--bg-surface);
border: 1px solid #333; background-image: var(--texture-surface), var(--texture-speckle);
border-radius: 8px; background-size:
256px 256px,
128px 128px;
background-repeat: repeat, repeat;
border: 1px solid rgba(var(--gold-rgb), 0.2);
border-radius: 4px;
padding: 0.75rem; padding: 0.75rem;
box-shadow:
0 4px 16px rgba(var(--shadow-rgb), 0.5),
0 1px 4px rgba(var(--shadow-rgb), 0.4),
inset 0 1px 0 rgba(var(--gold-rgb), 0.06),
inset 0 0 30px rgba(var(--shadow-rgb), 0.15);
} }
.sectionTitle { .sectionTitle {
font-family: "Cinzel", Georgia, serif;
font-size: 0.8rem; font-size: 0.8rem;
font-weight: 700; font-weight: 700;
color: #c9a84c; color: var(--gold);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.05em; letter-spacing: 0.1em;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.3);
} }
.infoGrid { .infoGrid {
@ -28,15 +40,17 @@
} }
.infoLabel { .infoLabel {
color: #666; font-family: "Cinzel", Georgia, serif;
color: var(--text-tertiary);
font-size: 0.7rem; font-size: 0.7rem;
text-transform: uppercase; text-transform: uppercase;
font-weight: 600; font-weight: 600;
min-width: 5rem; min-width: 5rem;
letter-spacing: 0.03em;
} }
.infoValue { .infoValue {
color: #e0e0e0; color: var(--text-primary);
} }
.notes { .notes {
@ -48,26 +62,28 @@
.editField { .editField {
padding: 0.3rem 0.5rem; padding: 0.3rem 0.5rem;
background: #0f1a30; background: var(--bg-inset);
border: 1px solid #333; border: 1px solid rgba(var(--gold-rgb), 0.15);
border-radius: 5px; border-radius: 5px;
color: #e0e0e0; color: var(--text-primary);
font-size: 0.85rem; font-size: 0.85rem;
width: 100%; width: 100%;
font-family: "Alegreya", Georgia, serif;
} }
.editField:focus { .editField:focus {
outline: none; outline: none;
border-color: #c9a84c; border-color: var(--gold);
} }
.editSelect { .editSelect {
padding: 0.3rem 0.5rem; padding: 0.3rem 0.5rem;
background: #0f1a30; background: var(--bg-inset);
border: 1px solid #333; border: 1px solid rgba(var(--gold-rgb), 0.15);
border-radius: 5px; border-radius: 5px;
color: #e0e0e0; color: var(--text-primary);
font-size: 0.85rem; font-size: 0.85rem;
font-family: "Alegreya", Georgia, serif;
} }
.editRow { .editRow {
@ -87,26 +103,28 @@
} }
.fieldLabel { .fieldLabel {
font-family: "Cinzel", Georgia, serif;
font-size: 0.65rem; font-size: 0.65rem;
color: #666; color: var(--text-tertiary);
text-transform: uppercase; text-transform: uppercase;
font-weight: 600; font-weight: 600;
letter-spacing: 0.03em;
} }
.notesEdit { .notesEdit {
width: 100%; width: 100%;
min-height: 50px; min-height: 50px;
padding: 0.4rem; padding: 0.4rem;
background: #0f1a30; background: var(--bg-inset);
border: 1px solid #333; border: 1px solid rgba(var(--gold-rgb), 0.15);
border-radius: 5px; border-radius: 5px;
color: #e0e0e0; color: var(--text-primary);
font-size: 0.85rem; font-size: 0.85rem;
font-family: inherit; font-family: "Alegreya", Georgia, serif;
resize: vertical; resize: vertical;
} }
.notesEdit:focus { .notesEdit:focus {
outline: none; outline: none;
border-color: #c9a84c; border-color: var(--gold);
} }

View file

@ -5,16 +5,16 @@
} }
.value:hover { .value:hover {
border-bottom-color: #c9a84c; border-bottom-color: var(--gold);
} }
.input { .input {
width: 3rem; width: 3rem;
padding: 0.1rem 0.2rem; padding: 0.1rem 0.2rem;
background: #0f1a30; background: var(--bg-inset);
border: 1px solid #c9a84c; border: 1px solid rgba(var(--gold-rgb), 0.3);
border-radius: 4px; border-radius: 4px;
color: #e0e0e0; color: var(--text-primary);
font-size: inherit; font-size: inherit;
font-weight: inherit; font-weight: inherit;
text-align: center; text-align: center;

View file

@ -5,16 +5,17 @@
.searchInput { .searchInput {
width: 100%; width: 100%;
padding: 0.5rem 0.75rem; padding: 0.5rem 0.75rem;
background: #0f1a30; background: var(--bg-inset);
border: 1px solid #333; border: 1px solid rgba(var(--gold-rgb), 0.25);
border-radius: 6px; border-radius: 4px;
color: #e0e0e0; color: var(--text-primary);
font-size: 0.85rem; font-size: 0.85rem;
font-family: "Alegreya", Georgia, serif;
} }
.searchInput:focus { .searchInput:focus {
outline: none; outline: none;
border-color: #c9a84c; border-color: var(--gold);
} }
.dropdown { .dropdown {
@ -24,12 +25,22 @@
right: 0; right: 0;
max-height: 220px; max-height: 220px;
overflow-y: auto; overflow-y: auto;
background: #16213e; background:
border: 1px solid #444; repeating-linear-gradient(
border-radius: 6px; 0deg,
transparent,
transparent 3px,
rgba(180, 155, 100, 0.02) 3px,
rgba(180, 155, 100, 0.02) 4px
),
linear-gradient(175deg, #221e18 0%, #1e1b16 50%, #201c17 100%);
border: 1px solid rgba(var(--gold-rgb), 0.25);
border-radius: 4px;
margin-bottom: 0.25rem; margin-bottom: 0.25rem;
z-index: 200; z-index: 200;
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.5); box-shadow:
0 -4px 20px rgba(var(--shadow-rgb), 0.5),
0 -2px 8px rgba(var(--shadow-rgb), 0.4);
} }
.group { .group {
@ -37,12 +48,14 @@
} }
.groupLabel { .groupLabel {
font-family: "Cinzel", Georgia, serif;
font-size: 0.7rem; font-size: 0.7rem;
font-weight: 700; font-weight: 700;
color: #c9a84c; color: var(--gold);
text-transform: uppercase; text-transform: uppercase;
padding: 0.25rem 0.75rem; padding: 0.25rem 0.75rem;
letter-spacing: 0.05em; letter-spacing: 0.08em;
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.3);
} }
.item { .item {
@ -54,15 +67,15 @@
} }
.item:hover { .item:hover {
background: rgba(201, 168, 76, 0.15); background: rgba(var(--gold-rgb), 0.12);
} }
.itemName { .itemName {
color: #e0e0e0; color: var(--text-primary);
} }
.itemMeta { .itemMeta {
color: #666; color: var(--text-tertiary);
font-size: 0.75rem; font-size: 0.75rem;
} }
@ -70,12 +83,12 @@
padding: 0.5rem 0.75rem; padding: 0.5rem 0.75rem;
cursor: pointer; cursor: pointer;
font-size: 0.85rem; font-size: 0.85rem;
color: #888; color: var(--text-secondary);
font-style: italic; font-style: italic;
border-top: 1px solid #333; border-top: 1px solid rgba(var(--gold-rgb), 0.1);
} }
.customOption:hover { .customOption:hover {
background: rgba(201, 168, 76, 0.15); background: rgba(var(--gold-rgb), 0.12);
color: #c9a84c; color: var(--gold);
} }

View file

@ -1,11 +1,15 @@
.card { .card {
background: #0f1a30; background-color: var(--bg-roll-entry);
border: 1px solid #2a2a4a; background-image: var(--texture-surface);
border-radius: 6px; background-size: 256px 256px;
background-repeat: repeat;
border: 1px solid rgba(var(--gold-rgb), 0.1);
border-radius: 4px;
padding: 0.5rem 0.6rem; padding: 0.5rem 0.6rem;
animation: slideIn 0.3s ease-out; animation: slideIn 0.3s ease-out;
border-left-width: 3px; border-left-width: 3px;
border-left-style: solid; border-left-style: solid;
box-shadow: 0 2px 6px rgba(var(--shadow-rgb), 0.3);
} }
@keyframes slideIn { @keyframes slideIn {
@ -20,16 +24,23 @@
} }
.card.nat20 { .card.nat20 {
border-color: #ffd700; border-color: var(--crit);
background: linear-gradient(135deg, #1a1a0e, #0f1a30); background: linear-gradient(
135deg,
rgba(40, 35, 15, 0.9),
rgba(24, 21, 16, 0.9)
);
box-shadow:
0 0 12px rgba(var(--crit-rgb), 0.15),
0 2px 6px rgba(var(--shadow-rgb), 0.3);
} }
.card.nat20 .total { .card.nat20 .total {
color: #ffd700; color: var(--crit);
} }
.card.fresh { .card.fresh {
border-color: #c9a84c; border-color: var(--gold);
animation: animation:
slideIn 0.3s ease-out, slideIn 0.3s ease-out,
glow 1s ease-out; glow 1s ease-out;
@ -37,7 +48,7 @@
@keyframes glow { @keyframes glow {
0% { 0% {
box-shadow: 0 0 8px rgba(201, 168, 76, 0.4); box-shadow: 0 0 8px rgba(var(--gold-rgb), 0.4);
} }
100% { 100% {
box-shadow: none; box-shadow: none;
@ -52,75 +63,78 @@
} }
.charName { .charName {
font-family: "Cinzel", Georgia, serif;
font-weight: 700; font-weight: 700;
font-size: 0.8rem; font-size: 0.8rem;
color: #c9a84c; color: var(--gold);
letter-spacing: 0.03em;
} }
.timestamp { .timestamp {
font-size: 0.65rem; font-size: 0.65rem;
color: #555; color: var(--text-faint);
} }
.label { .label {
font-size: 0.75rem; font-size: 0.75rem;
color: #888; color: var(--text-secondary);
margin-bottom: 0.2rem; margin-bottom: 0.2rem;
} }
.breakdown { .breakdown {
font-size: 0.75rem; font-size: 0.75rem;
color: #666; color: var(--text-tertiary);
margin-bottom: 0.15rem; margin-bottom: 0.15rem;
} }
.dieResult { .dieResult {
color: #e0e0e0; color: var(--text-primary);
font-weight: 600; font-weight: 600;
} }
.dieChosen { .dieChosen {
color: #c9a84c; color: var(--gold);
font-weight: 700; font-weight: 700;
} }
.dieDiscarded { .dieDiscarded {
color: #555; color: var(--text-faint);
text-decoration: line-through; text-decoration: line-through;
} }
.modLine { .modLine {
font-size: 0.7rem; font-size: 0.7rem;
color: #666; color: var(--text-tertiary);
} }
.total { .total {
font-size: 1.3rem; font-size: 1.3rem;
font-weight: 700; font-weight: 700;
color: #e0e0e0; color: var(--text-primary);
text-align: center; text-align: center;
margin-top: 0.2rem; margin-top: 0.2rem;
} }
.advantage { .advantage {
color: #4caf50; color: var(--hp);
font-size: 0.65rem; font-size: 0.65rem;
font-weight: 600; font-weight: 600;
text-transform: uppercase; text-transform: uppercase;
} }
.disadvantage { .disadvantage {
color: #e74c3c; color: var(--danger);
font-size: 0.65rem; font-size: 0.65rem;
font-weight: 600; font-weight: 600;
text-transform: uppercase; text-transform: uppercase;
} }
.critBanner { .critBanner {
font-family: "Cinzel", Georgia, serif;
text-align: center; text-align: center;
font-size: 0.75rem; font-size: 0.75rem;
font-weight: 700; font-weight: 700;
color: #ffd700; color: var(--crit);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.1em; letter-spacing: 0.1em;
padding: 0.15rem 0; padding: 0.15rem 0;

View file

@ -1,14 +1,18 @@
.panel { .panel {
width: 300px; width: 300px;
height: 100%; height: 100%;
background: #1a1a2e; background-color: var(--bg-roll-log);
border-left: 1px solid #333; background-image: var(--texture-surface);
background-size: 256px 256px;
background-repeat: repeat;
border-left: 2px solid rgba(var(--gold-rgb), 0.2);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
transition: width 0.2s; transition: width 0.2s;
flex-shrink: 0; flex-shrink: 0;
z-index: 150; z-index: 150;
position: relative; position: relative;
box-shadow: -4px 0 16px rgba(var(--shadow-rgb), 0.3);
} }
.panel.collapsed { .panel.collapsed {
@ -21,28 +25,30 @@
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 0.5rem 0.75rem; padding: 0.5rem 0.75rem;
border-bottom: 1px solid #333; border-bottom: 1px solid rgba(var(--gold-rgb), 0.15);
} }
.title { .title {
font-family: "Cinzel", Georgia, serif;
font-size: 0.85rem; font-size: 0.85rem;
font-weight: 700; font-weight: 700;
color: #c9a84c; color: var(--gold);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.05em; letter-spacing: 0.1em;
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.3);
} }
.collapseBtn { .collapseBtn {
background: none; background: none;
border: none; border: none;
color: #888; color: var(--text-secondary);
cursor: pointer; cursor: pointer;
font-size: 1rem; font-size: 1rem;
padding: 0.2rem; padding: 0.2rem;
} }
.collapseBtn:hover { .collapseBtn:hover {
color: #c9a84c; color: var(--gold);
} }
.collapsedContent { .collapsedContent {
@ -61,34 +67,35 @@
.collapsedLast { .collapsedLast {
writing-mode: vertical-rl; writing-mode: vertical-rl;
font-size: 0.7rem; font-size: 0.7rem;
color: #888; color: var(--text-secondary);
max-height: 100px; max-height: 100px;
overflow: hidden; overflow: hidden;
} }
.inputArea { .inputArea {
padding: 0.5rem 0.75rem; padding: 0.5rem 0.75rem;
border-bottom: 1px solid #333; border-bottom: 1px solid rgba(var(--gold-rgb), 0.15);
} }
.input { .input {
width: 100%; width: 100%;
padding: 0.4rem 0.6rem; padding: 0.4rem 0.6rem;
background: #0f1a30; background: var(--bg-inset);
border: 1px solid #333; border: 1px solid rgba(var(--gold-rgb), 0.15);
border-radius: 6px; border-radius: 4px;
color: #e0e0e0; color: var(--text-primary);
font-size: 0.85rem; font-size: 0.85rem;
font-family: "Alegreya", Georgia, serif;
} }
.input:focus { .input:focus {
outline: none; outline: none;
border-color: #c9a84c; border-color: var(--gold);
} }
.hint { .hint {
font-size: 0.6rem; font-size: 0.6rem;
color: #555; color: var(--text-faint);
margin-top: 0.25rem; margin-top: 0.25rem;
text-align: center; text-align: center;
} }
@ -101,7 +108,7 @@
flex-direction: column; flex-direction: column;
gap: 0.4rem; gap: 0.4rem;
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: #333 transparent; scrollbar-color: rgba(var(--gold-rgb), 0.15) transparent;
} }
.entries::-webkit-scrollbar { .entries::-webkit-scrollbar {
@ -109,13 +116,13 @@
} }
.entries::-webkit-scrollbar-thumb { .entries::-webkit-scrollbar-thumb {
background: #333; background: rgba(var(--gold-rgb), 0.15);
border-radius: 2px; border-radius: 2px;
} }
.empty { .empty {
text-align: center; text-align: center;
color: #555; color: var(--text-faint);
font-size: 0.8rem; font-size: 0.8rem;
font-style: italic; font-style: italic;
padding: 2rem 0; padding: 2rem 0;
@ -126,7 +133,7 @@
width: 100%; width: 100%;
height: 200px; height: 200px;
border-left: none; border-left: none;
border-top: 1px solid #333; border-top: 2px solid rgba(var(--gold-rgb), 0.2);
} }
.panel.collapsed { .panel.collapsed {

View file

@ -8,20 +8,23 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
background: #0f1a30; background: var(--bg-inset);
border: 1px solid #2a2a4a; border: 1px solid rgba(var(--gold-rgb), 0.12);
border-radius: 8px; border-radius: 4px;
padding: 0.5rem 0.3rem; padding: 0.5rem 0.3rem;
position: relative; position: relative;
box-shadow: inset 0 2px 4px rgba(var(--shadow-rgb), 0.3);
} }
.statName { .statName {
font-family: "Cinzel", Georgia, serif;
font-size: 0.7rem; font-size: 0.7rem;
color: #c9a84c; color: var(--gold);
font-weight: 700; font-weight: 700;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.08em; letter-spacing: 0.08em;
margin-bottom: 0.15rem; margin-bottom: 0.15rem;
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.3);
} }
.statRow { .statRow {
@ -33,22 +36,22 @@
.modifier { .modifier {
font-size: 1.3rem; font-size: 1.3rem;
font-weight: 700; font-weight: 700;
color: #e0e0e0; color: var(--text-primary);
min-width: 2.2rem; min-width: 2.2rem;
text-align: center; text-align: center;
} }
.score { .score {
font-size: 0.75rem; font-size: 0.75rem;
color: #666; color: var(--text-tertiary);
background: #1a1a2e; background: var(--bg-inset);
border-radius: 3px; border-radius: 3px;
padding: 0 0.3rem; padding: 0 0.3rem;
margin-top: 0.15rem; margin-top: 0.15rem;
} }
.bonus { .bonus {
color: #4caf50; color: var(--hp);
font-size: 0.65rem; font-size: 0.65rem;
} }
@ -56,9 +59,9 @@
width: 22px; width: 22px;
height: 22px; height: 22px;
border-radius: 50%; border-radius: 50%;
border: 1px solid #444; border: 1px solid rgba(var(--gold-rgb), 0.25);
background: #16213e; background: var(--bg-inset);
color: #e0e0e0; color: var(--text-primary);
cursor: pointer; cursor: pointer;
font-size: 0.8rem; font-size: 0.8rem;
display: flex; display: flex;
@ -71,8 +74,8 @@
} }
.btn:hover { .btn:hover {
border-color: #c9a84c; border-color: var(--gold);
color: #c9a84c; color: var(--gold);
} }
.rollSpace { .rollSpace {

View file

@ -1,21 +1,41 @@
.panel { .panel {
background: #16213e; background-color: var(--bg-surface);
border: 1px solid #333; background-image: var(--texture-surface), var(--texture-speckle);
border-radius: 8px; background-size:
256px 256px,
128px 128px;
background-repeat: repeat, repeat;
border: 1px solid rgba(var(--gold-rgb), 0.2);
border-radius: 4px;
padding: 0.75rem; padding: 0.75rem;
box-shadow:
0 4px 16px rgba(var(--shadow-rgb), 0.5),
0 1px 4px rgba(var(--shadow-rgb), 0.4),
inset 0 1px 0 rgba(var(--gold-rgb), 0.06),
inset 0 0 30px rgba(var(--shadow-rgb), 0.15);
} }
.sectionTitle { .sectionTitle {
font-family: "Cinzel", Georgia, serif;
font-size: 0.8rem; font-size: 0.8rem;
font-weight: 700; font-weight: 700;
color: #c9a84c; color: var(--gold);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.05em; letter-spacing: 0.1em;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.3);
} }
.separator { .separator {
border: none; border: none;
border-top: 1px solid #2a2a4a; height: 1px;
background: linear-gradient(
90deg,
transparent 5%,
rgba(var(--gold-rgb), 0.3) 30%,
rgba(var(--gold-rgb), 0.5) 50%,
rgba(var(--gold-rgb), 0.3) 70%,
transparent 95%
);
margin: 0.75rem 0; margin: 0.75rem 0;
} }

View file

@ -10,11 +10,13 @@
} }
.sectionTitle { .sectionTitle {
font-family: "Cinzel", Georgia, serif;
font-size: 0.9rem; font-size: 0.9rem;
font-weight: 700; font-weight: 700;
color: #c9a84c; color: var(--gold);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.05em; letter-spacing: 0.1em;
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.3);
} }
.list { .list {
@ -27,8 +29,9 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: flex-start; align-items: flex-start;
background: #0f1a30; background: rgba(var(--shadow-rgb), 0.2);
border-radius: 6px; border-left: 2px solid rgba(var(--gold-rgb), 0.15);
border-radius: 4px;
padding: 0.5rem 0.75rem; padding: 0.5rem 0.75rem;
} }
@ -43,20 +46,20 @@
.itemDesc { .itemDesc {
font-size: 0.75rem; font-size: 0.75rem;
color: #888; color: var(--text-secondary);
} }
.removeBtn { .removeBtn {
background: none; background: none;
border: none; border: none;
color: #666; color: var(--text-tertiary);
cursor: pointer; cursor: pointer;
font-size: 1rem; font-size: 1rem;
padding: 0.25rem; padding: 0.25rem;
} }
.removeBtn:hover { .removeBtn:hover {
color: #e74c3c; color: var(--danger);
} }
.addForm { .addForm {
@ -68,36 +71,46 @@
.addInput { .addInput {
flex: 1; flex: 1;
padding: 0.4rem 0.6rem; padding: 0.4rem 0.6rem;
background: #0f1a30; background: var(--bg-inset);
border: 1px solid #333; border: 1px solid rgba(var(--gold-rgb), 0.15);
border-radius: 6px; border-radius: 4px;
color: #e0e0e0; color: var(--text-primary);
font-size: 0.85rem; font-size: 0.85rem;
font-family: "Alegreya", Georgia, serif;
} }
.addInput:focus { .addInput:focus {
outline: none; outline: none;
border-color: #c9a84c; border-color: var(--gold);
} }
.addBtn { .addBtn {
padding: 0.4rem 0.75rem; padding: 0.4rem 0.75rem;
background: #c9a84c; background: var(--btn-gold-bg);
color: #1a1a2e; color: var(--btn-active-text);
border: none; border: none;
border-radius: 6px; border-radius: 4px;
font-weight: 600; font-weight: 600;
cursor: pointer; cursor: pointer;
font-size: 0.85rem; font-size: 0.85rem;
box-shadow:
0 2px 4px rgba(var(--shadow-rgb), 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.1);
text-shadow: 0 1px 1px rgba(var(--shadow-rgb), 0.2);
} }
.addBtn:hover { .addBtn:hover {
background: #d4b65a; background: linear-gradient(
180deg,
var(--gold-bright),
var(--gold-hover) 40%,
var(--gold)
);
} }
.empty { .empty {
font-size: 0.8rem; font-size: 0.8rem;
color: #555; color: var(--text-faint);
font-style: italic; font-style: italic;
padding: 0.5rem 0; padding: 0.5rem 0;
} }

View file

@ -5,16 +5,17 @@
.searchInput { .searchInput {
width: 100%; width: 100%;
padding: 0.5rem 0.75rem; padding: 0.5rem 0.75rem;
background: #0f1a30; background: var(--bg-inset);
border: 1px solid #333; border: 1px solid rgba(var(--gold-rgb), 0.25);
border-radius: 6px; border-radius: 4px;
color: #e0e0e0; color: var(--text-primary);
font-size: 0.85rem; font-size: 0.85rem;
font-family: "Alegreya", Georgia, serif;
} }
.searchInput:focus { .searchInput:focus {
outline: none; outline: none;
border-color: #c9a84c; border-color: var(--gold);
} }
.dropdown { .dropdown {
@ -24,12 +25,22 @@
right: 0; right: 0;
max-height: 220px; max-height: 220px;
overflow-y: auto; overflow-y: auto;
background: #16213e; background:
border: 1px solid #444; repeating-linear-gradient(
border-radius: 6px; 0deg,
transparent,
transparent 3px,
rgba(180, 155, 100, 0.02) 3px,
rgba(180, 155, 100, 0.02) 4px
),
linear-gradient(175deg, #221e18 0%, #1e1b16 50%, #201c17 100%);
border: 1px solid rgba(var(--gold-rgb), 0.25);
border-radius: 4px;
margin-bottom: 0.25rem; margin-bottom: 0.25rem;
z-index: 200; z-index: 200;
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.5); box-shadow:
0 -4px 20px rgba(var(--shadow-rgb), 0.5),
0 -2px 8px rgba(var(--shadow-rgb), 0.4);
} }
.group { .group {
@ -37,12 +48,14 @@
} }
.groupLabel { .groupLabel {
font-family: "Cinzel", Georgia, serif;
font-size: 0.7rem; font-size: 0.7rem;
font-weight: 700; font-weight: 700;
color: #c9a84c; color: var(--gold);
text-transform: uppercase; text-transform: uppercase;
padding: 0.25rem 0.75rem; padding: 0.25rem 0.75rem;
letter-spacing: 0.05em; letter-spacing: 0.08em;
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.3);
} }
.item { .item {
@ -54,16 +67,16 @@
} }
.item:hover { .item:hover {
background: rgba(201, 168, 76, 0.15); background: rgba(var(--gold-rgb), 0.12);
} }
.itemName { .itemName {
color: #e0e0e0; color: var(--text-primary);
font-weight: 600; font-weight: 600;
} }
.itemDesc { .itemDesc {
color: #888; color: var(--text-secondary);
font-size: 0.75rem; font-size: 0.75rem;
} }
@ -71,12 +84,12 @@
padding: 0.5rem 0.75rem; padding: 0.5rem 0.75rem;
cursor: pointer; cursor: pointer;
font-size: 0.85rem; font-size: 0.85rem;
color: #888; color: var(--text-secondary);
font-style: italic; font-style: italic;
border-top: 1px solid #333; border-top: 1px solid rgba(var(--gold-rgb), 0.1);
} }
.customOption:hover { .customOption:hover {
background: rgba(201, 168, 76, 0.15); background: rgba(var(--gold-rgb), 0.12);
color: #c9a84c; color: var(--gold);
} }

View file

@ -0,0 +1,76 @@
.container {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
z-index: 9999;
}
.trigger {
background: none;
border: 1px solid rgba(var(--gold-rgb), 0.25);
border-radius: 4px;
padding: 0.3rem 0.5rem;
cursor: pointer;
font-size: 1rem;
line-height: 1;
transition:
border-color 0.15s,
box-shadow 0.15s;
}
.trigger:hover {
border-color: rgba(var(--gold-rgb), 0.5);
box-shadow: 0 0 6px rgba(var(--gold-rgb), 0.15);
}
.dropdown {
position: absolute;
top: 100%;
right: 0;
margin-top: 0.35rem;
background-color: var(--bg-modal);
background-image: var(--texture-surface);
background-size: 256px 256px;
background-repeat: repeat;
border: 1px solid rgba(var(--gold-rgb), 0.3);
border-radius: 4px;
padding: 0.3rem;
min-width: 10rem;
z-index: 9999;
box-shadow:
0 4px 16px rgba(var(--shadow-rgb), 0.5),
inset 0 1px 0 rgba(var(--gold-rgb), 0.06);
}
.option {
display: flex;
align-items: center;
gap: 0.5rem;
width: 100%;
padding: 0.4rem 0.6rem;
background: none;
border: none;
border-radius: 3px;
color: var(--text-primary);
font-family: "Alegreya", Georgia, serif;
font-size: 0.85rem;
cursor: pointer;
text-align: left;
transition: background 0.1s;
}
.option:hover {
background: rgba(var(--gold-rgb), 0.1);
}
.option.active {
color: var(--gold);
font-weight: 600;
}
.optionIcon {
font-size: 1rem;
width: 1.4rem;
text-align: center;
}

View file

@ -0,0 +1,68 @@
import { useState } from "react";
import styles from "./ThemeToggle.module.css";
const THEMES = [
{ id: "dark-parchment", label: "Dark Parchment", icon: "\u{1F4DC}" },
{ id: "light-parchment", label: "Light Parchment", icon: "\u{1F3F0}" },
{ id: "white", label: "White", icon: "\u2600" },
{ id: "abyss", label: "Abyss", icon: "\u{1F311}" },
] as const;
type ThemeId = (typeof THEMES)[number]["id"];
function getInitialTheme(): ThemeId {
const saved = localStorage.getItem("shadowdark-theme");
if (saved && THEMES.some((t) => t.id === saved)) return saved as ThemeId;
return "dark-parchment";
}
function applyTheme(theme: ThemeId) {
if (theme === "dark-parchment") {
document.documentElement.removeAttribute("data-theme");
} else {
document.documentElement.setAttribute("data-theme", theme);
}
localStorage.setItem("shadowdark-theme", theme);
}
// Apply saved theme immediately on module load
applyTheme(getInitialTheme());
export default function ThemeToggle() {
const [current, setCurrent] = useState<ThemeId>(getInitialTheme);
const [open, setOpen] = useState(false);
function selectTheme(theme: ThemeId) {
applyTheme(theme);
setCurrent(theme);
setOpen(false);
}
const currentTheme = THEMES.find((t) => t.id === current)!;
return (
<div className={styles.container}>
<button
className={styles.trigger}
onClick={() => setOpen(!open)}
title="Change theme"
>
{currentTheme.icon}
</button>
{open && (
<div className={styles.dropdown}>
{THEMES.map((theme) => (
<button
key={theme.id}
className={`${styles.option} ${theme.id === current ? styles.active : ""}`}
onClick={() => selectTheme(theme.id)}
>
<span className={styles.optionIcon}>{theme.icon}</span>
<span>{theme.label}</span>
</button>
))}
</div>
)}
</div>
);
}

View file

@ -1,9 +1,10 @@
import { StrictMode } from "react"; import { StrictMode } from "react";
import { createRoot } from "react-dom/client"; import { createRoot } from "react-dom/client";
import "./theme.css";
import App from "./App"; import App from "./App";
createRoot(document.getElementById("root")!).render( createRoot(document.getElementById("root")!).render(
<StrictMode> <StrictMode>
<App /> <App />
</StrictMode> </StrictMode>,
); );

View file

@ -14,32 +14,49 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
background: #16213e; background-color: var(--bg-surface);
border: 1px solid #333; background-image: var(--texture-surface), var(--texture-speckle);
border-radius: 8px; background-size:
256px 256px,
128px 128px;
background-repeat: repeat, repeat;
border: 1px solid rgba(var(--gold-rgb), 0.2);
border-radius: 4px;
padding: 1rem 1.25rem; padding: 1rem 1.25rem;
cursor: pointer; cursor: pointer;
transition: border-color 0.15s; transition:
border-color 0.15s,
box-shadow 0.15s;
box-shadow:
0 4px 12px rgba(var(--shadow-rgb), 0.5),
0 1px 4px rgba(var(--shadow-rgb), 0.3),
inset 0 1px 0 rgba(var(--gold-rgb), 0.06);
} }
.campaignCard:hover { .campaignCard:hover {
border-color: #c9a84c; border-color: rgba(var(--gold-rgb), 0.5);
box-shadow:
0 6px 16px rgba(var(--shadow-rgb), 0.6),
0 2px 6px rgba(var(--shadow-rgb), 0.4),
inset 0 1px 0 rgba(var(--gold-rgb), 0.1);
} }
.campaignName { .campaignName {
font-family: "Cinzel", Georgia, serif;
font-size: 1.1rem; font-size: 1.1rem;
font-weight: 600; font-weight: 600;
color: var(--text-primary);
} }
.campaignDate { .campaignDate {
font-size: 0.8rem; font-size: 0.8rem;
color: #888; color: var(--text-secondary);
} }
.deleteBtn { .deleteBtn {
background: none; background: none;
border: none; border: none;
color: #666; color: var(--text-tertiary);
cursor: pointer; cursor: pointer;
font-size: 1.2rem; font-size: 1.2rem;
padding: 0.25rem 0.5rem; padding: 0.25rem 0.5rem;
@ -47,8 +64,8 @@
} }
.deleteBtn:hover { .deleteBtn:hover {
color: #e74c3c; color: var(--danger);
background: rgba(231, 76, 60, 0.1); background: rgba(var(--danger-rgb), 0.1);
} }
.createForm { .createForm {
@ -59,36 +76,47 @@
.createInput { .createInput {
flex: 1; flex: 1;
padding: 0.6rem 1rem; padding: 0.6rem 1rem;
background: #16213e; background: var(--bg-inset);
border: 1px solid #333; border: 1px solid rgba(var(--gold-rgb), 0.2);
border-radius: 8px; border-radius: 4px;
color: #e0e0e0; color: var(--text-primary);
font-size: 1rem; font-size: 1rem;
font-family: "Alegreya", Georgia, serif;
} }
.createInput:focus { .createInput:focus {
outline: none; outline: none;
border-color: #c9a84c; border-color: var(--gold);
} }
.createBtn { .createBtn {
padding: 0.6rem 1.25rem; padding: 0.6rem 1.25rem;
background: #c9a84c; background: var(--btn-gold-bg);
color: #1a1a2e; color: var(--btn-active-text);
border: none; border: none;
border-radius: 8px; border-radius: 4px;
font-family: "Cinzel", Georgia, serif;
font-weight: 600; font-weight: 600;
cursor: pointer; cursor: pointer;
font-size: 1rem; font-size: 1rem;
box-shadow:
0 2px 4px rgba(var(--shadow-rgb), 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.1);
text-shadow: 0 1px 1px rgba(var(--shadow-rgb), 0.2);
} }
.createBtn:hover { .createBtn:hover {
background: #d4b65a; background: linear-gradient(
180deg,
var(--gold-bright),
var(--gold-hover) 40%,
var(--gold)
);
} }
.empty { .empty {
text-align: center; text-align: center;
color: #666; color: var(--text-tertiary);
padding: 3rem 0; padding: 3rem 0;
font-style: italic; font-style: italic;
} }

View file

@ -30,34 +30,47 @@
} }
.backLink { .backLink {
color: #888; color: var(--text-secondary);
text-decoration: none; text-decoration: none;
font-size: 0.9rem; font-size: 0.9rem;
} }
.backLink:hover { .backLink:hover {
color: #c9a84c; color: var(--gold);
} }
.campaignName { .campaignName {
font-family: "Cinzel", Georgia, serif;
font-size: 1.5rem; font-size: 1.5rem;
font-weight: 700; font-weight: 700;
color: #c9a84c; color: var(--gold);
letter-spacing: 0.05em;
text-shadow: 0 1px 3px rgba(var(--shadow-rgb), 0.4);
} }
.addBtn { .addBtn {
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
background: #c9a84c; background: var(--btn-gold-bg);
color: #1a1a2e; color: var(--btn-active-text);
border: none; border: none;
border-radius: 8px; border-radius: 4px;
font-family: "Cinzel", Georgia, serif;
font-weight: 600; font-weight: 600;
cursor: pointer; cursor: pointer;
font-size: 0.9rem; font-size: 0.9rem;
box-shadow:
0 2px 4px rgba(var(--shadow-rgb), 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.1);
text-shadow: 0 1px 1px rgba(var(--shadow-rgb), 0.2);
} }
.addBtn:hover { .addBtn:hover {
background: #d4b65a; background: linear-gradient(
180deg,
var(--gold-bright),
var(--gold-hover) 40%,
var(--gold)
);
} }
.grid { .grid {
@ -80,7 +93,7 @@
.empty { .empty {
text-align: center; text-align: center;
color: #666; color: var(--text-tertiary);
padding: 3rem 0; padding: 3rem 0;
font-style: italic; font-style: italic;
grid-column: 1 / -1; grid-column: 1 / -1;
@ -89,7 +102,7 @@
.createModal { .createModal {
position: fixed; position: fixed;
inset: 0; inset: 0;
background: rgba(0, 0, 0, 0.7); background: var(--bg-overlay);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@ -98,19 +111,32 @@
} }
.createForm { .createForm {
background: #1a1a2e; background-color: var(--bg-modal);
border: 1px solid #333; background-image: var(--texture-surface), var(--texture-speckle);
border-radius: 12px; background-size:
256px 256px,
128px 128px;
background-repeat: repeat, repeat;
border: 2px solid rgba(var(--gold-rgb), 0.3);
border-radius: 4px;
padding: 1.5rem; padding: 1.5rem;
width: 100%; width: 100%;
max-width: 400px; max-width: 400px;
box-shadow:
0 8px 40px rgba(var(--shadow-rgb), 0.7),
0 2px 8px rgba(var(--shadow-rgb), 0.5),
inset 0 1px 0 rgba(var(--gold-rgb), 0.1),
inset 0 0 60px rgba(var(--shadow-rgb), 0.2);
} }
.createTitle { .createTitle {
font-family: "Cinzel", Georgia, serif;
font-size: 1.2rem; font-size: 1.2rem;
font-weight: 700; font-weight: 700;
margin-bottom: 1rem; margin-bottom: 1rem;
color: #c9a84c; color: var(--gold);
letter-spacing: 0.05em;
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.3);
} }
.formField { .formField {
@ -121,33 +147,37 @@
} }
.formLabel { .formLabel {
font-family: "Cinzel", Georgia, serif;
font-size: 0.75rem; font-size: 0.75rem;
color: #888; color: var(--text-secondary);
text-transform: uppercase; text-transform: uppercase;
font-weight: 600; font-weight: 600;
letter-spacing: 0.05em;
} }
.formInput { .formInput {
padding: 0.5rem 0.75rem; padding: 0.5rem 0.75rem;
background: #0f1a30; background: var(--bg-inset);
border: 1px solid #333; border: 1px solid rgba(var(--gold-rgb), 0.15);
border-radius: 6px; border-radius: 4px;
color: #e0e0e0; color: var(--text-primary);
font-size: 0.9rem; font-size: 0.9rem;
font-family: "Alegreya", Georgia, serif;
} }
.formInput:focus { .formInput:focus {
outline: none; outline: none;
border-color: #c9a84c; border-color: var(--gold);
} }
.formSelect { .formSelect {
padding: 0.5rem 0.75rem; padding: 0.5rem 0.75rem;
background: #0f1a30; background: var(--bg-inset);
border: 1px solid #333; border: 1px solid rgba(var(--gold-rgb), 0.15);
border-radius: 6px; border-radius: 4px;
color: #e0e0e0; color: var(--text-primary);
font-size: 0.9rem; font-size: 0.9rem;
font-family: "Alegreya", Georgia, serif;
} }
.formActions { .formActions {
@ -159,29 +189,39 @@
.formBtn { .formBtn {
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
border-radius: 6px; border-radius: 4px;
font-weight: 600; font-weight: 600;
cursor: pointer; cursor: pointer;
font-size: 0.9rem; font-size: 0.9rem;
} }
.formBtnPrimary { .formBtnPrimary {
background: #c9a84c; background: var(--btn-gold-bg);
color: #1a1a2e; color: var(--btn-active-text);
border: none; border: none;
font-family: "Cinzel", Georgia, serif;
box-shadow:
0 2px 4px rgba(var(--shadow-rgb), 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.1);
text-shadow: 0 1px 1px rgba(var(--shadow-rgb), 0.2);
} }
.formBtnPrimary:hover { .formBtnPrimary:hover {
background: #d4b65a; background: linear-gradient(
180deg,
var(--gold-bright),
var(--gold-hover) 40%,
var(--gold)
);
} }
.formBtnSecondary { .formBtnSecondary {
background: transparent; background: transparent;
color: #888; color: var(--text-secondary);
border: 1px solid #333; border: 1px solid rgba(var(--gold-rgb), 0.2);
} }
.formBtnSecondary:hover { .formBtnSecondary:hover {
border-color: #888; border-color: rgba(var(--gold-rgb), 0.4);
color: #e0e0e0; color: var(--text-primary);
} }

182
client/src/theme.css Normal file
View file

@ -0,0 +1,182 @@
/* ============================================================
Shadowdark Theme System
============================================================
All theme-dependent colors use CSS custom properties.
Themes are activated via data-theme attribute on <html>.
Default (no attribute) = dark-parchment.
============================================================ */
:root {
/* --- Color components (for rgba() usage) --- */
--gold-rgb: 201, 168, 76;
--shadow-rgb: 0, 0, 0;
--danger-rgb: 231, 76, 60;
--crit-rgb: 255, 215, 0;
/* --- Backgrounds --- */
--bg-body: #0a0908;
--bg-body-vignette: rgba(25, 22, 18, 0.6);
--bg-surface: #2a2520;
--bg-modal: #201c18;
--bg-input: #15130f;
--bg-inset: rgba(0, 0, 0, 0.3);
--bg-overlay: rgba(0, 0, 0, 0.75);
--bg-roll-log: #1a1714;
--bg-roll-entry: #252118;
/* --- Text --- */
--text-primary: #dad5c9;
--text-secondary: #908878;
--text-tertiary: #665e52;
--text-faint: #4a4238;
/* --- Gold accent --- */
--gold: #c9a84c;
--gold-hover: #d4b65a;
--gold-bright: #dcc06a;
--btn-gold-bg: linear-gradient(180deg, #d4b65a, #c9a84c 40%, #b8973e);
--btn-active-text: #1a1a2e;
/* --- Status colors --- */
--hp: #4caf50;
--ac: #5dade2;
--danger: #e74c3c;
--warning: #ff9800;
--crit: #ffd700;
--copper: #b87333;
--silver: #a0a0a0;
/* --- Textures --- */
--texture-surface: url("/textures/parchment-noise.png");
--texture-speckle: url("/textures/speckle.png");
--texture-body: url("/textures/wood-grain.png");
--texture-surface-size: 256px 256px;
--texture-speckle-size: 128px 128px;
--texture-body-size: 512px 512px;
}
/* ============================================================
Light Parchment warm beige, like reading by daylight
============================================================ */
[data-theme="light-parchment"] {
--gold-rgb: 140, 110, 40;
--shadow-rgb: 80, 60, 30;
--danger-rgb: 200, 60, 45;
--bg-body: #c4b594;
--bg-body-vignette: rgba(160, 140, 100, 0.3);
--bg-surface: #ddd0b0;
--bg-modal: #d5c8a8;
--bg-input: #c8bb9a;
--bg-inset: rgba(0, 0, 0, 0.06);
--bg-overlay: rgba(0, 0, 0, 0.5);
--bg-roll-log: #d0c3a0;
--bg-roll-entry: #d8cbb0;
--text-primary: #2a2218;
--text-secondary: #5a5040;
--text-tertiary: #7a7060;
--text-faint: #9a9080;
--gold: #8a6d2b;
--gold-hover: #a0832e;
--gold-bright: #b89530;
--btn-gold-bg: linear-gradient(180deg, #a08335, #8a6d2b 40%, #7a5d20);
--btn-active-text: #f0e8d0;
--hp: #2e8b34;
--ac: #2e7da8;
--danger: #c83c2d;
--warning: #c87800;
--crit: #b8960a;
--copper: #8a5520;
--silver: #707070;
--texture-surface: url("/textures/parchment-noise-light.png");
--texture-speckle: url("/textures/speckle-light.png");
--texture-body: url("/textures/wood-grain-light.png");
}
/* ============================================================
White clean, minimal, near-white
============================================================ */
[data-theme="white"] {
--gold-rgb: 154, 125, 48;
--shadow-rgb: 0, 0, 0;
--danger-rgb: 200, 60, 45;
--bg-body: #f0ede8;
--bg-body-vignette: transparent;
--bg-surface: #faf8f4;
--bg-modal: #f5f3ef;
--bg-input: #eae7e0;
--bg-inset: rgba(0, 0, 0, 0.04);
--bg-overlay: rgba(0, 0, 0, 0.4);
--bg-roll-log: #f2f0ec;
--bg-roll-entry: #f8f6f2;
--text-primary: #1a1816;
--text-secondary: #555048;
--text-tertiary: #807870;
--text-faint: #aaa498;
--gold: #9a7d30;
--gold-hover: #b0932e;
--gold-bright: #c8a830;
--btn-gold-bg: linear-gradient(180deg, #b09335, #9a7d30 40%, #8a6d25);
--btn-active-text: #f5f3ef;
--hp: #2e8b34;
--ac: #2e7da8;
--danger: #c83c2d;
--warning: #c87800;
--crit: #8a7010;
--copper: #8a5520;
--silver: #707070;
--texture-surface: none;
--texture-speckle: none;
--texture-body: none;
}
/* ============================================================
Abyss maximum dark, pitch black
============================================================ */
[data-theme="abyss"] {
--gold-rgb: 212, 182, 90;
--shadow-rgb: 0, 0, 0;
--danger-rgb: 231, 76, 60;
--bg-body: #050505;
--bg-body-vignette: transparent;
--bg-surface: #0e0e14;
--bg-modal: #0a0a10;
--bg-input: #08080e;
--bg-inset: rgba(0, 0, 0, 0.5);
--bg-overlay: rgba(0, 0, 0, 0.85);
--bg-roll-log: #0a0a10;
--bg-roll-entry: #0e0e14;
--text-primary: #e8e8e8;
--text-secondary: #888888;
--text-tertiary: #606060;
--text-faint: #404040;
--gold: #d4b65a;
--gold-hover: #e0c870;
--gold-bright: #edd880;
--btn-gold-bg: linear-gradient(180deg, #e0c870, #d4b65a 40%, #c4a64a);
--btn-active-text: #0a0a10;
--hp: #4caf50;
--ac: #5dade2;
--danger: #e74c3c;
--warning: #ff9800;
--crit: #ffd700;
--copper: #b87333;
--silver: #a0a0a0;
--texture-surface: none;
--texture-speckle: none;
--texture-body: none;
}