/* D&D Theme - a Player's Handbook page in a certificate frame, on a leather desk */

/* Homebrewery's 5e fonts (Solbera's CC-BY-SA 4.0 remakes; see fonts/LICENSE.txt) */
@font-face {
    font-family: 'Bookinsanity';
    src: url('/fonts/Bookinsanity-acb5fbb3e14d67153802e0aa97998f44.woff2') format('woff2');
    font-display: swap;
}
@font-face {
    font-family: 'Bookinsanity';
    font-weight: bold;
    src: url('/fonts/BookinsanityBold-58f93fdce6614cbcbe59fb33ca5f6408.woff2') format('woff2');
    font-display: swap;
}
@font-face {
    font-family: 'Bookinsanity';
    font-style: italic;
    src: url('/fonts/BookinsanityItalic-737f59499c305e19e0fc176afa662e39.woff2') format('woff2');
    font-display: swap;
}
@font-face {
    font-family: 'Bookinsanity';
    font-style: italic;
    font-weight: bold;
    src: url('/fonts/BookinsanityBoldItalic-eb9f967395231d368aee1221afc547fd.woff2') format('woff2');
    font-display: swap;
}
@font-face {
    font-family: 'Mr Eaves Small Caps';
    src: url('/fonts/MrEavesSmallCaps-0c5445af25ba106869283a13b2dd9335.woff2') format('woff2');
    font-display: swap;
}
/* The Campaign Sage's handwriting: Almendra by Ana Sanfelippo (SIL Open Font License 1.1; fonts/Almendra-OFL.txt) */
@font-face {
    font-family: 'Almendra';
    src: url('/fonts/Almendra-f9e602c4b25960cfd3e774c594d61171.woff2') format('woff2');
    font-display: swap;
}
@font-face {
    font-family: 'Almendra';
    font-weight: bold;
    src: url('/fonts/AlmendraBold-5f8bc943a579909b02abf99d55faefd4.woff2') format('woff2');
    font-display: swap;
}
@font-face {
    font-family: 'Almendra';
    font-style: italic;
    src: url('/fonts/AlmendraItalic-90e3a361f4e411220f7ea4ab706f2bb3.woff2') format('woff2');
    font-display: swap;
}
@font-face {
    font-family: 'Almendra';
    font-style: italic;
    font-weight: bold;
    src: url('/fonts/AlmendraBoldItalic-6adb567d9a4803dc4b21e0e65db717f1.woff2') format('woff2');
    font-display: swap;
}
@font-face {
    font-family: 'Solbera Imitation';
    src: url('/fonts/SolberaImitationTweak-0f3b6b970827ec69b6b53b021b3f9fbd.woff2') format('woff2');
    font-display: swap;
}

/* Color Palette */
:root {
    --font-body: 'Bookinsanity', Georgia, serif;
    --font-heading: 'Mr Eaves Small Caps', Georgia, serif;
    /* Player's Handbook heading red, and the gold rule under its headings */
    --oxblood: #58180d;
    --rule-gold: #c9ad6a;
    /* The pale green of a PHB note box */
    --note-green: #e0e5c1;
    --parchment-light: #f4e8d0;
    --parchment-dark: #e8d5b7;
    --leather-brown: #8b4513;
    --leather-dark: #654321;
    --leather-darker: #2c1810;
    --gold: #d4af37;
    --gold-dark: #aa8c2c;
    --gold-light: #e5c048;
    /* Gold for small text on leather; --gold-light is too dark to read there */
    --gold-pale: #f5d76e;
    --text-dark: #2c1810;
    --text-light: #f4e8d0;
    --success: #556b2f;
    --warning: #b8860b;
    /* Crimson, kept well apart from the oxblood main button so a Delete never passes for a Save */
    --danger: #b3261e;
    --info: #2f5f8a;
    /* Warning-coloured small text; --warning itself is too light to read on parchment */
    --warning-text: #7a5a00;
}

/* Global Font */
/* The page is a dark leather desk; each page's content lies on it as a framed parchment sheet (.page-frame) */
body {
    font-family: var(--font-body);
    color: var(--text-dark);
    background-color: var(--leather-darker);
    min-height: 100vh;
}

/* Every page's main container: the certificate sheet. border-image cuts the picture into nine pieces, so the
   ornamental corners keep their shape at any page size and only the edges and the middle stretch. */
.page-frame {
    border: 62px solid transparent;
    border-image: url('/images/certificate-frame-683a3f897cb05a18b13ff17665cd1933.jpg') 250 fill / 62px stretch;
    padding: 0.5rem 1rem 1rem;
    margin-bottom: 2rem;
}

@media (max-width: 768px) {
    .page-frame {
        border-width: 28px;
        border-image-width: 28px;
        padding: 0.25rem 0.25rem 0.75rem;
    }
}

/* Page footers lie on the dark desk, outside the sheet, so their muted text is lightened to stay readable */
body > footer,
body > footer .text-muted {
    color: var(--parchment-dark) !important;
    border-color: var(--leather-dark) !important;
    font-family: var(--font-heading);
    font-size: 1.1rem;
}

/* Credit line for the fonts, on the desk under the page */
.font-credit {
    padding-bottom: 1rem;
    text-align: center;
    font-family: var(--font-heading);
    font-size: 0.95rem;
    color: var(--parchment-dark);
}

.font-credit a {
    color: var(--gold-pale);
    font-weight: normal;
}

/* Inline icons (fragments/icons.html) sit on the text baseline like the icon font did */
.icon {
    vertical-align: -0.125em;
}

/* A collapsible header's caret points up while its section is open */
.collapse-caret .icon {
    transition: transform 0.2s;
}
[aria-expanded="true"] .collapse-caret .icon {
    transform: rotate(180deg);
}

/* Typography */
/* Player's Handbook headings: oxblood small caps (Mr Eaves has one weight, so no faux bold) */
h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-heading);
    font-weight: normal;
    color: var(--oxblood);
}

h1 {
    font-size: 2.6rem;
}

.campaign-title {
    font-family: var(--font-heading);
    color: var(--oxblood);
}

/* A Player's Handbook note: pale green between gold rules, raised off the page */
.phb-note {
    background: var(--note-green);
    border-top: 3px solid var(--rule-gold);
    border-bottom: 3px solid var(--rule-gold);
    box-shadow: 0 4px 6px rgba(44, 24, 16, 0.25);
    padding: 0.75rem 1rem;
}

.phb-note h5 {
    color: var(--text-dark);
    margin-bottom: 0.25rem;
}

/* The first letter of an opening paragraph, PHB style: a tall ornamental capital. The paragraph contains the
   floated capital, so a one-line paragraph grows to fit it instead of letting it spill out of its card. */
.drop-cap {
    display: flow-root;
}

.drop-cap::first-letter {
    float: left;
    font-family: 'Solbera Imitation', var(--font-heading);
    font-size: 4.2rem;
    line-height: 0.85;
    padding: 0.2rem 0.4rem 0 0;
    color: var(--oxblood);
}

/* Navigation Bar */
.navbar-dark {
    background: linear-gradient(to bottom, var(--leather-brown), var(--leather-dark)) !important;
    border-bottom: 3px solid var(--leather-darker);
    box-shadow: 0 4px 8px rgba(0,0,0,0.4);
}

.navbar-brand, .nav-link {
    color: var(--parchment-light) !important;
    font-family: var(--font-heading);
    text-shadow: 1px 1px 3px rgba(0,0,0,0.7);
}

.navbar-brand {
    font-size: 1.6rem;
}

.navbar .nav-link {
    font-size: 1.25rem;
}

.navbar-brand:hover, .nav-link:hover {
    color: var(--gold) !important;
}

.nav-link:active, .navbar-brand:active {
    color: var(--gold-light) !important;
    transform: scale(0.95);
    transition: transform 0.05s;
}

/* Global click feedback for links */
a:active {
    opacity: 0.7;
    transition: opacity 0.05s;
}

/* Loading overlay — shown on page navigation */
.page-loading-overlay {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(244, 232, 208, 0.7);
    z-index: 9999;
    justify-content: center;
    align-items: center;
    flex-direction: column;
}

.page-loading-overlay.active {
    display: flex;
}

.page-loading-text {
    font-family: var(--font-body);
    font-style: italic;
    color: var(--oxblood);
    font-size: 1rem;
    margin-top: 12px;
}

.page-loading-d20 {
    width: 48px;
    height: 48px;
    position: relative;
    animation: d20-roll 1.2s ease-in-out infinite;
}

.page-loading-d20 svg {
    width: 100%;
    height: 100%;
}

@keyframes d20-roll {
    0% { transform: rotate(0deg) scale(1); }
    25% { transform: rotate(90deg) scale(1.05); }
    50% { transform: rotate(180deg) scale(1); }
    75% { transform: rotate(270deg) scale(0.95); }
    100% { transform: rotate(360deg) scale(1); }
}

/* Breadcrumbs */
/* Breadcrumbs: an italic running head, ruled off from the page */
.breadcrumb {
    background: none;
    padding: 0.25rem 0;
    border-bottom: 1px solid var(--rule-gold);
    border-radius: 0;
    font-style: italic;
}

.breadcrumb-item a {
    color: var(--oxblood);
    font-weight: bold;
}

.breadcrumb-item.active {
    color: var(--leather-dark);
}

/* Cards: a section of the page, edged in a thin gold rule */
.card, .dnd-card {
    background: rgba(244, 232, 208, 0.6);
    border: 1px solid var(--rule-gold);
    box-shadow: 0 2px 4px rgba(44, 24, 16, 0.2);
    border-radius: 0;
}

/* A label over a value in an info card (Calendar, Last Played …): a PHB stat-block entry, like a field label */
.info-label {
    color: var(--oxblood);
    font-family: var(--font-heading);
    font-size: 1.2rem;
    line-height: 1.2;
}

/* The title of a campaign-page section tile (Sessions, Locations …): a larger, bolder PHB heading, no icon */
.dnd-card-header .section-tile-title {
    font-size: 1.9rem;
    font-weight: bold;
    letter-spacing: 0.03em;
    line-height: 1.1;
}

/* Card headers: a PHB section title, oxblood small caps over a gold rule */
.dnd-card-header {
    background: transparent;
    border-bottom: 2px solid var(--rule-gold);
    color: var(--oxblood);
    font-family: var(--font-heading);
    font-size: 1.2rem;
    padding: 0.5rem 1rem 0.2rem;
    border-radius: 0;
}

.dnd-card-header h1,
.dnd-card-header h2,
.dnd-card-header h3,
.dnd-card-header h4,
.dnd-card-header h5,
.dnd-card-header h6 {
    color: var(--oxblood);
}

.card-body {
    background: transparent;
}

/* Buttons - main action: solid oxblood, the Player's Handbook red */
.btn-primary {
    background: var(--oxblood) !important;
    border: 2px solid var(--leather-darker) !important;
    color: var(--parchment-light) !important;
    font-family: var(--font-heading);
    box-shadow: 0 2px 4px rgba(0,0,0,0.3);
    border-radius: 3px;
}

.btn-primary:hover {
    background: #74241a !important;
    color: #fff !important;
}

.btn-primary:active {
    background: var(--leather-darker) !important;
    box-shadow: inset 0 3px 6px rgba(0,0,0,0.4) !important;
    transform: translateY(1px);
    transition: transform 0.05s, box-shadow 0.05s;
}

/* Buttons - the five roles (STYLE_GUIDE.md). Each has its own look so a Delete never passes for a Cancel. */
.dnd-btn-add,
.btn-secondary,
.btn-danger,
.btn-outline-danger,
.btn-outline-secondary {
    font-family: var(--font-heading);
    box-shadow: 0 2px 4px rgba(0,0,0,0.3);
    border-radius: 3px;
}

.btn-sm.btn-outline-danger,
.btn-sm.btn-outline-secondary {
    box-shadow: none;
}

/* Create / add: an oxblood outline on parchment, the main button's quieter twin */
.dnd-btn-add {
    background: var(--parchment-light) !important;
    border: 2px solid var(--oxblood) !important;
    color: var(--oxblood) !important;
}

/* Cancel / back: darker leather, a step down from Create */
.btn-secondary {
    background: linear-gradient(to bottom, var(--leather-dark), var(--leather-darker)) !important;
    border: 2px solid var(--leather-darker) !important;
    color: var(--parchment-dark) !important;
    text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
}

/* Destructive: crimson */
.btn-danger {
    background: var(--danger) !important;
    border: 2px solid #7f1a14 !important;
    color: var(--parchment-light) !important;
    text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
}

/* Destructive, quieter: crimson on parchment, dashed so it can't pass for the create outline */
.btn-outline-danger {
    background: var(--parchment-light) !important;
    border: 2px dashed var(--danger) !important;
    color: var(--danger) !important;
}

/* Low-key / utility: leather text on parchment, edged in the gold rule */
.btn-outline-secondary {
    background: var(--parchment-light) !important;
    border: 1px solid var(--rule-gold) !important;
    color: var(--leather-dark) !important;
}

.dnd-btn-add:hover {
    background: var(--oxblood) !important;
    color: var(--parchment-light) !important;
}

.btn-secondary:hover {
    background: linear-gradient(to bottom, #9c5524, #765432) !important;
    color: #fff !important;
}

.btn-danger:hover,
.btn-outline-danger:hover {
    background: #c9342b !important;
    color: #fff !important;
}

.btn-outline-secondary:hover {
    background: var(--parchment-dark) !important;
    color: var(--leather-dark) !important;
}

.dnd-btn-add:active,
.btn-secondary:active,
.btn-danger:active,
.btn-outline-danger:active,
.btn-outline-secondary:active {
    box-shadow: inset 0 3px 6px rgba(0,0,0,0.5) !important;
    transform: translateY(1px);
    transition: transform 0.05s, box-shadow 0.05s;
}

/* Buttons are set in the PHB heading small caps, a size up because Mr Eaves runs small */
.btn {
    font-size: 1.15rem;
    line-height: 1.3;
}

/* Small Buttons */
.btn-sm {
    padding: 0.2rem 0.75rem;
    font-size: 1rem;
}

/* Badges */
/* Badges in the PHB heading small caps, a size up because Mr Eaves runs small */
.badge, .dnd-badge {
    font-size: 0.9em;
    font-weight: normal;
    background: var(--leather-brown);
    color: var(--parchment-light);
    border: 1px solid var(--leather-darker);
    font-family: var(--font-heading);
    border-radius: 0;
}

/* Alternate badge colors maintain D&D theme */

/* A larger badge, for the one status a page is about */
.badge.badge-large {
    font-size: 1rem;
}

/* Badge tones: the only badge colours. Chosen by BadgeTones through fragments/badges.html. */
.badge.badge-success { background: var(--success); color: var(--text-light); }
.badge.badge-info { background: var(--info); color: var(--text-light); }
.badge.badge-warning { background: var(--warning); color: var(--text-dark); }
.badge.badge-danger { background: var(--danger); color: var(--text-light); }
.badge.badge-neutral { background: var(--leather-brown); color: var(--text-light); }

/* Forms */
/* Every text box can be dragged taller to read long text; never wider, since each already fills its column */
textarea {
    resize: vertical;
}

/* ...and from anywhere along the top or bottom edge (static/js/textarea-edge-resize.js) */
textarea.textarea-edge-hover {
    cursor: ns-resize;
}

.textarea-edge-resizing,
.textarea-edge-resizing * {
    cursor: ns-resize !important;
    user-select: none;
}

/* Fields: a pale writing space on the parchment, edged in the gold rule */
.form-control, .form-select {
    background-color: rgba(255, 250, 240, 0.65);
    border: 1px solid var(--rule-gold);
    color: var(--text-dark);
    font-family: var(--font-body);
    border-radius: 0;
}

.form-control:focus, .form-select:focus {
    background-color: #fffaf0;
    border-color: var(--gold);
    box-shadow: 0 0 0 0.2rem rgba(212, 175, 55, 0.25);
}

.form-label {
    color: var(--oxblood);
    font-family: var(--font-heading);
}

/* Every field's label reads like a stat-block entry in the Player's Handbook: oxblood small caps, no box */
label.form-label {
    display: block;
    margin-bottom: 0.15rem;
    background: none;
    color: var(--oxblood);
    font-size: 1.2rem;
    line-height: 1.2;
}

/* The required-field asterisk, crimson on the parchment */
label.form-label .text-danger {
    color: var(--danger) !important;
}

/* Alerts */
.alert {
    border: 2px solid var(--leather-brown);
    border-radius: 0;
    font-family: var(--font-body);
    background: linear-gradient(to bottom, var(--parchment-light), var(--parchment-dark));
}

.alert-success { border-color: var(--success); }
.alert-danger { border-color: var(--danger); }
.alert-warning { border-color: var(--warning); }
.alert-info { border-color: var(--info); }

/* A group of fields is a section of the page, PHB style: no box, just a gold rule along the top */
.choice-panel {
    position: relative;
    padding: 0.25rem 0 0.75rem;
    border: none;
    border-top: 2px solid var(--rule-gold);
    border-radius: 0;
    background: none;
}

/* Section titles: oxblood PHB small caps sitting on the gold rule. A fieldset opens its border around the
   legend, so the rule runs into the title and out again. */
.choice-panel > legend {
    float: none;
    width: auto;
    padding: 0 0.4rem;
    margin-bottom: 0.25rem;
    background: none;
    color: var(--oxblood);
    font-family: var(--font-heading);
    font-size: 1.6rem;
    line-height: 1;
}

/* Tick boxes: a parchment square in the gold rule; ticked, oxblood with a gold quill check */
.form-check-input {
    width: 1.2em;
    height: 1.2em;
    margin-top: 0.15em;
    background-color: var(--parchment-light);
    border: 1px solid var(--gold-dark);
    cursor: pointer;
}

.form-check-input[type="checkbox"] {
    border-radius: 3px;
}

.form-check-input:checked {
    background-color: var(--oxblood);
    border-color: var(--oxblood);
}

.form-check-input:checked[type="checkbox"] {
    --bs-form-check-bg-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.2 8.6c1.3.9 2.3 2.2 3.1 3.8 1.6-3.9 3.9-6.9 6.6-9.1' fill='none' stroke='%23e5c048' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

.form-check-input:checked[type="radio"] {
    --bs-form-check-bg-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='2.2' fill='%23e5c048'/%3E%3C/svg%3E");
}

.form-check-input:focus {
    border-color: var(--gold-dark);
    box-shadow: 0 0 0 0.2rem rgba(212, 175, 55, 0.4);
}

.form-check-label {
    font-family: var(--font-body);
    color: var(--text-dark);
    cursor: pointer;
}

/* The formatting toolbar above each long text box (static/js/text-format.js) */
.format-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-bottom: 4px;
}

.format-toolbar .btn {
    padding: 0 0.5rem;
    font-size: 0.95rem;
    box-shadow: none;
}

/* A long text field shown formatted (Markdown through @md.html): PHB spacing, oxblood bullets */
.md-text > :last-child {
    margin-bottom: 0;
}

.md-text p {
    margin-bottom: 0.5rem;
}

.md-text ul,
.md-text ol {
    margin-bottom: 0.5rem;
    padding-left: 1.4rem;
}

.md-text ul ul,
.md-text ol ol,
.md-text ul ol,
.md-text ol ul {
    margin-bottom: 0;
}

.md-text li::marker {
    color: var(--oxblood);
}

.md-text h1,
.md-text h2,
.md-text h3,
.md-text h4,
.md-text h5,
.md-text h6 {
    font-size: 1.3rem;
    margin: 0.5rem 0 0.25rem;
}

.md-text blockquote {
    margin: 0 0 0.5rem;
    padding-left: 0.75rem;
    border-left: 3px solid var(--rule-gold);
    font-style: italic;
}

/* Hidden until the page's script shows it (the script sets an inline display, which overrides this) */
.starts-hidden {
    display: none;
}

/* A long tick-box list that scrolls up and down inside its panel, e.g. a faction's members; never sideways */
.scroll-choices {
    max-height: 14rem;
    overflow-x: hidden;
    overflow-y: auto;
}

/* A grid row's negative side margins would make the list wider than its box */
.scroll-choices > .row {
    margin-left: 0;
    margin-right: 0;
}

/* A scrollable block of sample text, e.g. the import format example */
.example-block {
    max-height: 20rem;
    overflow: auto;
    white-space: pre-wrap;
    padding: 0.5rem;
    border: 1px solid var(--rule-gold);
    border-radius: 4px;
}

/* A cautionary note under a field */
.warning-note {
    color: var(--warning-text);
}

/* Loading spinners in the theme's leather */
.spinner-theme {
    color: var(--leather-brown);
}

/* A card header that opens and closes its card */
.collapse-toggle {
    cursor: pointer;
}

/* Text describing a good outcome */
.success-note {
    color: var(--success);
}

/* A small button inside a dense row, e.g. a scheme step's Edit */
.compact-button {
    padding: 0.1rem 0.5rem;
    font-size: 0.75rem;
}

/* Links and subtitles sitting in a card header */
.header-link {
    color: var(--oxblood);
    text-decoration: none;
}

.header-subtitle {
    color: var(--leather-dark);
    font-family: var(--font-body);
    font-size: 0.9rem;
}

/* Scheme steps; the step in progress is outlined and lit in gold */
.step-card.step-current {
    border: 1px solid var(--gold-dark);
    box-shadow: 0 0 0 2px rgba(212, 175, 55, 0.45), 0 2px 4px rgba(44, 24, 16, 0.2);
}

/* The step in progress has its title washed in gold */
.step-card.step-current > .dnd-card-header {
    background: rgba(212, 175, 55, 0.25);
}

/* Faction power out of 10, coloured by band */
.power-meter {
    width: 100%;
    height: 25px;
    accent-color: var(--success);
}

.power-meter.power-mid {
    accent-color: var(--warning);
}

.power-meter.power-high {
    accent-color: var(--danger);
}

/* A card that lifts its shadow on hover */
.hover-shadow {
    transition: box-shadow 0.3s ease-in-out;
}

.hover-shadow:hover {
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.2);
}

/* Rumor steps: numbered parchment slips with an oxblood edge; the current one is lit in gold, finished ones fade */
.rumor-step {
    padding: 12px 16px;
    margin-bottom: 10px;
    background: rgba(244, 232, 208, 0.6);
    border: 1px solid var(--rule-gold);
    border-left: 5px solid var(--oxblood);
}

.rumor-step.rumor-step-current {
    border-left-color: var(--gold);
    box-shadow: 0 0 0 2px var(--gold), 0 4px 8px rgba(0, 0, 0, 0.3);
}

.rumor-step.rumor-step-done {
    opacity: 0.7;
}

.step-number {
    display: inline-block;
    width: 32px;
    height: 32px;
    margin-right: 10px;
    line-height: 28px;
    text-align: center;
    font-family: var(--font-heading);
    font-size: 1.2rem;
    background: var(--oxblood);
    color: var(--parchment-light);
    border: 2px solid var(--rule-gold);
    border-radius: 50%;
}

/* How far through its steps a rumor is */
.rumor-progress {
    width: 100%;
    height: 8px;
    accent-color: var(--gold-dark);
}

/* Colour swatches on the /style-guide page */
.swatch {
    width: 9rem;
    padding: 1.5rem 0.5rem 0.5rem;
    border: 2px solid var(--leather-darker);
    font-size: 0.75rem;
    color: var(--text-light);
}

.swatch-parchment { background: var(--parchment-light); color: var(--text-dark); }
.swatch-leather { background: var(--leather-brown); }
.swatch-gold { background: var(--gold); color: var(--text-dark); }
.swatch-oxblood { background: var(--oxblood); }
.swatch-rule-gold { background: var(--rule-gold); color: var(--text-dark); }
.swatch-note-green { background: var(--note-green); color: var(--text-dark); }
.swatch-success { background: var(--success); }
.swatch-warning { background: var(--warning); color: var(--text-dark); }
.swatch-danger { background: var(--danger); }
.swatch-info { background: var(--info); }

/* A large loading spinner, for a page-level wait */
.spinner-large {
    width: 3rem;
    height: 3rem;
}

/* Text that keeps its own line breaks, e.g. AI-written prep */
.preserve-lines {
    white-space: pre-wrap;
    font-family: inherit;
}

/* Campaign list: rows of equal height, descriptions cut to two lines */
.campaign-row {
    height: 140px;
}

.clamp-2-lines {
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

/* The edit pop-up while it fetches the item's form */
/* The pop-up's loading state: the same rolling d20 and phrase as a page change */
.edit-modal-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 3rem 2rem;
}

.edit-modal-loading .page-loading-d20 {
    color: var(--gold-dark);
}

/* A card that opens something when clicked: lift it on hover and show keyboard focus */
.clickable-card {
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.clickable-card:hover,
.clickable-card:focus-visible {
    transform: translateY(-2px);
    box-shadow: 0 6px 14px rgba(44, 24, 16, 0.3);
}

.clickable-card:focus-visible {
    outline: 3px solid var(--gold);
    outline-offset: 2px;
}

/* A row in a list (a location page's rumors and plot threads) that opens the edit pop-up: it lights up instead
   of lifting like a card */
.clickable-row {
    padding: 0.5rem;
    border-radius: 4px;
}

.clickable-row:hover,
.clickable-row:focus-visible {
    transform: none;
    box-shadow: none;
    background-color: rgba(212, 175, 55, 0.15);
}

/* A feature people should notice, not fine print: a PHB note box, like .phb-note */
.import-format-callout {
    background: var(--note-green);
    border-top: 3px solid var(--rule-gold);
    border-bottom: 3px solid var(--rule-gold);
    box-shadow: 0 4px 6px rgba(44, 24, 16, 0.25);
    padding: 0.9rem 1rem;
}

.import-format-callout-title {
    color: var(--text-dark);
    font-family: var(--font-heading);
    font-size: 1.3rem;
    margin-bottom: 0.35rem;
}

code {
    color: var(--leather-brown);
    font-weight: bold;
}

.import-format-callout [aria-expanded="true"] .when-collapsed,
.import-format-callout [aria-expanded="false"] .when-expanded {
    display: none;
}

/* Tables */

/* List Groups */
.list-group-item {
    background: rgba(244, 232, 208, 0.6);
    border: 1px solid var(--rule-gold);
    color: var(--text-dark);
    font-family: var(--font-body);
}

.list-group-item:hover, .list-group-item-action:hover {
    background: rgba(212, 175, 55, 0.2);
    color: var(--text-dark);
}

.list-group-item:active, .list-group-item-action:active {
    background: rgba(212, 175, 55, 0.35);
    box-shadow: inset 0 2px 4px rgba(0,0,0,0.3);
    transform: scale(0.98);
    transition: transform 0.05s, background 0.05s;
}

/* Modals: the same certificate parchment as the page (a narrower frame), its title a PHB heading over a gold rule */
.modal-content {
    background: none;
    border: 28px solid transparent;
    border-image: url('/images/certificate-frame-683a3f897cb05a18b13ff17665cd1933.jpg') 250 fill / 28px stretch;
    filter: drop-shadow(0 8px 16px rgba(0, 0, 0, 0.5));
    border-radius: 0;
}

.modal-header {
    border-bottom: 2px solid var(--rule-gold);
}

.modal-footer {
    border-top: 1px solid var(--rule-gold);
}

.modal-title {
    font-family: var(--font-heading);
    font-size: 1.8rem;
    color: var(--oxblood);
}

/* Links */
a {
    color: var(--leather-brown);
    font-weight: bold;
}

a:hover {
    color: var(--gold);
}

/* Container */
.container {
    max-width: 1200px;
}

/* Specific Card Types */

/* Tabs: PHB small-caps labels; the open tab is a parchment tab edged in the gold rule */
.nav-tabs {
    border-bottom: 2px solid var(--rule-gold);
}

.nav-tabs .nav-link {
    background: transparent;
    border: 1px solid transparent;
    border-bottom: none;
    color: var(--leather-dark) !important;
    font-family: var(--font-heading);
    font-size: 1.2rem;
    margin-right: 5px;
    border-radius: 0;
    padding: 6px 18px 4px;
}

.nav-tabs .nav-link:hover {
    background: rgba(212, 175, 55, 0.15);
    color: var(--oxblood) !important;
    border-color: transparent;
}

.nav-tabs .nav-link.active {
    background: var(--parchment-light) !important;
    border: 1px solid var(--rule-gold);
    border-bottom: none;
    color: var(--oxblood) !important;
}

/* ===== AI Chat Panel ===== */

/* Container - sidebar mode */
.chat-panel-wrapper {
    display: flex;
    gap: 20px;
    align-items: flex-start;
}

.chat-panel-wrapper .edit-form-area {
    flex: 0 0 calc(60% - 10px);
    min-width: 0;
}

.chat-panel-wrapper .chat-panel-area {
    flex: 0 0 calc(40% - 10px);
    min-width: 0;
}

/* Full-width variant (debrief / planning) */
.chat-panel-wrapper.chat-panel-full {
    flex-direction: column;
}

.chat-panel-wrapper.chat-panel-full .edit-form-area,
.chat-panel-wrapper.chat-panel-full .chat-panel-area {
    flex: 1 1 100%;
    width: 100%;
}

/* Chat panel */
.chat-panel {
    position: sticky;
    top: 100px;
    display: flex;
    flex-direction: column;
    height: calc(100vh - 200px);
    margin: 14px 0;
    border: 24px solid transparent;
    border-image: url('/images/certificate-frame-683a3f897cb05a18b13ff17665cd1933.jpg') 250 fill / 24px stretch;
    filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.35));
    font-family: var(--font-body);
}

/* The scroll's wooden rollers, top and bottom, wider than the paper */
.chat-panel::before,
.chat-panel::after {
    content: "";
    position: absolute;
    left: -34px;
    right: -34px;
    height: 26px;
    z-index: 2;
    border-radius: 13px;
    background: linear-gradient(to bottom, var(--leather-darker), var(--leather-brown) 35%, var(--gold-dark) 50%,
        var(--leather-brown) 65%, var(--leather-darker));
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.45);
    pointer-events: none;
}

.chat-panel::before {
    top: -38px;
}

.chat-panel::after {
    top: calc(100% + 10px);
}

.chat-panel-full .chat-panel {
    position: relative;
    top: auto;
    height: 600px;
}

.chat-header {
    padding: 0 0 4px;
    border-bottom: 2px solid var(--rule-gold);
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: var(--oxblood);
    font-family: var(--font-heading);
}

.chat-title {
    font-size: 1.6rem;
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* Toggle wrapper - keeps label and switch inline */

/* Toggle switch - leather track, gold knob */

/* Messages */
.chat-messages {
    flex: 1;
    overflow-y: auto;
    padding: 12px 4px;
}

.chat-message {
    margin-bottom: 12px;
    display: flex;
}

.chat-message-user {
    justify-content: flex-end;
}

.chat-message-ai {
    justify-content: flex-start;
}

.chat-bubble {
    padding: 10px 14px;
    max-width: 85%;
    font-family: var(--font-body);
    border-radius: 0;
    color: var(--text-dark);
    line-height: 1.45;
    white-space: pre-wrap;
    word-wrap: break-word;
}

/* Your messages: a parchment slip edged in the gold rule */
.chat-bubble-user {
    background: var(--parchment-light);
    border: 1px solid var(--rule-gold);
    box-shadow: 0 2px 4px rgba(44, 24, 16, 0.2);
}

/* The Sage writes its answers straight onto the scroll: ink in its own hand, no box. chat-panel.js writes them
   at a quill's pace, with .sage-quill at the end of the line. */
.chat-bubble-ai {
    max-width: 100%;
    padding: 2px 4px;
    background: none;
    font-family: 'Almendra', var(--font-body);
    font-size: 1.12rem;
    line-height: 1.5;
    color: var(--leather-darker);
    white-space: normal;
}

.chat-bubble-ai p {
    margin-bottom: 0.5rem;
}

.chat-bubble-ai > :last-child {
    margin-bottom: 0;
}

.chat-bubble-ai ul,
.chat-bubble-ai ol {
    margin-bottom: 0.5rem;
    padding-left: 1.3rem;
}

.chat-bubble-ai li::marker {
    color: var(--oxblood);
}

/* The quill nib at the end of the line while the Sage writes; it scratches back and forth a little */
.sage-quill {
    display: inline-block;
    margin-left: 2px;
    color: var(--oxblood);
    font-family: var(--font-body);
    font-style: normal;
    transform-origin: bottom left;
    animation: quill-scratch 0.35s ease-in-out infinite alternate;
}

@keyframes quill-scratch {
    from { transform: translate(0, 0) rotate(-8deg); }
    to { transform: translate(2px, -1px) rotate(6deg); }
}

/* A reply that failed: crimson-edged, so it reads as an error and not as advice */
.chat-bubble-error {
    font-family: var(--font-body);
    font-size: 1rem;
    background: var(--parchment-light);
    border: 1px solid var(--danger);
    border-left-width: 4px;
    color: var(--danger);
}

/* A one-line notice in the conversation, e.g. that older messages were trimmed */
.chat-notice {
    margin: 0 0 12px;
    text-align: center;
    font-size: 0.85rem;
    font-style: italic;
    color: var(--leather-dark);
}

/* Input area */
.chat-input-area {
    padding: 10px 0 0;
    border-top: 1px solid var(--rule-gold);
    position: relative;
}

.chat-input {
    background: var(--parchment-light);
    border: 1px solid var(--rule-gold);
    border-radius: 0;
    font-family: var(--font-body);
    color: var(--text-dark);
    width: 100%;
    /* Drag the corner to make room for long notes; capped so the Send button stays on the scroll */
    resize: vertical;
    padding: 8px 10px;
    min-height: 60px;
    max-height: 40vh;
    box-sizing: border-box;
}

.chat-input:focus {
    outline: none;
    border-color: var(--gold);
    box-shadow: 0 0 0 2px rgba(212, 175, 55, 0.3);
    background: #fff;
}

.chat-send-btn {
    margin-top: 6px;
    background: var(--oxblood);
    border: 2px solid var(--leather-darker);
    color: var(--parchment-light);
    font-family: var(--font-heading);
    box-shadow: 0 2px 4px rgba(0,0,0,0.3);
    border-radius: 3px;
    padding: 6px 18px;
    cursor: pointer;
}

.chat-send-btn:hover {
    background: #74241a;
    color: #fff;
}

.chat-send-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Loading animation */

@keyframes pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.5; }
}

.chat-loading-d20 {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 14px;
}

.chat-loading-d20-icon {
    width: 28px;
    height: 28px;
    animation: d20-roll 1.2s ease-in-out infinite;
}

.chat-loading-d20-icon svg {
    width: 100%;
    height: 100%;
}

.chat-loading-d20 .chat-loading-text {
    font-style: italic;
    color: var(--oxblood);
    font-family: var(--font-body);
    font-size: 0.85rem;
    animation: pulse 1.5s ease-in-out infinite;
}

/* @-mention autocomplete dropdown */
.chat-mention-dropdown {
    position: absolute;
    background: var(--parchment-light);
    border: 1px solid var(--rule-gold);
    border-radius: 0;
    /* Above the floating Sage (1050) and its button (1051), which the list opens over */
    z-index: 1060;
    max-height: 200px;
    overflow-y: auto;
    min-width: 220px;
    box-shadow: 0 4px 8px rgba(0,0,0,0.3);
}

.chat-mention-item {
    padding: 8px 12px;
    cursor: pointer;
    font-family: var(--font-body);
    color: var(--text-dark);
    border-bottom: 1px solid var(--parchment-dark);
}

.chat-mention-item:last-child {
    border-bottom: none;
}

.chat-mention-item:hover,
.chat-mention-item.chat-mention-active {
    background: rgba(212, 175, 55, 0.25);
    color: var(--text-dark);
}

.chat-mention-name {
    font-weight: bold;
}

.chat-mention-type {
    font-family: var(--font-heading);
    font-size: 0.95em;
    color: var(--oxblood);
    margin-left: 6px;
}

/* Change summary */

/* Floating action button for mobile */
.chat-toggle-fab {
    display: none;
    position: fixed;
    bottom: 20px;
    right: 20px;
    width: 56px;
    height: 56px;
    background: var(--oxblood);
    border: 2px solid var(--rule-gold);
    color: var(--parchment-light);
    font-family: var(--font-heading);
    font-size: 1.5rem;
    cursor: pointer;
    box-shadow: 0 4px 8px rgba(0,0,0,0.4);
    z-index: 1050;
    border-radius: 50%;
}

.chat-toggle-fab:hover {
    background: #74241a;
}

/* Mobile: chat as overlay */
@media (max-width: 768px) {
    .chat-panel-wrapper {
        flex-direction: column;
        gap: 0;
    }

    .chat-panel-wrapper .edit-form-area,
    .chat-panel-wrapper .chat-panel-area {
        flex: 1 1 100%;
        width: 100%;
    }

    .chat-panel-wrapper .chat-panel-area {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1040;
        background: rgba(0, 0, 0, 0.5);
        display: none;
        padding: 20px;
        box-sizing: border-box;
    }

    .chat-panel-wrapper .chat-panel-area.chat-open {
        display: block;
    }

    .chat-panel-wrapper .chat-panel {
        position: relative;
        top: auto;
        height: 100%;
        max-height: calc(100vh - 40px);
    }

    .chat-toggle-fab {
        display: flex;
        align-items: center;
        justify-content: center;
    }
}

/* Scrollbar styling */
.chat-messages::-webkit-scrollbar {
    width: 8px;
}

.chat-messages::-webkit-scrollbar-track {
    background: var(--parchment-dark);
}

.chat-messages::-webkit-scrollbar-thumb {
    background: var(--rule-gold);
}

.chat-messages::-webkit-scrollbar-thumb:hover {
    background: var(--gold-dark);
}

/* Campaign-wide floating chat (fragments/campaign-chat.html) */
.chat-floating {
    position: fixed;
    right: 34px;
    bottom: 100px;
    width: min(420px, calc(100vw - 68px));
    height: min(560px, calc(100vh - 150px));
    z-index: 1050;
}

.chat-floating[hidden] {
    display: none;
}

/* Opening the Sage unrolls it: the bottom roller travels down from the top one and the paper is revealed behind
   it. The clip and the roller are both measured from the padding box and move the same distance with the same
   timing, so the paper's edge stays 2px under the roller all the way. Closing plays it back. */
.chat-floating .chat-panel {
    animation: scroll-unroll 0.6s ease-out;
}

.chat-floating .chat-panel::after {
    animation: scroll-roller-down 0.6s ease-out;
}

.chat-floating.chat-rolling-up .chat-panel,
.chat-floating.chat-rolling-up .chat-panel::after {
    animation-direction: reverse;
    animation-timing-function: ease-in;
    animation-fill-mode: forwards;
}

/* Restart the animations for rolling up (an animation does not replay just because its direction changed) */
.chat-floating.chat-rolling-up .chat-panel {
    animation-name: scroll-roll-up;
}

.chat-floating.chat-rolling-up .chat-panel::after {
    animation-name: scroll-roller-up;
}

@keyframes scroll-unroll {
    from { clip-path: inset(-40px -60px calc(100% + 10px) -60px) padding-box; }
    to { clip-path: inset(-40px -60px -38px -60px) padding-box; }
}

@keyframes scroll-roll-up {
    from { clip-path: inset(-40px -60px calc(100% + 10px) -60px) padding-box; }
    to { clip-path: inset(-40px -60px -38px -60px) padding-box; }
}

@keyframes scroll-roller-down {
    from { top: -38px; }
    to { top: calc(100% + 10px); }
}

@keyframes scroll-roller-up {
    from { top: -38px; }
    to { top: calc(100% + 10px); }
}

@media (prefers-reduced-motion: reduce) {
    .chat-floating .chat-panel,
    .chat-floating .chat-panel::after {
        animation: none !important;
    }
}

.chat-floating .chat-panel {
    height: 100%;
    margin: 0;
}

/* The messages take whatever room is left, so a long reply scrolls instead of squeezing the help or the input */
.chat-floating .chat-messages {
    flex: 1 1 0;
    min-height: 0;
    overflow-y: auto;
}

.chat-floating .chat-input {
    /* 30% of the scroll's writing area (its height less the 24px frame), so it fits beside the opened help */
    max-height: calc((min(560px, 100vh - 150px) - 48px) * 0.3);
}

.chat-floating-fab {
    position: fixed;
    right: 20px;
    bottom: 20px;
    z-index: 1051;
    padding: 8px 20px;
    background: var(--oxblood);
    border: 2px solid var(--rule-gold);
    border-radius: 28px;
    color: var(--parchment-light);
    font-family: var(--font-heading);
    font-size: 1.35rem;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
}

.chat-floating-fab:hover {
    background: #74241a;
}

.chat-close-btn {
    margin-left: auto;
    margin-right: 0;
    background: none;
    border: none;
    font-size: 1.75rem;
    line-height: 1;
    color: var(--oxblood);
}

@media (max-width: 768px) {
    .chat-floating {
        right: 30px;
        left: 30px;
        width: auto;
    }
}

/* "Does this change the world state?" after a plot thread edit (static/js/sage-ask.js); bottom left, clear of the
   Sage's button */
.sage-ask-banner {
    position: fixed;
    left: 20px;
    bottom: 20px;
    z-index: 1052;
    max-width: min(380px, calc(100vw - 40px));
    padding: 12px 14px;
    background: var(--parchment-light);
    border: 2px solid var(--rule-gold);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
    font-family: var(--font-body);
    color: var(--text-dark);
}

.sage-ask-banner p {
    margin: 0 0 10px;
}

.sage-ask-banner .btn {
    margin-right: 8px;
}

.sage-ask-yes {
    background: var(--oxblood);
    border: 2px solid var(--leather-darker);
    color: var(--parchment-light);
}

.sage-ask-no {
    background: transparent;
    border: 1px solid var(--rule-gold);
    color: var(--leather-dark);
}

/* Sage status line and proposal card sit under the reply bubble, full width, not beside it */
.chat-message-ai {
    flex-wrap: wrap;
}

.chat-message-ai > .chat-status,
.chat-message-ai > .sage-card {
    flex: 0 0 100%;
    box-sizing: border-box;
}

/* Sage status line while it looks something up */
.chat-status {
    margin: 4px 0 0 2px;
    font-size: 0.85rem;
    font-style: italic;
    color: var(--leather-dark);
    opacity: 0.8;
}

/* Sage proposal checklist, styled like the chat bubbles */
.sage-card {
    margin: 8px 0 0;
    padding: 10px 12px;
    background: var(--parchment-light);
    border: 1px solid var(--rule-gold);
    box-shadow: 0 2px 4px rgba(44, 24, 16, 0.2);
    font-family: var(--font-body);
    font-size: 0.9rem;
    color: var(--text-dark);
    overflow-wrap: anywhere;
}
.sage-card-title {
    margin: 0 0 6px;
    font-family: var(--font-heading);
    font-size: 1.25rem;
    color: var(--oxblood);
    border-bottom: 2px solid var(--rule-gold);
    padding-bottom: 2px;
}
.sage-card-summary { margin: 0 0 8px; font-style: italic; }
.sage-card-rows { list-style: none; padding: 0; margin: 0 0 8px; }
.sage-row { padding: 4px 0; border-bottom: 1px dotted var(--parchment-dark); }
.sage-row:last-child { border-bottom: none; }
.sage-row > label {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: 8px;
    align-items: start;
    cursor: pointer;
    margin: 0;
}
.sage-row > label > input { margin-top: 3px; }
.sage-row-also { grid-column: 2; opacity: 0.75; }
.sage-row-delete .sage-row-label { color: var(--danger); font-weight: bold; }
.sage-row-result { display: block; margin-left: 22px; font-size: 0.85rem; }
.sage-row-result:empty { display: none; }
.sage-row-result.is-applied { color: var(--success); }
.sage-row-result.is-failed { color: var(--danger); }
.sage-row-result.is-skipped { opacity: 0.6; }
.sage-row-details { margin: 2px 0 0 22px; font-size: 0.8rem; opacity: 0.8; }
.sage-row-details summary { cursor: pointer; }
.sage-row-detail-line { white-space: pre-wrap; margin: 2px 0 0; }
.sage-row-detail-more { margin: 2px 0 0; }
.sage-row-detail-more summary { cursor: pointer; white-space: pre-wrap; }
.session-logging-help { font-size: 0.85rem; margin: 0 0 8px; }
.session-logging-help summary { cursor: pointer; font-weight: 600; }
/* Keeps its size however long the chat or tall the input gets; opened, it scrolls within 40% of the scroll */
.chat-floating .session-logging-help {
    flex: 0 0 auto;
    padding: 4px 12px;
    max-height: 40%;
    overflow-y: auto;
}
.sage-card-note { min-height: 1em; margin: 0 0 8px; font-size: 0.85rem; font-style: italic; }
.sage-card-note:empty { display: none; }
.sage-card-stale:empty { display: none; }
.sage-card-stale { margin: 0 0 8px; font-size: 0.85rem; color: var(--danger); }
.sage-card-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.sage-card-actions button,
.sage-card-stale button {
    font-family: var(--font-heading);
    border-radius: 3px;
    padding: 4px 14px;
    cursor: pointer;
    box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
/* Apply is the card's main action (oxblood, like btn-primary); Dismiss and Reload are utility */
.sage-apply {
    background: var(--oxblood);
    border: 2px solid var(--leather-darker);
    color: var(--parchment-light);
}
.sage-dismiss,
.sage-reload {
    background: var(--parchment-light);
    border: 1px solid var(--rule-gold);
    color: var(--leather-dark);
}
.sage-card-actions button:disabled { opacity: 0.6; cursor: default; }
.sage-card-locked { opacity: 0.9; }

/* Pictures: an NPC's portrait on its page and its round thumbnail on the list */
.npc-portrait {
    max-width: 220px;
    border: 1px solid var(--rule-gold);
    object-fit: cover;
}

.npc-thumb {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--rule-gold);
}

/* A location's gallery: a grid of tiles that opens in the picture viewer */
.picture-gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 0.75rem;
}

.picture-tile img {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
}

/* The full-size picture pop-up, and the resized preview shown before saving */
.picture-viewer {
    max-width: 95vw;
    max-height: 95vh;
    padding: 0;
}

.picture-viewer::backdrop {
    background: rgba(0, 0, 0, 0.7);
}

.picture-viewer img {
    max-width: 100%;
    max-height: 90vh;
}

.picture-preview {
    max-height: 200px;
}
