feat: Printable character sheet

This commit is contained in:
2026-06-16 02:10:22 +00:00
parent fcbd0acfb2
commit f462205463
2 changed files with 195 additions and 0 deletions

View File

@@ -451,6 +451,9 @@ export default function CharacterSheet() {
<span className={`save-status${saveStatus ? " show" : ""}`}>
Saved!
</span>
<button className="btn-print" onClick={() => window.print()}>
Print
</button>
<button
className="btn-theme"
onClick={() => setTheme((t) => (t === "light" ? "dark" : "light"))}

View File

@@ -1075,6 +1075,25 @@ input[type="number"] {
box-shadow: 0 0 8px rgba(26, 122, 118, 0.35);
}
/* ── PRINT BUTTON ────────────────────────────────── */
.btn-print {
font-family: var(--font-display);
font-size: 0.55rem;
letter-spacing: 0.12em;
text-transform: uppercase;
padding: 7px 12px;
cursor: pointer;
border: 1px solid var(--border-bright);
background: transparent;
color: var(--text-dim);
transition: all 0.2s;
}
.btn-print:hover {
border-color: var(--teal-dim);
color: var(--teal);
}
/* ── THEME TOGGLE BUTTON ─────────────────────────── */
.btn-theme {
font-family: var(--font-display);
@@ -1137,3 +1156,176 @@ input[type="number"] {
::-webkit-scrollbar-thumb:hover {
background: var(--teal-dim);
}
/* ── PRINT ───────────────────────────────────────── */
/* Content is shrunk to fit one page via a smaller root font-size (shrinks all
rem-sized text/spacing) plus tighter print-specific paddings — NOT via
zoom/transform tricks, since browsers don't reliably honor those during
print layout, which previously caused content to overflow the page and get
clipped on the right edge. .page is always kept at width: 100% so it can
never exceed the printable area. */
@page {
size: letter portrait;
margin: 0.4in 0.5in;
}
@media print {
:root {
--bg: #fff;
--surface: #fff;
--surface2: #f9f9f9;
--surface3: #f3f3f3;
--border: #ccc;
--border-bright: #aaa;
--teal: #1a7a76;
--teal-dim: #1a7a76;
--gold: #8a6520;
--gold-dim: #8a6520;
--text: #111;
--text-dim: #555;
--text-bright: #000;
--crisis: #c0392b;
font-size: 65%;
}
* {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
body {
background: #fff !important;
background-image: none !important;
font-size: 11px !important;
}
/* Hide all screen-only chrome */
header,
.url-banner,
#page-manage {
display: none !important;
}
/* Each tab prints as one portrait page, never wider than the page */
.page {
display: block !important;
width: 100% !important;
max-width: none !important;
margin: 0 !important;
padding: 6px 10px !important;
box-sizing: border-box !important;
overflow: hidden;
page-break-after: always;
break-after: page;
page-break-inside: avoid;
}
#page-spells {
page-break-after: avoid;
break-after: avoid;
}
/* Tighten spacing so content fits within the page */
.section {
padding: 6px 10px !important;
}
.section-title {
margin-bottom: 5px !important;
padding-bottom: 4px !important;
}
.field {
margin-bottom: 5px !important;
}
label {
margin-bottom: 2px !important;
}
.grid-2,
.grid-3 {
gap: 8px !important;
}
/* Flex/grid items default to min-width: auto (their content's intrinsic
size), which can force the container wider than the page and clip the
right edge. Overriding to 0 lets every item shrink to fit. */
.page * {
min-width: 0 !important;
}
.field-row {
gap: 8px !important;
}
/* Make inputs look clean for print — just an underline, no box */
input[type="text"],
input:not([type]),
input[type="number"],
textarea,
select {
background: transparent !important;
border: none !important;
border-bottom: 1px solid #bbb !important;
box-shadow: none !important;
padding: 1px 2px !important;
color: #000 !important;
min-height: unset !important;
}
textarea {
resize: none !important;
overflow: hidden !important;
}
/* Hide interactive-only buttons */
.add-btn,
.spell-del-btn,
.btn-print,
.btn-theme,
.btn-save,
.btn-load,
.save-status {
display: none !important;
}
/* Calc buttons inside vital-block */
.vital-block > .add-btn {
display: none !important;
}
/* XP / FP visuals */
.xp-bar-wrap {
background: #eee !important;
}
.xp-bar {
background: #1a7a76 !important;
}
.fp-pip {
border-color: #999 !important;
box-shadow: none !important;
}
.fp-pip.filled {
background: #1a7a76 !important;
box-shadow: none !important;
}
/* Status / discipline toggles */
.status-item.active-status {
background: #ddd !important;
}
.disc-item.checked {
background: #ddd !important;
}
/* Tables */
th, td {
border-color: #ccc !important;
}
}