
:root {
    --bg: #090819;
    --panel: rgba(22, 18, 43, 0.92);
    --panel2: rgba(31, 23, 57, 0.95);
    --border: rgba(255, 213, 116, 0.34);
    --gold: #ffd46e;
    --blue: #7bdcff;
    --green: #6dffb5;
    --rose: #ff8bb8;
    --text: #fff5dd;
    --muted: #d1c5ff;
    --danger: #ff6376;
    --shadow: 0 20px 60px rgba(0,0,0,0.38);
}

* {
    box-sizing: border-box;
}

body {
    margin: 0;
    min-height: 100vh;
    color: var(--text);
    font-family: "Trebuchet MS", system-ui, sans-serif;
    background:
        radial-gradient(circle at 12% 8%, rgba(123, 220, 255, 0.16), transparent 30%),
        radial-gradient(circle at 92% 3%, rgba(255, 139, 184, 0.15), transparent 28%),
        linear-gradient(135deg, #080716, #151131 45%, #2b112f);
}

body::before {
    content: "";
    position: fixed;
    inset: 0;
    pointer-events: none;
    background:
        radial-gradient(circle at 18px 18px, rgba(255, 217, 120, 0.12) 0 2px, transparent 3px),
        linear-gradient(rgba(255,255,255,0.02) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255,255,255,0.02) 1px, transparent 1px);
    background-size: 120px 120px, 80px 80px, 80px 80px;
    opacity: 0.8;
}

.topbar {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 18px;
    border-bottom: 1px solid var(--border);
    background: rgba(9, 8, 25, 0.88);
    backdrop-filter: blur(12px);
}

.brand {
    color: var(--gold);
    font-family: Georgia, serif;
    font-size: 1.4rem;
    font-weight: 900;
    text-decoration: none;
}

.app-name {
    /* The project wordmark, centered in the free space between the logo and
       the nav. Darkish brown, with a faint light edge so it stays legible on
       the dark topbar. */
    margin: 0 auto;
    font-family: "Cinzel", Georgia, serif;
    font-size: 1.5rem;
    font-weight: 800;
    letter-spacing: 0.06em;
    color: #5a3a1e;
    text-shadow: 0 1px 0 rgba(255, 224, 178, 0.18);
    user-select: none;
    pointer-events: none;
    white-space: nowrap;
}

.topbar nav {
    display: flex;
    gap: 8px;
}

.topbar a,
.button,
button {
    border: 1px solid rgba(255, 213, 116, 0.4);
    border-radius: 12px;
    padding: 9px 12px;
    color: #21132f;
    font-weight: 800;
    background: linear-gradient(180deg, #ffe28a, #ffbd4d);
    text-decoration: none;
    cursor: pointer;
    box-shadow: 0 10px 22px rgba(0,0,0,0.24);
}

button:hover,
.button:hover,
.topbar a:hover {
    filter: brightness(1.08);
    transform: translateY(-1px);
}

button.danger,
.danger {
    color: white;
    background: linear-gradient(180deg, #ff7a86, #bd3346);
    border-color: rgba(255, 120, 135, 0.5);
}

button:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

.account-pill {
    border: 1px solid rgba(123,220,255,0.32);
    border-radius: 999px;
    padding: 6px 10px;
    color: var(--blue);
}

main {
    position: relative;
    z-index: 1;
    padding: 18px;
}

h1,
h2,
h3,
summary {
    font-family: Georgia, "Times New Roman", serif;
    color: var(--gold);
}

.hero,
.login-card,
.home-tile,
.side-panel,
.right-panel,
.board-shell,
details,
.panel-card {
    border: 1px solid var(--border);
    border-radius: 20px;
    background:
        linear-gradient(180deg, var(--panel2, rgba(30, 24, 58, 0.93)), var(--panel, rgba(12, 10, 29, 0.95)));
    box-shadow: var(--shadow);
}

.hero {
    padding: 28px;
    margin-bottom: 18px;
}

.hero h1 {
    font-size: clamp(2.2rem, 5vw, 4rem);
    margin: 0 0 10px;
}

.login-card {
    max-width: 460px;
    margin: 8vh auto;
    padding: 26px;
}

.default-login-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin: 14px 0;
}

.default-login-grid div {
    border: 1px solid rgba(123,220,255,0.25);
    border-radius: 14px;
    padding: 12px;
    background: rgba(0,0,0,0.18);
}

code {
    display: block;
    color: var(--green);
    margin-top: 4px;
}

.stack-form {
    display: grid;
    gap: 9px;
}

.inline-form {
    display: grid;
    grid-template-columns: minmax(0,1fr) auto;
    gap: 8px;
    margin: 8px 0;
}

input,
select,
textarea {
    width: 100%;
    border: 1px solid rgba(123,220,255,0.28);
    border-radius: 12px;
    padding: 10px 12px;
    background: rgba(7, 7, 24, 0.78);
    color: var(--text);
    outline: none;
}

textarea {
    min-height: 84px;
    resize: vertical;
}

label {
    color: #ffe6a2;
    font-weight: 800;
}

.hint {
    color: var(--muted);
}

.flash-stack {
    display: grid;
    gap: 8px;
    margin-bottom: 12px;
}

.flash {
    border: 1px solid rgba(123,220,255,0.36);
    border-radius: 14px;
    padding: 10px 12px;
    background: rgba(22,18,43,0.9);
}

.home-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 18px;
}

.home-tile {
    padding: 24px;
    text-decoration: none;
    color: var(--text);
    transition: transform 140ms ease;
}

.home-tile:hover {
    transform: translateY(-3px);
}

.tile-icon {
    font-size: 2rem;
}

.page-title,
.board-top {
    display: flex;
    justify-content: space-between;
    gap: 14px;
    align-items: center;
    margin-bottom: 12px;
}

.editor-layout {
    display: grid;
    grid-template-columns: 360px minmax(0, 1fr);
    gap: 14px;
    height: calc(100vh - 112px);
}

.board-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 360px;
    gap: 14px;
    height: calc(100vh - 76px);
}

.side-panel,
.right-panel {
    padding: 12px;
}

.scroll-panel {
    overflow: auto;
}

details {
    padding: 12px;
    margin-bottom: 10px;
}

summary {
    cursor: pointer;
    font-size: 1.1rem;
    font-weight: 900;
}

.board-shell {
    position: relative;
    display: grid;
    grid-template-rows: auto auto minmax(0, 1fr);
    gap: 10px;
    padding: 12px;
    min-height: 480px;
}

.editor-board {
    grid-template-rows: auto auto minmax(0, 1fr);
}

.calendar-strip {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.calendar-pill {
    border: 1px solid rgba(255,213,116,0.3);
    border-radius: 999px;
    padding: 6px 10px;
    background: rgba(255,213,116,0.08);
    color: #ffe6a2;
    font-weight: 800;
}

.board-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
}

.tool.active {
    outline: 3px solid rgba(123,220,255,0.35);
    background: linear-gradient(180deg, #8fffe0, #54c993);
}

.map-viewport {
    position: relative;
    overflow: hidden;
    border: 1px solid rgba(123,220,255,0.28);
    border-radius: 18px;
    background: rgba(0,0,0,0.42);
    min-height: 0;
}

.map-content {
    position: absolute;
    top: 0;
    left: 0;
    transform-origin: top left;
    /* Promote to its own GPU compositing layer. Without this, every zoom/pan
       transform forced the browser to re-rasterize ALL children on the CPU
       each frame (the map image, the grid, the fog SVG with its masks, the
       185-wall obstruction SVG, tokens, light glows) - which made camera
       movement and zooming choppy. With a dedicated layer the transform is a
       cheap GPU composite instead. (JS sets the actual transform in applyCrop;
       will-change just asks for the layer - we don't set transform here or it
       would override the JS value.) */
    will-change: transform;
    backface-visibility: hidden;
}

.map-image {
    display: block;
    user-select: none;
    pointer-events: none;
}

.grid-layer,
.fog-layer,
.token-layer,
.drag-preview-layer,
.archer-range-layer,
.measure-layer {
    position: absolute;
    inset: 0;
}

.grid-layer,
.fog-layer,
.archer-range-layer,
.measure-layer {
    pointer-events: none;
}

.drag-preview-layer {
    pointer-events: none;
}

.token-layer {
    pointer-events: none;
}

.token {
    position: absolute;
    display: grid;
    place-items: center;
    border: 3px solid rgba(255,255,255,0.86);
    border-radius: 50%;
    background: var(--gold);
    color: #170d20;
    font-weight: 900;
    overflow: visible;
    cursor: grab;
    transform: translate(-50%, -50%);
    transition: left var(--move-duration, 110ms) linear, top var(--move-duration, 110ms) linear;
    box-shadow: 0 10px 24px rgba(0,0,0,0.48);
    pointer-events: auto;
    user-select: none;
}

.token.dragging {
    transition: none;
    z-index: 10;
    cursor: grabbing;
}

.token.dm-layer {
    border-color: rgba(255,139,184,0.9);
    opacity: 0.72;
}

.token.dead {
    filter: grayscale(0.85) brightness(0.75);
    border-color: rgba(200, 60, 60, 0.85);
    cursor: pointer;
}

.token-dead-badge {
    position: absolute;
    top: -10px;
    right: -6px;
    font-size: 0.95rem;
    filter: none;
    text-shadow: 0 2px 3px rgba(0,0,0,0.7);
}

.token-lock-badge {
    position: absolute;
    top: -10px;
    left: -6px;
    font-size: 0.85rem;
    text-shadow: 0 2px 3px rgba(0,0,0,0.7);
}

.token-conditions {
    position: absolute;
    bottom: -8px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 2px;
    filter: none;
}

.token-conditions span {
    font-size: 0.7rem;
    background: rgba(0,0,0,0.6);
    border-radius: 999px;
    padding: 1px 3px;
    line-height: 1;
}

.condition-checklist {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4px 10px;
    margin-bottom: 4px;
}

.condition-checkbox {
    font-size: 0.82rem;
}

.archer-range-ring {
    fill: rgba(255, 99, 118, 0.08);
    stroke: rgba(255, 99, 118, 0.85);
    stroke-width: 2;
    stroke-dasharray: 10 7;
}

.aoe-shape {
    fill: rgba(255, 178, 87, 0.22);
    stroke: rgba(255, 178, 87, 0.9);
    stroke-width: 2;
    stroke-linejoin: round;
}

.aoe-shape.aoe-shape-line {
    fill: none;
    stroke: rgba(255, 178, 87, 0.55);
    stroke-linecap: round;
}

.aoe-shape.aoe-final {
    animation: aoe-fade 6s ease-out forwards;
}

@keyframes aoe-fade {
    0%   { opacity: 1; }
    70%  { opacity: 0.85; }
    100% { opacity: 0; }
}

.token.aoe-caught {
    box-shadow: 0 0 0 4px rgba(255, 99, 60, 0.85), 0 10px 24px rgba(0,0,0,0.48);
}

.archer-range-menu {
    position: fixed;
    z-index: 90;
    transform: translate(-10px, -10px);
    background: var(--panel2);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 10px 14px;
    box-shadow: var(--shadow);
    display: grid;
    gap: 6px;
    min-width: 180px;
}

.loot-lock-status {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    background: rgba(200, 60, 60, 0.14);
    border: 1px solid rgba(200, 60, 60, 0.4);
    border-radius: 10px;
    padding: 8px 10px;
    margin: 4px 0 10px;
    font-size: 0.85rem;
}

.token-loot-inventory-list {
    display: grid;
    gap: 6px;
    margin: 6px 0 12px;
}

.token-loot-inventory-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 6px 10px;
    border-radius: 8px;
    background: rgba(0,0,0,0.22);
    font-size: 0.85rem;
}

.handout-upload-form {
    margin-bottom: 10px;
    padding-bottom: 10px;
    border-bottom: 1px dashed rgba(255,255,255,0.15);
}

.handout-list {
    display: grid;
    gap: 6px;
    max-height: 320px;
    overflow-y: auto;
}

.handout-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 10px;
    text-align: left;
    border-radius: 10px;
}

.handout-thumb {
    width: 34px;
    height: 34px;
    border-radius: 6px;
    object-fit: cover;
    flex-shrink: 0;
}

.handout-thumb-placeholder {
    display: grid;
    place-items: center;
    background: rgba(0,0,0,0.3);
    font-size: 1.1rem;
}

.handout-row-title {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.handout-full-image {
    width: 100%;
    max-height: 360px;
    object-fit: contain;
    border-radius: 10px;
    margin-bottom: 12px;
    background: rgba(0,0,0,0.3);
}

.handout-full-text {
    white-space: pre-wrap;
    line-height: 1.5;
}

.token img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%;
}

.token-name {
    position: absolute;
    bottom: -23px;
    left: 50%;
    transform: translateX(-50%);
    border-radius: 999px;
    padding: 2px 7px;
    background: rgba(0,0,0,0.72);
    color: #fff5dd;
    font-size: 0.72rem;
    white-space: nowrap;
}

.fog-block {
    position: absolute;
    background: rgba(0,0,0,1);
    border: 1px solid rgba(255,255,255,0.04);
}

body.role-dm .fog-block {
    background: rgba(0,0,0,0.46);
    border: 1px solid rgba(255,139,184,0.22);
}

.measure-readout {
    position: absolute;
    left: 14px;
    bottom: 14px;
    border: 1px solid rgba(123,220,255,0.36);
    border-radius: 12px;
    padding: 8px 10px;
    background: rgba(0,0,0,0.68);
    color: var(--blue);
    font-weight: 900;
    pointer-events: none;
    display: none;
}

.measure-readout.visible {
    display: block;
}

.tree-list,
.map-library,
.token-editor-list,
.chat-log,
.quest-box {
    display: grid;
    gap: 8px;
}

.tree-node,
.map-preview,
.token-row,
.chat-message,
.quest-card {
    border: 1px solid rgba(123,220,255,0.22);
    border-radius: 14px;
    padding: 10px;
    background: rgba(0,0,0,0.18);
}

.map-preview {
    cursor: pointer;
    transition: transform 120ms ease, border-color 120ms ease;
}

.map-preview:hover {
    transform: translateY(-1px);
    border-color: rgba(255,213,116,0.62);
}

.map-preview img {
    width: 100%;
    height: 130px;
    object-fit: cover;
    border-radius: 10px;
    display: block;
    margin-bottom: 7px;
}

.token-row {
    display: grid;
    gap: 8px;
}

.token-row-top {
    display: flex;
    justify-content: space-between;
    gap: 8px;
}

.badge {
    border: 1px solid rgba(255,213,116,0.26);
    border-radius: 999px;
    padding: 3px 7px;
    color: #ffe6a2;
    font-size: 0.78rem;
}

.chat-log {
    max-height: 280px;
    overflow: auto;
}

.chat-message strong {
    color: var(--gold);
}

.roll-result {
    color: var(--green);
    font-weight: 900;
}

.chat-form {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 8px;
    margin-top: 8px;
}

.quest-objective {
    display: flex;
    gap: 8px;
    align-items: center;
}

.quest-objective.done {
    opacity: 0.55;
    text-decoration: line-through;
}

.fog-preview {
    position: absolute;
    border: 2px dashed var(--rose);
    background: rgba(255,139,184,0.16);
    pointer-events: none;
}

@media (max-width: 1100px) {
    .editor-layout,
    .board-layout {
        grid-template-columns: 1fr;
        height: auto;
    }

    .board-shell {
        height: 72vh;
    }
}

@media (max-width: 720px) {
    main {
        padding: 10px;
    }

    .page-title,
    .board-top {
        align-items: stretch;
        flex-direction: column;
    }

    .topbar {
        flex-wrap: wrap;
    }

    .board-toolbar button {
        flex: 1;
    }
}


/* v0.2 fixes and Roll20-like controls */
.path-display {
    border: 1px solid rgba(123,220,255,0.26);
    border-radius: 12px;
    padding: 10px 12px;
    background: rgba(0,0,0,0.22);
    color: var(--green);
    font-weight: 900;
}

.modal-backdrop {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: none;
    background: rgba(0,0,0,0.72);
    backdrop-filter: blur(8px);
    padding: 24px;
    overflow: auto;
}

.modal-backdrop.open {
    display: block;
}

.path-picker-modal {
    max-width: 720px;
    margin: 5vh auto;
    border: 1px solid var(--border, rgba(255,213,116,0.42));
    border-radius: 22px;
    padding: 18px;
    background:
        linear-gradient(180deg, var(--panel2, rgba(30, 24, 58, 0.98)), var(--panel, rgba(12, 10, 29, 0.98)));
    box-shadow: var(--shadow, 0 30px 80px rgba(0,0,0,0.62));
}

.modal-top {
    display: flex;
    align-items: start;
    justify-content: space-between;
    gap: 12px;
}

.path-picker-list {
    display: grid;
    gap: 8px;
    margin-top: 12px;
    max-height: 46vh;
    overflow: auto;
}

.path-choice {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    width: 100%;
    color: var(--text);
    background: rgba(0,0,0,0.22);
}

.wide-map-button {
    width: 100%;
    text-align: left;
    margin: 5px 0;
    color: var(--text);
    background: rgba(0,0,0,0.22);
}

.map-viewport.crop-mode {
    cursor: grab;
}

.token-bubbles {
    position: absolute;
    display: flex;
    gap: 4px;
    top: -30px;
    left: 50%;
    transform: translateX(-50%);
    pointer-events: none;
}

.token-bubble {
    min-width: 34px;
    max-width: 70px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    border: 1px solid rgba(255,255,255,0.55);
    border-radius: 999px;
    padding: 2px 6px;
    background: rgba(0,0,0,0.74);
    color: white;
    font-size: 0.72rem;
    text-align: center;
}

.bubble-1 {
    background: rgba(92, 226, 160, 0.82);
    color: #05140d;
}

.bubble-2 {
    background: rgba(123, 220, 255, 0.82);
    color: #06121a;
}

.bubble-3 {
    background: rgba(255, 139, 184, 0.82);
    color: #1d0610;
}

.token-popover {
    position: absolute;
    left: 14px;
    top: 74px;
    z-index: 30;
    width: min(360px, calc(100% - 28px));
    display: none;
    border: 1px solid var(--border, rgba(255,213,116,0.46));
    border-radius: 18px;
    padding: 12px;
    background:
        linear-gradient(180deg, var(--panel2, rgba(30, 24, 58, 0.98)), var(--panel, rgba(12, 10, 29, 0.98)));
    box-shadow: var(--shadow, 0 24px 60px rgba(0,0,0,0.58));
}

.token-popover.open {
    display: grid;
    gap: 8px;
}

.popover-top {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    align-items: center;
}

.popover-top button {
    width: 38px;
    height: 38px;
    padding: 0;
}

.token-bars-editor {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 6px;
}

.checkbox-label {
    display: flex;
    align-items: center;
    gap: 8px;
}

.checkbox-label input {
    width: auto;
}

.chat-message.system {
    color: var(--blue);
    font-style: italic;
    opacity: 0.8;
}


/* v0.3 folder tree and wildshape-style map selector */
.board-top-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    justify-content: flex-end;
}

.folder-tree-list {
    display: grid;
    gap: 8px;
}

.folder-node summary {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 8px;
}

.folder-summary-main {
    cursor: pointer;
    color: var(--gold);
}

.folder-actions {
    display: flex;
    gap: 6px;
}

.folder-actions button {
    width: 34px;
    height: 34px;
    padding: 0;
    display: grid;
    place-items: center;
}

.folder-children {
    margin-left: 14px;
    padding-left: 10px;
    border-left: 1px solid rgba(123,220,255,0.22);
}

.folder-map-list {
    display: grid;
    gap: 6px;
    margin: 8px 0;
}

.map-selector-modal {
    max-width: 1120px;
    margin: 4vh auto;
    border: 1px solid var(--border, rgba(255,213,116,0.42));
    border-radius: 24px;
    padding: 18px;
    /* Theme-driven panel so the town/map modal follows the active theme
       instead of staying purple under Dungeon, Forest, Infernal, etc. */
    background:
        linear-gradient(180deg, var(--panel2, rgba(30, 24, 58, 0.98)), var(--panel, rgba(12, 10, 29, 0.98)));
    box-shadow: var(--shadow, 0 30px 80px rgba(0,0,0,0.62));
}

.map-selector-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 14px;
    margin-top: 16px;
}

.selector-tile {
    min-height: 180px;
    border: 1px solid rgba(123,220,255,0.28);
    border-radius: 18px;
    padding: 12px;
    background:
        linear-gradient(180deg, rgba(24, 20, 43, 0.92), rgba(9, 8, 25, 0.96)),
        radial-gradient(circle at 100% 0%, rgba(255, 139, 184, 0.10), transparent 30%);
    cursor: pointer;
    display: grid;
    align-content: start;
    gap: 8px;
    transition: transform 130ms ease, border-color 130ms ease;
}

.selector-tile:hover {
    transform: translateY(-2px);
    border-color: rgba(255,213,116,0.68);
}

.selector-folder-icon {
    height: 110px;
    display: grid;
    place-items: center;
    font-size: 4.2rem;
    border-radius: 14px;
    background: rgba(0,0,0,0.22);
}

.map-tile img {
    width: 100%;
    height: 120px;
    object-fit: cover;
    border-radius: 14px;
    border: 1px solid rgba(255,255,255,0.12);
}

.map-tile strong,
.folder-tile strong {
    color: var(--gold);
    font-size: 1.05rem;
}

@media (max-width: 720px) {
    .map-selector-grid {
        grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    }

    .selector-tile {
        min-height: 150px;
    }
}


/* v0.4 Roll20-style local map zoom and pan */
.map-viewport {
    overscroll-behavior: contain;
}

.map-viewport.panning {
    cursor: grabbing !important;
}

.zoom-readout {
    position: absolute;
    right: 14px;
    bottom: 14px;
    z-index: 20;
    border: 1px solid rgba(123,220,255,0.38);
    border-radius: 999px;
    padding: 6px 10px;
    background: rgba(0,0,0,0.68);
    color: var(--blue);
    font-weight: 900;
    pointer-events: none;
}

#reset-view-button {
    background: linear-gradient(180deg, #a9e9ff, #64c6e9);
}


/* v0.5 folder rename and NPC automatic movement */
.folder-summary-main::after {
    content: "  right-click rename";
    color: var(--muted);
    font-size: 0.74rem;
    font-family: "Trebuchet MS", system-ui, sans-serif;
    opacity: 0.72;
}

.npc-path-layer {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: visible;
}

.token-popover h3 {
    margin: 8px 0 0;
    color: var(--green);
}

.token-popover hr {
    width: 100%;
    border: none;
    border-top: 1px solid rgba(123,220,255,0.24);
    margin: 8px 0;
}

.token.dm-layer::after {
    content: "DM";
    position: absolute;
    right: -10px;
    top: -10px;
    border-radius: 999px;
    padding: 2px 6px;
    background: rgba(255,139,184,0.95);
    color: #1d0610;
    font-size: 0.65rem;
    font-weight: 900;
}

.token[data-npc-auto="1"] .token-name::before {
    content: "↻ ";
    color: var(--green);
}


/* v0.6 map manager, smoother NPCs, darkvision and torch fog circles */
.manager-upload-panel {
    border: 1px solid rgba(123,220,255,0.24);
    border-radius: 18px;
    padding: 12px;
    background: rgba(0,0,0,0.18);
    margin-top: 12px;
}

.manager-upload-form {
    display: grid;
    grid-template-columns: 1.2fr 1fr 130px 1.2fr auto;
    gap: 10px;
    align-items: end;
}

.compact-folder-tree {
    margin-top: 12px;
    max-height: 36vh;
    overflow: auto;
}

.create-folder-tile .selector-folder-icon {
    color: var(--green);
    font-size: 5rem;
}

.speed-slider-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 86px;
    gap: 8px;
    align-items: center;
}

.speed-slider-row input[type="range"] {
    padding: 0;
}

.fog-svg,
.vision-circle-svg {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: visible;
}

.vision-circle,
.torch-circle {
    fill: rgba(123, 220, 255, 0.08);
    stroke: rgba(123, 220, 255, 0.95);
    stroke-width: 3;
    stroke-dasharray: 10 8;
    pointer-events: none;
}

.torch-circle {
    fill: rgba(255, 213, 116, 0.10);
    stroke: rgba(255, 213, 116, 0.98);
    stroke-dasharray: none;
}

.token[data-vision="1"]::before {
    content: "";
    position: absolute;
    inset: -7px;
    border: 2px solid rgba(123,220,255,0.72);
    border-radius: 50%;
    pointer-events: none;
}

#stop-all-npc-button {
    background: linear-gradient(180deg, #ff7a86, #bd3346);
}

@media (max-width: 1050px) {
    .manager-upload-form {
        grid-template-columns: 1fr;
    }
}


/* v0.7 combat, shops, first folder prompt, weather and token image mask */
.weather-layer {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 7;
}

.map-viewport.night-mode::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 6;
    pointer-events: none;
    background:
        radial-gradient(circle at 50% 42%, rgba(20, 25, 70, 0.18), rgba(0, 0, 18, 0.48)),
        linear-gradient(180deg, rgba(6, 8, 36, 0.22), rgba(3, 4, 20, 0.54));
    mix-blend-mode: multiply;
}

.rain-lines {
    position: absolute;
    inset: 0;
    opacity: calc(var(--rain-opacity, 0.5) * 0.6);
    overflow: hidden;
    z-index: 2;
    mix-blend-mode: screen;
}

.rain-lines i {
    position: absolute;
    top: 0;
    width: 1.5px;
    height: 68px;
    background: linear-gradient(180deg, rgba(210,238,255,0), rgba(210,238,255,0.7));
    animation: rain-fall 0.8s linear infinite;
}

@keyframes rain-fall {
    from { top: -12%; transform: rotate(13deg); }
    to   { top: 112%; transform: rotate(13deg); }
}

.snow-flakes {
    position: absolute;
    inset: 0;
    opacity: var(--weather-opacity, 0.5);
    overflow: hidden;
}

.snow-flakes i {
    position: absolute;
    top: -3%;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.9);
    box-shadow: 0 0 3px rgba(255,255,255,0.6);
    animation: snow-fall linear infinite;
}

@keyframes snow-fall {
    from { top: -4%; transform: translateX(0); }
    50%  { transform: translateX(20px); }
    to   { top: 106%; transform: translateX(-8px); }
}

.fog-drift {
    position: absolute;
    inset: -20%;
    opacity: var(--weather-opacity, 0.5);
    background:
        radial-gradient(ellipse 60% 40% at 20% 30%, rgba(220, 225, 235, 0.55), transparent 60%),
        radial-gradient(ellipse 55% 45% at 75% 60%, rgba(220, 225, 235, 0.5), transparent 65%),
        radial-gradient(ellipse 50% 35% at 45% 85%, rgba(220, 225, 235, 0.4), transparent 60%);
    filter: none;
    /* Full-screen blur is disabled on the board. Even without animation it can
       force a large offscreen surface during camera transforms. */
    transform: translateX(0) translateY(-1%);
}

@keyframes fog-drift {
    from { transform: translateX(-3%) translateY(0); }
    to   { transform: translateX(3%) translateY(-2%); }
}

.storm-flash {
    position: absolute;
    inset: 0;
    background: rgba(220, 230, 255, 0.9);
    opacity: 0;
    animation: storm-flash 7s ease-in-out infinite;
}

@keyframes storm-flash {
    0%, 91%, 100% { opacity: 0; }
    92%  { opacity: 0.55; }
    92.6% { opacity: 0.05; }
    93.2% { opacity: 0.4; }
    94%  { opacity: 0; }
}

.map-viewport.fog-mode::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 6;
    pointer-events: none;
    background: rgba(180, 190, 205, 0.14);
    mix-blend-mode: screen;
}

.token-face {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    border-radius: 50%;
    overflow: hidden;
}

.token-face img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%;
    display: block;
}

.token.combat-active {
    outline: 5px solid rgba(255, 213, 116, 0.95);
    box-shadow:
        0 0 0 8px rgba(255, 213, 116, 0.20),
        0 0 34px rgba(255, 213, 116, 0.75),
        0 10px 24px rgba(0,0,0,0.48);
    z-index: 25;
}

.combat-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.combat-order {
    display: grid;
    gap: 7px;
    margin-top: 10px;
}

.combat-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto auto;
    gap: 7px;
    align-items: center;
    border: 1px solid rgba(123,220,255,0.22);
    border-radius: 12px;
    padding: 8px;
    background: rgba(0,0,0,0.18);
}

.combat-row.active {
    border-color: rgba(255,213,116,0.82);
    background: rgba(255,213,116,0.12);
}

.end-turn-button {
    width: 100%;
    margin: 8px 0;
    padding: 12px;
    font-size: 0.95rem;
    background: linear-gradient(180deg, rgba(109, 255, 181, 0.28), rgba(109, 255, 181, 0.12));
    border-color: rgba(109, 255, 181, 0.5);
}

.end-turn-button:disabled {
    opacity: 0.4;
    cursor: not-allowed;
    background: rgba(255,255,255,0.05);
}

.inline-initiative-label {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 0.78rem;
    color: var(--muted);
    margin: 4px 0;
}

.inline-initiative-input {
    width: 64px;
    text-align: center;
    padding: 5px 6px;
}

.inline-hp-row {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 0.78rem;
    color: var(--muted);
    margin: 4px 0;
    flex-wrap: wrap;
}

.death-save-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 4px 0;
}

.death-save-box input {
    width: 20px;
    height: 20px;
    cursor: pointer;
}

.death-save-box.success input {
    accent-color: #6dffb5;
}

.death-save-box.failure input {
    accent-color: #ff6376;
}

.lock-movement-button.active-lock {
    background: linear-gradient(180deg, #8f3126, #63201a);
    border-color: rgba(217, 122, 95, 0.55);
}

.mod-log-row {
    display: grid;
    grid-template-columns: auto auto 1fr auto;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border-radius: 8px;
    background: rgba(0,0,0,0.2);
    font-size: 0.8rem;
    margin-bottom: 5px;
}

.mod-log-row small {
    color: var(--muted);
    white-space: nowrap;
}

.town-editor-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}

.town-edit-card,
.shop-edit-card,
.shop-view-card {
    border: 1px solid rgba(123,220,255,0.22);
    border-radius: 14px;
    padding: 10px;
    background: rgba(0,0,0,0.18);
    margin-top: 10px;
    display: grid;
    gap: 8px;
}

.item-edit-row {
    display: grid;
    grid-template-columns: 1fr 90px 1.2fr auto;
    gap: 6px;
}

.shops-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 14px;
    margin-top: 14px;
}

/* Shop-detail view (stock grid + sell panel) reuses #shops-modal-content,
   which is a multi-column .shops-grid meant for the shop-LIST view. Its
   direct children need to explicitly span every column, or a single
   section like the sell panel only gets one column's width. */
.shops-modal-top,
.direct-sell-panel,
#shops-modal-content > .hint,
#shops-modal-content > .v099-stock-grid,
#shops-modal-content > .quest-corkboard {
    grid-column: 1 / -1;
}

.shops-modal-top {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

.shop-item-row {
    border-top: 1px solid rgba(255,255,255,0.08);
    padding-top: 8px;
    margin-top: 8px;
}

.shop-item-row span {
    color: var(--gold);
    font-weight: 900;
    float: right;
}

@media (max-width: 760px) {
    .combat-row,
    .item-edit-row {
        grid-template-columns: 1fr;
    }
}


/* v0.8 release-only movement, explored fog memory, token auto-hide */
.token.smooth-moving {
    transition-timing-function: ease-in-out;
}

.unseen-fog rect {
    fill: #05060a;
}
.unseen-fog {
    /* Fog "breathe" animation removed for performance (see torch-flicker note).
       The fog still renders solidly; it just no longer animates. */
    opacity: 1;
}
@keyframes unseen-fog-breathe {
    0%   { opacity: 0.96; }
    100% { opacity: 1; }
}

.seen-dim-fog rect {
    fill: rgba(0,0,0,0.78);
}

.seen-circle {
    fill: rgba(160, 170, 255, 0.04);
    stroke: rgba(160, 170, 255, 0.28);
    stroke-width: 2;
    stroke-dasharray: 4 8;
}

.seen-dim-fog {
    /* No blur: filters force the player fog layer to be rerasterized whenever
       vision moves. A flat dim overlay is much cheaper and visually clearer. */
    filter: none;
}

body.role-player .fog-svg {
    shape-rendering: optimizeSpeed;
}

/* Player fog is now a genuinely capped canvas bitmap. Do not promote the full
   6150px fog container to a separate GPU layer: that can exceed the texture or
   memory budget and force software compositing on weaker clients. The parent
   map-content layer handles camera transforms. */
body.role-player .fog-layer {
    will-change: auto;
    transform: none;
    contain: none;
    isolation: auto;
}

.fog-canvas {
    position: absolute;
    top: 0;
    left: 0;
    display: block;
    pointer-events: none;
    image-rendering: auto;
}


/* v0.9 sync, cleaner vision UI, stronger weather */
.dm-fog-rects rect {
    fill: rgba(0,0,0,0.38);
}

body.role-dm .fog-block {
    background: rgba(0,0,0,0.38);
}

body.role-player .vision-circle,
body.role-player .torch-circle {
    display: none;
}

.calendar-card {
    display: grid;
    gap: 6px;
    border: 1px solid rgba(123,220,255,0.24);
    border-radius: 14px;
    padding: 12px;
    background: rgba(0,0,0,0.18);
}

.calendar-card strong {
    color: var(--gold);
    font-size: 1.1rem;
}

.calendar-event-pill {
    background: rgba(255, 213, 116, 0.18);
    border: 1px solid rgba(255, 213, 116, 0.5);
}

.calendar-event-note {
    margin: 4px 0 0;
    padding: 6px 8px;
    border-radius: 8px;
    background: rgba(255, 213, 116, 0.12);
    font-size: 0.85rem;
}

.calendar-events-list {
    display: grid;
    gap: 6px;
    margin-top: 12px;
}

.calendar-event-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 6px 10px;
    border-radius: 8px;
    background: rgba(0,0,0,0.22);
    font-size: 0.82rem;
}

.town-editor-panel select {
    margin-bottom: 8px;
}

.token-popover h3 {
    margin-top: 12px;
}


/* v0.9.2 three-token-layer system */
.token.hidden-layer::after {
    content: "H";
    position: absolute;
    right: -10px;
    top: -10px;
    border-radius: 999px;
    padding: 2px 7px;
    background: rgba(123,220,255,0.95);
    color: #06121a;
    font-size: 0.65rem;
    font-weight: 900;
}

body.role-player .token.hidden-layer::after {
    display: none;
}

.token-row .badge {
    white-space: nowrap;
}


/* v0.9.4 compact board + build-up controls */
body.page-board main,
body.page-editor main {
    padding: 8px 10px;
}

body.page-board .topbar,
body.page-editor .topbar {
    padding: 7px 12px;
}

body.page-board .brand,
body.page-editor .brand {
    font-size: 1.1rem;
}

body.page-board .board-layout {
    height: calc(100vh - 56px);
    grid-template-columns: minmax(0, 1fr) 340px;
    gap: 10px;
}

body.page-editor .editor-layout {
    height: calc(100vh - 56px);
    grid-template-columns: 340px minmax(0, 1fr);
    gap: 10px;
}

body.page-board .board-shell,
body.page-editor .board-shell {
    padding: 10px;
    gap: 6px;
    min-height: 0;
}

body.page-board .board-top {
    margin: 0 0 4px;
    align-items: end;
}

body.page-board .board-top h1 {
    margin: 0;
    font-size: clamp(1.35rem, 2vw, 2rem);
}

body.page-board .board-top .hint {
    margin: 3px 0;
}

body.page-board .board-top-actions {
    gap: 8px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
}

body.page-board .board-top-actions details {
    display: none;
}

body.page-board .right-panel,
body.page-editor .side-panel {
    padding: 10px;
}

body.page-board details,
body.page-editor details {
    padding: 10px;
    margin-bottom: 8px;
}

body.page-board .board-toolbar,
body.page-editor .board-toolbar {
    gap: 7px;
    align-items: center;
}

body.page-board .board-toolbar button,
body.page-editor .board-toolbar button,
body.page-board .button,
body.page-editor .button {
    padding: 8px 11px;
}

.obstruction-layer {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 4;
}

body.role-dm .obstruction-layer {
    pointer-events: auto;
}

.wall-line {
    stroke: #ff6376;
    stroke-width: 5;
    stroke-linecap: round;
    opacity: 0.95;
    filter: drop-shadow(0 2px 3px rgba(0,0,0,0.7));
}

.door-line {
    stroke-width: 6;
    stroke-linecap: round;
    cursor: pointer;
    filter: drop-shadow(0 2px 3px rgba(0,0,0,0.7));
}

.door-line.closed {
    stroke: #ffd46e;
    stroke-dasharray: 10 6;
}

.door-line.open {
    stroke: #6dffb5;
    stroke-dasharray: 3 10;
    opacity: 0.65;
}

.small-builder-modal {
    max-width: 740px;
}

.character-sheet-panel {
    max-width: 960px;
    margin: 0 auto;
    border: 1px solid var(--border);
    border-radius: 20px;
    padding: 18px;
    background: var(--panel);
    box-shadow: var(--shadow);
}

.character-sheet-form textarea {
    min-height: 130px;
}

@media (max-width: 1100px) {
    body.page-board .board-layout,
    body.page-editor .editor-layout {
        height: calc(100vh - 52px);
    }

    body.page-board .right-panel {
        display: none;
    }

    body.page-board .board-layout {
        grid-template-columns: 1fr;
    }

    body.page-editor .editor-layout {
        grid-template-columns: 300px minmax(0, 1fr);
    }
}

@media (max-width: 820px) {
    body.page-editor .editor-layout {
        grid-template-columns: 1fr;
        height: auto;
    }

    body.page-editor .side-panel {
        max-height: 38vh;
        overflow: auto;
    }

    body.page-board .board-top-actions {
        justify-content: flex-start;
    }
}


/* v0.9.5 token/wall/sheet/database fixes */
body.role-player .obstruction-layer {
    display: none;
}

.obstruction-layer {
    pointer-events: none !important;
}

body.role-dm .obstruction-layer .door-line,
body.role-dm .obstruction-layer .wall-line {
    pointer-events: stroke;
}

.token-popover {
    position: fixed !important;
    left: auto !important;
    right: 18px !important;
    top: 74px !important;
    width: min(430px, calc(100vw - 36px)) !important;
    max-height: calc(100vh - 94px) !important;
    overflow-y: auto !important;
    overscroll-behavior: contain;
    z-index: 9000 !important;
}

.token-popover.open {
    display: grid;
}

.token-popover .popover-top {
    position: sticky;
    top: -12px;
    z-index: 5;
    background: rgba(22, 18, 43, 0.98);
    padding: 4px 0 8px;
}

.token-popover #tok-save {
    position: sticky;
    bottom: -12px;
    z-index: 5;
    box-shadow: 0 -12px 20px rgba(0,0,0,0.35);
}

.sheet-pro,
.database-section,
.character-sheet-panel {
    max-width: 1180px;
    margin: 0 auto 18px;
}

/* Character sheet: classic 5e paper layout. Identity banner up top,
   ability-score rail down the left, skills beside it, AC/Init/Speed
   shields and HP on the right, spell slots under those, item lists in
   two columns, notes across the bottom. Layout + dress only - every
   input id, name, and script hook is untouched. */
.sheet-pro {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: 12px;
    align-items: start;
}

.sheet-pro > .page-title { grid-column: 1 / -1; }
.sheet-pro > .area-identity { grid-column: 1 / -1; }
.sheet-pro > .area-wildshape { grid-column: 1 / -1; }
.sheet-pro > .area-abilities { grid-column: 1 / span 4; }
.sheet-pro > .area-combat    { grid-column: 1 / span 4; }
.sheet-pro > .area-defenses  { grid-column: 1 / span 4; }
.sheet-pro > .area-skills    { grid-column: 5 / -1; grid-row: span 3; }
.sheet-pro > .area-slots { grid-column: span 6; }
.sheet-pro > .area-list { grid-column: span 6; }
.sheet-pro > .area-notes { grid-column: 1 / -1; }
.sheet-pro > .sticky-save-bar { grid-column: 1 / -1; }

@media (max-width: 1050px) {
    .sheet-pro > .area-abilities,
    .sheet-pro > .area-defenses,
    .sheet-pro > .area-skills,
    .sheet-pro > .area-combat,
    .sheet-pro > .area-slots,
    .sheet-pro > .area-list {
        grid-column: 1 / -1;
        grid-row: auto;
    }
}

/* Combat card: 3-across mini-stats that fit the rail width */
.area-combat .form-grid { grid-template-columns: repeat(3, 1fr); gap: 8px; }
.area-combat .form-grid input,
.area-combat .form-grid .carry-weight-display { width: 100%; box-sizing: border-box; }
/* Abilities: 2 across in the rail */
.area-abilities .ability-grid { grid-template-columns: repeat(2, 1fr); }
/* Skills: 2 columns to fill the wide right area (kills the blank space) */
.area-skills .skills-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* Identity banner: big character name, everything else in a strip. */
.area-identity .form-grid {
    grid-template-columns: repeat(4, 1fr);
}

.area-identity .form-grid > div:first-child {
    grid-column: 1 / -1;
}

.area-identity input[name="character_name"] {
    font-size: 1.55rem;
    font-family: var(--display-font);
    padding: 10px 12px;
}

/* Ability rail: classic stacked stat boxes. */
.area-abilities .form-grid {
    grid-template-columns: 1fr;
    gap: 10px;
}

.area-abilities .form-grid > div {
    border: 2px double var(--border);
    border-radius: 12px;
    padding: 8px 6px 10px;
    text-align: center;
    background: rgba(0, 0, 0, 0.18);
}

.area-abilities .form-grid label {
    display: block;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    font-size: 0.62rem;
    color: var(--muted);
    margin-bottom: 4px;
}

.area-abilities .form-grid input {
    width: 74px;
    margin: 0 auto;
    text-align: center;
    font-size: 1.45rem;
    font-weight: 700;
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--border);
    border-radius: 0;
}

/* Combat: AC / Initiative / Speed as three shield boxes, HP beneath. */
.area-combat .form-grid {
    grid-template-columns: repeat(3, 1fr);
}

.area-combat .form-grid > div:nth-child(-n+3) {
    border: 2px solid var(--border);
    border-radius: 14px 14px 22px 22px;
    padding: 8px 4px 12px;
    text-align: center;
    background: rgba(0, 0, 0, 0.2);
}

.area-combat .form-grid > div:nth-child(-n+3) label {
    display: block;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    font-size: 0.6rem;
    color: var(--muted);
    margin-bottom: 4px;
}

.area-combat .form-grid > div:nth-child(-n+3) input {
    width: 64px;
    margin: 0 auto;
    text-align: center;
    font-size: 1.3rem;
    font-weight: 700;
    background: transparent;
    border: none;
}

.sheet-card,
.database-entry {
    border: 1px solid var(--border);
    border-radius: 18px;
    padding: 14px;
    margin: 0;
    background: rgba(22, 18, 43, 0.92);
    box-shadow: var(--shadow);
    min-width: 0;
}

.sheet-card > h2 {
    margin: -14px -14px 12px;
    padding: 10px 14px;
    border-bottom: 1px solid var(--border);
    border-radius: 18px 18px 0 0;
    background: rgba(0, 0, 0, 0.22);
    font-size: 1.02rem;
    font-family: var(--display-font);
    letter-spacing: 0.04em;
}

.multiclass-toggle-label {
    float: right;
    margin: -46px 0 0;
    padding: 6px 10px;
    border-radius: 10px;
    background: rgba(0,0,0,0.25);
}

.form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 10px;
}

.form-grid .full-row {
    grid-column: 1 / -1;
}

.ability-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(135px, 1fr));
    gap: 10px;
}

.ability {
    border: 1px solid rgba(123, 220, 255, 0.22);
    border-radius: 14px;
    padding: 10px;
    background: rgba(0,0,0,0.22);
    text-align: center;
}

.ability-mod {
    margin-top: 8px;
    color: var(--gold);
    font-size: 1.4rem;
    font-weight: 900;
}

.skills-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 8px;
}

.skill-row {
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr) 70px 54px;
    gap: 8px;
    align-items: center;
    padding: 8px;
    border: 1px solid rgba(123, 220, 255, 0.16);
    border-radius: 12px;
    background: rgba(0,0,0,0.18);
}

.library-search-block {
    position: relative;
}

.library-search-results {
    display: grid;
    gap: 6px;
    max-height: 260px;
    overflow: auto;
    margin: 8px 0;
}

.library-search-results button {
    display: grid;
    text-align: left;
    gap: 2px;
    border-radius: 12px;
    padding: 9px 10px;
}

.sheet-entry-list,
.database-entry-list {
    display: grid;
    gap: 8px;
}

.sheet-entry {
    border: 1px solid rgba(123, 220, 255, 0.22);
    border-radius: 14px;
    padding: 10px;
    background: rgba(0,0,0,0.2);
}

.sheet-entry summary,
.database-entry summary {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    cursor: pointer;
}

.database-form {
    display: grid;
    gap: 10px;
}

.sticky-save-row {
    position: sticky;
    bottom: 10px;
    display: flex;
    gap: 10px;
    justify-content: flex-end;
    padding: 10px;
    border: 1px solid var(--border);
    border-radius: 16px;
    background: rgba(12, 10, 29, 0.92);
    box-shadow: var(--shadow);
}


/* v0.9.6 town workflow, trade, wildshape images, spell slots, persistent measure */
.town-builder-modal {
    max-width: 1080px;
}

.town-builder-nav,
.town-builder-actions,
.shops-town-summary,
.tavern-game-row {
    display: flex;
    gap: 10px;
    align-items: center;
    flex-wrap: wrap;
    margin: 10px 0;
}

.town-store-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 10px;
}

.town-store-card,
.wildshape-card {
    text-align: left;
    display: grid;
    gap: 6px;
}

.store-editor {
    display: grid;
    gap: 12px;
}

.store-item-editor {
    display: grid;
    grid-template-columns: repeat(5, minmax(120px, 1fr));
    gap: 10px;
    border: 1px solid rgba(123, 220, 255, 0.22);
    border-radius: 16px;
    padding: 10px;
    margin: 10px 0;
    background: rgba(0,0,0,0.22);
}

.store-item-editor .full-row {
    grid-column: 1 / -1;
}

.shop-inventory-table,
.sell-box,
.sell-request-row {
    display: grid;
    gap: 8px;
    margin-top: 8px;
}

.shop-inventory-row,
.sell-inventory-row,
.sell-request-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto auto;
    gap: 8px;
    align-items: center;
    border: 1px solid rgba(123, 220, 255, 0.16);
    border-radius: 12px;
    padding: 8px;
    background: rgba(0,0,0,0.18);
}

.wildshape-toolbar {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 150px;
    gap: 10px;
    align-items: end;
}

.wildshape-toolbar-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 220px;
    gap: 10px;
    margin-bottom: 10px;
}

.wildshape-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
    gap: 10px;
    max-height: 430px;
    overflow: auto;
    padding: 8px 0;
}

.wildshape-card img,
.database-preview-image {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: 14px;
    border: 1px solid rgba(123, 220, 255, 0.25);
}

.wildshape-placeholder {
    width: 100%;
    aspect-ratio: 1 / 1;
    border-radius: 14px;
    background: rgba(0,0,0,0.35);
}

.charge-boxes,
.spell-slot-row > div {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    align-items: center;
}

.charge-box {
    display: inline-flex;
    gap: 6px;
    align-items: center;
    padding: 6px 8px;
    border: 1px solid rgba(123, 220, 255, 0.22);
    border-radius: 10px;
    background: rgba(0,0,0,0.2);
}

.spell-slot-boxes {
    display: grid;
    gap: 10px;
}

.spell-slot-row {
    display: grid;
    grid-template-columns: 90px minmax(0, 1fr);
    gap: 10px;
    align-items: center;
    padding: 8px;
    border: 1px solid rgba(123, 220, 255, 0.16);
    border-radius: 12px;
    background: rgba(0,0,0,0.18);
}

.measure-layer text {
    fill: #ffffff;
    stroke: #000000;
    stroke-width: 3px;
    paint-order: stroke fill;
    font-weight: 900;
    font-size: 18px;
    text-anchor: middle;
    pointer-events: none;
}

.measure-layer .measure-saved line,
.measure-layer .measure-temp line {
    stroke: #7bdcff;
    stroke-width: 4;
    stroke-dasharray: 10 8;
}

.measure-layer .measure-saved circle,
.measure-layer .measure-temp circle {
    fill: #ffbe4a;
    stroke: #071024;
    stroke-width: 2;
}

@media (max-width: 850px) {
    .store-item-editor,
    .shop-inventory-row,
    .sell-request-row {
        grid-template-columns: 1fr;
    }

    .wildshape-toolbar {
        grid-template-columns: 1fr;
    }
}


/* v0.9.7 shops/sheets/quests polish */
.carry-weight-display {
    min-height: 44px;
    display: flex;
    align-items: center;
    padding: 0 14px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: rgba(0,0,0,0.28);
    font-weight: 900;
    color: #7dffb3;
}

.carry-weight-display.overweight {
    color: #ff6b7f;
    border-color: rgba(255, 107, 127, 0.7);
}

.sheet-bubble-list,
.pretty-shop-grid,
.shop-stock-grid,
.quest-list-grid {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    align-items: stretch;
}

.sheet-entry-bubble {
    min-width: 135px;
    max-width: 220px;
    text-align: center;
    border-radius: 999px;
}

.sheet-entry-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: nowrap;
}

.inline-equip-toggle {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 0.78rem;
    color: var(--muted);
    white-space: nowrap;
    cursor: pointer;
    margin: 0;
}

.inline-equip-toggle input {
    width: auto;
    accent-color: var(--gold);
    cursor: pointer;
}

.equipped-badge {
    display: inline-block;
    margin: 2px 0 8px;
}

.item-detail-bits {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 8px 0;
}

.item-detail-bits span {
    border: 1px solid rgba(123, 220, 255, 0.22);
    border-radius: 999px;
    padding: 5px 9px;
    background: rgba(0,0,0,0.24);
}

.wildshape-picker-modal {
    max-width: 1280px;
}

.pretty-shop-card {
    min-width: 240px;
    min-height: 120px;
    justify-content: center;
    text-align: left;
    font-size: 1.05rem;
}

.shop-stock-card {
    width: min(270px, 100%);
    border: 1px solid rgba(123, 220, 255, 0.22);
    border-radius: 18px;
    padding: 14px;
    background: rgba(0,0,0,0.24);
}

.town-bound-card {
    display: grid;
    gap: 4px;
    border: 1px solid rgba(123, 220, 255, 0.22);
    border-radius: 14px;
    padding: 10px;
    background: rgba(0,0,0,0.24);
    margin: 10px 0;
}

.quest-objective.done {
    opacity: 0.55;
    text-decoration: line-through;
}

.quest-list-card {
    display: grid;
    gap: 4px;
    min-width: 240px;
    max-width: 320px;
    text-align: left;
}

.sell-request-panel {
    width: 100%;
}

#reverse-button {
    background: linear-gradient(180deg, #9bdcff, #5cb8e8);
}

@media (max-width: 700px) {
    .pretty-shop-grid,
    .shop-stock-grid,
    .quest-list-grid,
    .sheet-bubble-list {
        display: grid;
        grid-template-columns: 1fr;
    }
}


/* v0.9.8 store/wildshape fix pass */
.v098-store-editor {
    max-width: 1120px;
}

.store-editor-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    margin-top: 12px;
}

.store-item-card-list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 14px;
}

.store-item-editor-card {
    border: 1px solid rgba(123, 220, 255, 0.22);
    border-radius: 18px;
    padding: 14px;
    background: rgba(0, 0, 0, 0.24);
    display: flex;
    flex-direction: column;
    gap: 10px;
    transition: border-color .25s ease, box-shadow .25s ease;
}

.store-item-card-head {
    display: flex;
    align-items: center;
    gap: 8px;
}
.store-item-name-input {
    flex: 1;
    min-width: 0;
    font-weight: 700;
    font-size: 1rem;
}
.store-item-editor-card textarea {
    min-height: 54px;
    resize: vertical;
}
.store-item-card-fields {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px 10px;
}
.store-item-card-fields label {
    display: flex;
    flex-direction: column;
    gap: 3px;
    font-size: 0.72rem;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: .03em;
}
.store-item-card-fields input,
.store-item-card-fields select {
    font-size: 0.85rem;
}

/* Briefly highlights a newly added item card so it's obvious the click
   actually did something, instead of a new row silently appearing at the
   bottom of a long, easy-to-miss list. */
.store-item-card-new {
    border-color: var(--gold, #ffbd4d);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--gold, #ffbd4d) 45%, transparent);
    animation: store-item-flash 1.4s ease-out;
}
@keyframes store-item-flash {
    0% { background: color-mix(in srgb, var(--gold, #ffbd4d) 22%, rgba(0, 0, 0, 0.24)); }
    100% { background: rgba(0, 0, 0, 0.24); }
}

.store-save-status {
    font-size: 0.82rem;
    color: var(--muted);
    padding: 0 4px;
}
.store-save-status.unsaved {
    color: var(--gold, #ffbd4d);
    font-weight: 600;
}

.store-item-card-title {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    margin-bottom: 10px;
}

.small-danger {
    padding: 7px 12px;
}

.sticky-store-actions {
    position: sticky;
    bottom: 0;
    padding: 12px 0 0;
    background: linear-gradient(180deg, transparent, rgba(12, 10, 29, 0.98) 35%);
}

.v098-player-shop-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 330px));
    justify-content: center;
    gap: 18px;
    margin-top: 24px;
}

.v098-player-shop-card {
    min-height: 145px;
    padding: 24px;
    border-radius: 18px;
    background: linear-gradient(180deg, var(--panel2, rgba(31, 23, 57, 0.95)), var(--panel, rgba(22, 18, 43, 0.92)));
    color: var(--text, #fff5dd);
    border: 1px solid var(--border, rgba(255, 229, 138, 0.8));
}

.v098-player-shop-card strong {
    font-size: 1.2rem;
}

.v098-stock-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 310px));
    gap: 14px;
}

.direct-sell-panel {
    margin-top: 18px;
    border: 1px solid rgba(123, 220, 255, 0.22);
    border-radius: 18px;
    padding: 14px;
    background: rgba(0,0,0,0.24);
}

.direct-sell-row {
    display: grid;
    grid-template-columns: minmax(220px, 1fr) 160px auto;
    gap: 10px;
    align-items: end;
}

.wildshape-picker-modal {
    width: min(1700px, 96vw);
    max-width: 1700px;
    height: min(900px, 92vh);
}

.wildshape-picker-modal .wildshape-card-grid {
    max-height: calc(92vh - 190px);
}

.wildshape-stat-grid {
    margin: 8px 0 12px;
}

@media (max-width: 750px) {
    .direct-sell-row,
    .v098-player-shop-grid,
    .v098-stock-grid {
        grid-template-columns: 1fr;
    }
}


/* v0.9.9 old-flow town/store/quest fixes */
.v099-shop-summary {
    width: min(900px, 100%);
    margin: 0 auto 16px;
    justify-content: space-between;
}

.v099-shop-grid {
    display: grid !important;
    grid-template-columns: repeat(auto-fit, minmax(280px, 360px)) !important;
    justify-content: center !important;
    align-items: stretch !important;
    gap: 18px !important;
    width: min(900px, 100%);
    margin: 20px auto 0;
}

.v099-shop-card {
    min-height: 140px;
    display: grid;
    align-content: center;
    gap: 8px;
    text-align: left;
    padding: 24px;
    border-radius: 18px;
    /* Theme-driven: uses the active theme's panel + accent so Dungeon,
       Forest, Infernal etc. all restyle the town, not just Tavern. */
    background: linear-gradient(180deg, var(--panel2, rgba(31, 23, 57, 0.95)), var(--panel, rgba(22, 18, 43, 0.92)));
    color: var(--text, #fff5dd);
    border: 1px solid var(--border, rgba(255, 213, 116, 0.34));
    box-shadow: var(--shadow, 0 15px 38px rgba(0, 0, 0, 0.24));
    transition: border-color .15s, box-shadow .15s, transform .15s;
}

.v099-shop-card:hover {
    border-color: var(--gold, #ffd46e);
    box-shadow: 0 0 16px color-mix(in srgb, var(--accent, #ffd46e) 30%, transparent);
    transform: translateY(-2px);
}

.v099-shop-card strong {
    font-size: 1.35rem;
    color: var(--gold, #ffd46e);
}

.v099-shop-type {
    font-size: 0.95rem;
    font-weight: 900;
    opacity: 0.85;
    color: var(--accent, var(--gold, #ffd46e));
}

.v099-stock-grid {
    display: grid !important;
    grid-template-columns: repeat(auto-fit, minmax(240px, 320px));
    gap: 14px;
    justify-content: start;
}

.v099-stock-card {
    border: 1px solid var(--border, rgba(123, 220, 255, 0.22));
    border-radius: 18px;
    padding: 14px;
    background: var(--panel, rgba(0, 0, 0, 0.24));
}

.v099-store-editor,
.v099-quest-form {
    max-width: 1180px;
}

.store-editor-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    margin-top: 14px;
}

.store-item-card-title {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    align-items: center;
    margin-bottom: 10px;
}

.small-danger {
    padding: 7px 12px;
}

.sticky-store-actions {
    position: sticky;
    bottom: 0;
    padding: 12px 0 0;
    background: linear-gradient(180deg, transparent, rgba(12, 10, 29, 0.98) 35%);
}

.v099-town-store-grid,
.v099-quest-list {
    display: grid !important;
    grid-template-columns: repeat(auto-fit, minmax(220px, 280px));
    gap: 12px;
    justify-content: start;
}

.direct-sell-row {
    display: grid;
    grid-template-columns: minmax(220px, 1fr) 150px auto;
    gap: 10px;
}

.quest-objective.done {
    opacity: 0.55;
    text-decoration: line-through;
}

@media (max-width: 760px) {
    .v099-shop-grid,
    .v099-stock-grid,
    .v099-town-store-grid,
    .v099-quest-list,
    .direct-sell-row {
        grid-template-columns: 1fr !important;
    }
}


/* v0.9.10 standalone Towns manager */
.towns-page-grid {
    display: grid;
    grid-template-columns: minmax(250px, 330px) minmax(0, 1fr);
    gap: 18px;
    align-items: start;
}

.towns-sidebar {
    position: sticky;
    top: 92px;
}

.town-list,
.store-tabs,
.attached-map-list,
.store-item-list {
    display: grid;
    gap: 10px;
}

.town-list-item,
.store-tab,
.attached-map-row,
.store-item-card,
.town-bound-card {
    border: 1px solid rgba(123, 220, 255, 0.22);
    border-radius: 16px;
    padding: 12px;
    background: rgba(0, 0, 0, 0.22);
}

.town-list-item,
.store-tab {
    display: grid;
    gap: 4px;
    color: inherit;
    text-decoration: none;
}

.town-list-item.active,
.store-tab.active {
    border-color: rgba(255, 229, 138, 0.75);
    box-shadow: 0 0 0 2px rgba(255, 190, 74, 0.15);
}

.town-edit-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(160px, 220px) auto;
    gap: 12px;
    align-items: end;
}

.town-edit-row > div:first-of-type:last-of-type {
    grid-column: span 2;
}

.attached-map-row {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    align-items: center;
}

.store-tabs {
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    margin-top: 14px;
}

.store-item-form {
    display: grid;
    grid-template-columns: repeat(6, minmax(120px, 1fr));
    gap: 10px;
    align-items: end;
}

.store-item-form .full-row {
    grid-column: 1 / -1;
}

.store-item-card {
    display: grid;
    gap: 12px;
}

.store-item-card-top {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    align-items: center;
}

.inline-card-form {
    grid-template-columns: repeat(6, minmax(100px, 1fr));
}

.store-item-actions,
.store-item-delete-form {
    display: flex;
    gap: 10px;
    justify-content: flex-end;
}

.danger-zone {
    margin-top: 12px;
    border: 1px solid rgba(255, 107, 127, 0.25);
    border-radius: 14px;
    padding: 10px;
}

@media (max-width: 950px) {
    .towns-page-grid {
        grid-template-columns: 1fr;
    }

    .towns-sidebar {
        position: static;
    }

    .town-edit-row,
    .store-item-form,
    .inline-card-form {
        grid-template-columns: 1fr;
    }
}


/* v0.9.11 stable quests/dice/shop/category fixes */
.map-selector-modal:has(#shops-modal-content) {
    max-width: 1500px;
    width: min(1500px, 96vw);
}

#shops-modal-content,
.v099-shop-grid,
.v099-stock-grid {
    width: 100%;
}

.v099-shop-grid {
    grid-template-columns: repeat(auto-fit, minmax(280px, 360px)) !important;
    justify-content: center !important;
}

.v099-stock-grid {
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)) !important;
}

.database-picker-box {
    margin: 12px 0 18px;
}

.compact-store-item-card {
    padding: 12px;
}

.compact-item-form {
    grid-template-columns: repeat(4, minmax(120px, 1fr));
}

.quests-page-grid {
    display: grid;
    grid-template-columns: minmax(260px, 340px) minmax(0, 1fr);
    gap: 18px;
    align-items: start;
}

.quest-sidebar {
    position: sticky;
    top: 92px;
}

.quest-list-panel {
    display: grid;
    gap: 10px;
    margin-top: 12px;
}

.quest-list-row {
    display: grid;
    gap: 4px;
    color: inherit;
    text-decoration: none;
    border: 1px solid rgba(123, 220, 255, 0.22);
    border-radius: 16px;
    padding: 12px;
    background: rgba(0,0,0,0.22);
}

.quest-list-row.active {
    border-color: rgba(255, 229, 138, 0.75);
}

.quest-action-row {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
}

.dice-button-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 14px;
}

.dice-button-grid button {
    min-height: 86px;
    font-size: 1.3rem;
}

.dice-result-box {
    margin-top: 18px;
    border: 1px solid rgba(123, 220, 255, 0.22);
    border-radius: 18px;
    padding: 22px;
    font-size: 2rem;
    font-weight: 900;
    text-align: center;
    background: rgba(0,0,0,0.24);
}

.wildshape-photo-tools {
    display: grid;
    grid-template-columns: 150px minmax(0, 1fr);
    gap: 12px;
    align-items: center;
    margin: 12px 0;
}

.wildshape-photo-preview {
    width: 138px;
    height: 138px;
    border: 1px solid rgba(123, 220, 255, 0.25);
    border-radius: 18px;
    display: grid;
    place-items: center;
    overflow: hidden;
    background: rgba(0,0,0,0.24);
}

.wildshape-photo-preview img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.item-equip-toggle {
    margin: 8px 0;
}

.wall-line,
.door-line {
    pointer-events: stroke;
}

@media (max-width: 950px) {
    .quests-page-grid,
    .wildshape-photo-tools {
        grid-template-columns: 1fr;
    }
    .quest-sidebar { position: static; }
    .compact-item-form { grid-template-columns: 1fr; }
}


/* ---------- v0.9.21: combat select flow, dice rolls, folded popover, explorer ---------- */

.combat-pick-badge {
    position: absolute;
    top: -12px;
    right: -12px;
    width: 22px;
    height: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: #2f9e44;
    color: #fff;
    font-size: 0.85rem;
    box-shadow: 0 2px 6px rgba(0,0,0,0.6);
    z-index: 4;
}

.combat-selectable {
    cursor: pointer;
    outline: 2px dashed rgba(255, 217, 143, 0.5);
    outline-offset: 3px;
}

.active-turn {
    z-index: 3;
}

.active-turn::after {
    content: "";
    position: absolute;
    inset: -8px;
    border-radius: 50%;
    border: 3px solid #ffd98f;
    box-shadow: 0 0 14px 4px rgba(255, 217, 143, 0.65);
    animation: active-turn-pulse 1.6s ease-in-out infinite;
    pointer-events: none;
}

@keyframes active-turn-pulse {
    0%, 100% { transform: scale(1); opacity: 0.9; }
    50% { transform: scale(1.07); opacity: 0.55; }
}

.dice-roll-anim {
    position: absolute;
    left: 50%;
    top: -46px;
    transform: translateX(-50%);
    min-width: 34px;
    padding: 5px 8px;
    border-radius: 9px;
    background: rgba(20, 14, 8, 0.92);
    border: 2px solid #ffd98f;
    color: #ffd98f;
    font-weight: 700;
    font-size: 1.05rem;
    text-align: center;
    z-index: 6;
    animation: dice-wobble 0.09s linear infinite;
    pointer-events: none;
}

.dice-roll-anim.settled {
    animation: dice-land 0.25s ease-out;
    background: #2f9e44;
    border-color: #d3f9d8;
    color: #fff;
}

@keyframes dice-wobble {
    0% { transform: translateX(-50%) rotate(-7deg); }
    50% { transform: translateX(-50%) rotate(7deg); }
    100% { transform: translateX(-50%) rotate(-7deg); }
}

@keyframes dice-land {
    0% { transform: translateX(-50%) scale(1.6); }
    100% { transform: translateX(-50%) scale(1); }
}

.popover-section {
    border: 1px solid var(--border);
    border-radius: 10px;
    margin: 6px 0;
    padding: 0 8px;
    background: rgba(0,0,0,0.14);
}

.popover-section > summary {
    cursor: pointer;
    padding: 7px 2px;
    font-weight: 600;
    color: var(--muted);
}

.popover-section[open] {
    padding-bottom: 8px;
}

.map-context-menu {
    position: absolute;
    z-index: 260;
    display: grid;
    gap: 4px;
    min-width: 190px;
    max-height: 320px;
    overflow: auto;
    padding: 10px;
    border-radius: 12px;
    border: 1px solid var(--border);
    background: rgba(22, 18, 43, 0.98);
    box-shadow: 0 14px 34px rgba(0,0,0,0.6);
}

.map-context-menu button {
    text-align: left;
}

.selector-tile.drop-target {
    outline: 3px dashed #ffd98f;
    outline-offset: -3px;
}

.weather-settings-modal {
    display: grid;
    gap: 8px;
}

/* ---------- v0.9.22: token palette, thumbnails, emoji faces ---------- */

.token-emoji {
    font-size: 1.5em;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
}

.standard-token-palette {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
    gap: 8px;
}

.standard-token-chip {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 8px 4px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: rgba(0, 0, 0, 0.2);
    cursor: grab;
    text-align: center;
}

.standard-token-chip:hover {
    border-color: #ffd98f;
    background: rgba(255, 217, 143, 0.08);
}

.standard-token-chip:active {
    cursor: grabbing;
}

.standard-token-glyph {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.4rem;
    box-shadow: inset 0 0 0 2px rgba(0,0,0,0.25), 0 2px 4px rgba(0,0,0,0.4);
}

.standard-token-name {
    font-size: 0.68rem;
    color: var(--muted);
    line-height: 1.1;
}

/* --- Bestiary picker (Enemies tab) --- */
/* The palette these get inserted into (#standard-token-palette) is itself
   a 2-column CSS grid for the token chips. Without this, every top-level
   element in a block below (heading, blurb, search box, hr) becomes its
   own grid cell instead of stacking normally - which is exactly the bug
   this rule fixes: span the full row so the section lays out as an
   ordinary block internally, with only the chip grid inside it forming
   actual grid cells. */
.token-source-divider {
    grid-column: 1 / -1;
    margin: 14px 0 10px;
    border: none;
    border-top: 1px solid var(--border);
}
.token-palette-section {
    grid-column: 1 / -1;
}
.bestiary-heading {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 4px;
    font-size: 0.92rem;
}
.bestiary-search-row {
    margin: 8px 0 10px;
}
.bestiary-search-row input {
    width: 100%;
}
.bestiary-grid {
    display: grid;
    /* Match the Standard-tokens grid above so bestiary chips sit two-across
       in the narrow side panel instead of stacking into one tall column. */
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
    gap: 8px;
    max-height: 360px;
    overflow-y: auto;
    padding-right: 2px;
}
.bestiary-chip .standard-token-glyph {
    color: #fff;
}

/* --- Bestiary Level selector (token popover) --- */
.bestiary-level-editor {
    margin: 4px 0 10px;
    padding: 10px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: rgba(123, 220, 255, 0.05);
}
.bestiary-level-editor > label {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 8px;
    font-weight: 700;
}
.bestiary-level-editor .inline-form {
    margin-top: 6px;
}
#tok-bestiary-level {
    width: 70px;
}
.bestiary-statblock-ref {
    margin-top: 8px;
    padding: 6px 8px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: rgba(0, 0, 0, 0.18);
}
.bestiary-statblock-ref summary {
    cursor: pointer;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--muted);
}
.bestiary-statblock-body {
    margin-top: 8px;
    font-size: 0.8rem;
    line-height: 1.45;
}
.bestiary-statblock-body p {
    margin: 0 0 6px;
}

.token-row-thumb {
    width: 34px;
    height: 34px;
    min-width: 34px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.1rem;
    font-weight: 700;
    overflow: hidden;
    box-shadow: inset 0 0 0 2px rgba(0,0,0,0.25);
    cursor: grab;
}

.token-row-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.token-row-thumb[draggable="true"]:active {
    cursor: grabbing;
}

.token-row-top {
    display: flex;
    align-items: center;
    gap: 8px;
}

.token-row-actions {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}

/* ---------- v0.9.23: docked token library tray (bottom-left of the editor map) ---------- */

.token-library-tray {
    position: absolute;
    left: 12px;
    bottom: 12px;
    z-index: 40;
    width: 232px;
    max-height: 46%;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--border);
    border-radius: 14px;
    background: rgba(18, 14, 32, 0.94);
    box-shadow: 0 12px 30px rgba(0,0,0,0.55);
    backdrop-filter: blur(3px);
    overflow: hidden;
}

.token-library-tray-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 12px;
    border-bottom: 1px solid var(--border);
    background: rgba(0, 0, 0, 0.25);
    font-size: 0.9rem;
}

.token-library-tray-head strong {
    font-family: var(--display-font, inherit);
    letter-spacing: 0.03em;
}

#token-library-collapse {
    width: 26px;
    height: 26px;
    border-radius: 8px;
    border: 1px solid var(--border);
    background: rgba(0,0,0,0.3);
    color: var(--text, #eee);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
}

.token-library-tray.collapsed .token-library-items {
    display: none;
}

.token-library-items {
    padding: 8px;
    overflow-y: auto;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
    gap: 8px;
    align-content: start;
}

.token-library-item {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    padding: 6px 3px 4px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: rgba(0,0,0,0.2);
    cursor: grab;
    text-align: center;
}

.token-library-item:hover {
    border-color: #ffd98f;
    background: rgba(255, 217, 143, 0.08);
}

.token-library-item:active {
    cursor: grabbing;
}

.token-library-thumb {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    font-size: 1.05rem;
    font-weight: 700;
    box-shadow: inset 0 0 0 2px rgba(0,0,0,0.28), 0 2px 4px rgba(0,0,0,0.4);
}

.token-library-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.token-library-name {
    font-size: 0.64rem;
    color: var(--muted);
    line-height: 1.05;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.token-library-remove {
    position: absolute;
    top: -6px;
    right: -6px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: 1px solid var(--border);
    background: #c92a2a;
    color: #fff;
    font-size: 0.85rem;
    line-height: 1;
    cursor: pointer;
    display: none;
}

.token-library-item:hover .token-library-remove {
    display: block;
}

.token-library-empty {
    grid-column: 1 / -1;
    margin: 4px 2px;
}

/* ---------- v0.9.26: map pings ("look here") ---------- */

.map-ping {
    position: absolute;
    transform: translate(-50%, -50%);
    pointer-events: none;
    z-index: 55;
    --ping-color: #7bd0ff;    /* a player ping */
}
.map-ping.map-ping-dm { --ping-color: #ffd46e; }        /* DM plain ping */
.map-ping.map-ping-camera { --ping-color: #ff7b9c; }    /* DM camera ping */

.map-ping-rings {
    position: absolute;
    left: 0; top: 0;
    transform: translate(-50%, -50%);
    width: 0; height: 0;
}
.map-ping-rings i {
    position: absolute;
    left: 0; top: 0;
    transform: translate(-50%, -50%);
    width: 22px; height: 22px;
    border-radius: 50%;
    border: 3px solid var(--ping-color);
    opacity: 0;
    animation: ping-ring 2s ease-out forwards;
}
.map-ping-rings i:nth-child(2) { animation-delay: 0.28s; }
.map-ping-rings i:nth-child(3) { animation-delay: 0.56s; }
.map-ping.map-ping-camera .map-ping-rings i {
    border-width: 4px;
    animation-duration: 2.6s;
}

@keyframes ping-ring {
    0%   { width: 14px; height: 14px; opacity: 0.95; }
    70%  { opacity: 0.5; }
    100% { width: 120px; height: 120px; opacity: 0; }
}

.map-ping::after {
    /* solid center dot */
    content: "";
    position: absolute;
    left: 0; top: 0;
    transform: translate(-50%, -50%);
    width: 12px; height: 12px;
    border-radius: 50%;
    background: var(--ping-color);
    box-shadow: 0 0 10px 2px var(--ping-color);
    animation: ping-dot 2s ease-out forwards;
}
@keyframes ping-dot {
    0% { transform: translate(-50%,-50%) scale(0.4); opacity: 1; }
    30% { transform: translate(-50%,-50%) scale(1.15); }
    100% { transform: translate(-50%,-50%) scale(1); opacity: 0; }
}

.map-ping-label {
    position: absolute;
    left: 0; top: 14px;
    transform: translateX(-50%);
    white-space: nowrap;
    font-size: 0.72rem;
    font-weight: 700;
    color: #fff;
    background: var(--ping-color);
    padding: 1px 7px;
    border-radius: 8px;
    box-shadow: 0 2px 6px rgba(0,0,0,0.5);
    opacity: 0;
    animation: ping-label 2s ease-out forwards;
}
@keyframes ping-label {
    0%, 10% { opacity: 0; transform: translateX(-50%) translateY(4px); }
    20% { opacity: 1; transform: translateX(-50%) translateY(0); }
    80% { opacity: 1; }
    100% { opacity: 0; }
}

/* v0.9.28: archer range menu slider */
.archer-range-slider-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 6px;
}
.archer-range-slider-row input[type="range"] { flex: 1; }
.archer-range-slider-row .hint { min-width: 46px; text-align: right; }

/* v0.9.28: standard vs uploaded token source switch */
.token-source-switch {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 8px;
}
.token-source-btn {
    padding: 5px 12px;
    background: transparent;
    color: var(--muted);
    border: 1px solid var(--border);
    border-radius: 8px;
    cursor: pointer;
    font-size: 0.82rem;
    white-space: nowrap;
}
.token-source-btn.active {
    background: var(--accent);
    color: #1a1204;
    font-weight: 700;
}
.token-source-upload {
    padding: 5px 12px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: #2f6a3a;
    color: #f3f7ec;
    cursor: pointer;
    font-size: 0.82rem;
    font-weight: 700;
    white-space: nowrap;
}
.token-source-upload:hover,
.token-source-upload:focus-visible {
    background: #3b8248;
}
.standard-token-glyph img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }

/* v0.9.28: tripwire lines + trap-halt */
.tripwire-line {
    stroke: #d64550;
    stroke-width: 3;
    stroke-dasharray: 2 7;
    stroke-linecap: round;
    opacity: 0.9;
    pointer-events: none;
}
.tripwire-line.tripwire-hidden {
    stroke: #7a5cff;
    opacity: 0.55;
    stroke-dasharray: 4 6;
}
.token.tripwire-picking {
    outline: 3px dashed #d64550;
    outline-offset: 2px;
    border-radius: 50%;
}
.token.trap-halted {
    animation: trap-halt-flash 0.8s ease-in-out 3;
}
@keyframes trap-halt-flash {
    0%, 100% { filter: none; }
    50% { filter: drop-shadow(0 0 8px #ff3b3b) drop-shadow(0 0 14px #ff3b3b); }
}

/* v0.9.31: world map clickable places */
.world-spot-layer {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 6;
}
.world-spot {
    position: absolute;
    pointer-events: auto;
    cursor: pointer;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}
.world-spot-text .world-spot-label {
    background: rgba(20, 14, 6, 0.82);
    color: #ffe0a3;
    border: 1px solid #b8873c;
    border-radius: 8px;
    padding: 4px 10px;
    font-family: "Cinzel", Georgia, serif;
    font-weight: 700;
    white-space: nowrap;
    box-shadow: 0 2px 8px rgba(0,0,0,0.4);
}
.world-spot-circle {
    transform: none;
    border: 3px dashed #ffcf6b;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(255,207,107,0.12), rgba(255,207,107,0.03) 70%, transparent);
    justify-content: center;
}
.world-spot-circle .world-spot-label {
    color: #ffe0a3;
    font-family: "Cinzel", Georgia, serif;
    font-weight: 700;
    text-shadow: 0 1px 3px #000;
}
.world-spot.picked .world-spot-label,
.world-spot.picked.world-spot-circle {
    border-color: #7bd88f;
    box-shadow: 0 0 12px rgba(123,216,143,0.7);
}
.world-spot-votes {
    background: #2f9e44;
    color: #fff;
    border-radius: 10px;
    padding: 0 7px;
    font-size: 0.72rem;
    font-weight: 700;
}
.world-spot-link {
    font-size: 0.66rem;
    color: #cdb891;
    background: rgba(0,0,0,0.55);
    padding: 0 5px;
    border-radius: 5px;
}
.world-spot-row {
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 8px;
    margin-bottom: 8px;
    display: flex;
    flex-direction: column;
    gap: 5px;
}
.world-spot-row-actions {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* v0.9.32: tab attention badges (new handout / trade request) */
.tab-attention {
    display: inline-block;
    margin-left: 6px;
    background: #d64550;
    color: #fff;
    font-size: 0.6rem;
    font-weight: 800;
    letter-spacing: 0.05em;
    padding: 1px 6px;
    border-radius: 8px;
    vertical-align: middle;
    animation: tab-attention-pulse 1.4s ease-in-out infinite;
}
@keyframes tab-attention-pulse {
    0%, 100% { opacity: 1; box-shadow: 0 0 0 rgba(214,69,80,0.0); }
    50% { opacity: 0.75; box-shadow: 0 0 8px rgba(214,69,80,0.8); }
}

/* v0.9.32: dynamic torch light - soft, colored, flickering, WALL-BLOCKED glow */
.light-glow-layer {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 3;
    mix-blend-mode: screen;
}
.light-glow-svg {
    position: absolute;
    left: 0;
    top: 0;
    overflow: visible;
}
.light-glow-rect {
    /* Flicker animation removed: the infinite scale/opacity keyframes forced
       constant GPU repaints and made the board lag badly on low-power devices
       (e.g. a Raspberry Pi client). The light still renders, just without the
       animated flicker. Re-enable by restoring the animation line below. */
    /* animation: torch-flicker 3.2s ease-in-out infinite alternate; */
    opacity: 0.9;
}
@keyframes torch-flicker {
    0%   { opacity: 0.78; transform: scale(0.985); }
    18%  { opacity: 0.95; transform: scale(1.015); }
    37%  { opacity: 0.7;  transform: scale(0.975); }
    55%  { opacity: 0.92; transform: scale(1.008); }
    72%  { opacity: 0.76; transform: scale(0.992); }
    100% { opacity: 0.9;  transform: scale(1.01); }
}

/* ===== v0.9.34: condition auras + animated per-condition effects ===== */
.token-fx {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: visible;
    z-index: 1;
}
/* Aura: a soft coloured glow pulsing behind the token */
.cfx-aura {
    position: absolute;
    inset: -18%;
    border-radius: 50%;
    background: radial-gradient(circle, color-mix(in srgb, var(--aura) 55%, transparent) 0%, transparent 70%);
    animation: cfx-aura-pulse 2.4s ease-in-out infinite;
    z-index: 0;
}
@supports not (background: color-mix(in srgb, red 50%, white)) {
    .cfx-aura { background: radial-gradient(circle, var(--aura) 0%, transparent 70%); opacity: 0.5; }
}
@keyframes cfx-aura-pulse {
    0%, 100% { opacity: 0.45; transform: scale(0.96); }
    50%      { opacity: 0.75; transform: scale(1.04); }
}

/* placement helpers */
.cfx { position: absolute; }
.cfx-base { left: 0; right: 0; bottom: -6%; height: 60%; }
.cfx-surround { inset: -12%; }
.cfx-overlay { inset: 0; border-radius: 50%; overflow: hidden; }

/* --- poison bubbles --- */
.cfx-bubble {
    position: absolute; bottom: 0;
    border-radius: 50%;
    background: radial-gradient(circle at 35% 30%, rgba(180,255,150,0.95), rgba(60,160,40,0.6));
    box-shadow: 0 0 4px rgba(80,200,60,0.7);
    animation: cfx-bubble-rise 2s ease-in infinite;
    opacity: 0;
}
@keyframes cfx-bubble-rise {
    0%   { transform: translateY(0) scale(0.6); opacity: 0; }
    20%  { opacity: 0.9; }
    100% { transform: translateY(-140%) scale(1.1); opacity: 0; }
}

/* --- charmed hearts --- */
.cfx-heart {
    position: absolute; bottom: 0; width: 8px; height: 8px;
    background: #ff6fae;
    transform: rotate(45deg);
    animation: cfx-heart-float 2.2s ease-in infinite;
    opacity: 0;
}
.cfx-heart::before, .cfx-heart::after {
    content: ""; position: absolute; width: 8px; height: 8px; background: #ff6fae; border-radius: 50%;
}
.cfx-heart::before { top: -4px; left: 0; }
.cfx-heart::after { left: -4px; top: 0; }
@keyframes cfx-heart-float {
    0%   { transform: translateY(0) rotate(45deg) scale(0.5); opacity: 0; }
    25%  { opacity: 0.95; }
    100% { transform: translateY(-150%) rotate(45deg) scale(1); opacity: 0; }
}

/* --- zzz (sleep / exhaustion / unconscious) --- */
.cfx-zzz {
    position: absolute; bottom: 20%;
    color: #cfe0ff; font-weight: 800; font-family: Georgia, serif;
    text-shadow: 0 1px 2px #000;
    animation: cfx-zzz-drift 2.6s ease-out infinite;
    opacity: 0;
}
.cfx-zzz::before { content: "z"; }
@keyframes cfx-zzz-drift {
    0%   { transform: translate(0,0) rotate(0); opacity: 0; }
    25%  { opacity: 0.9; }
    100% { transform: translate(60%,-160%) rotate(18deg); opacity: 0; }
}

/* --- orbiting stars (stunned / incapacitated) --- */
.cfx-orbit { animation: cfx-spin 1.6s linear infinite; }
.cfx-orbit.cfx-slow { animation-duration: 3.2s; }
.cfx-star {
    position: absolute; top: 50%; left: 50%; width: 10px; height: 10px; margin: -5px 0 0 -5px;
    transform: rotate(var(--a)) translateX(60%);
    color: #ffd23a; font-size: 11px; line-height: 10px; text-align: center;
    animation: cfx-star-twinkle 0.9s ease-in-out infinite alternate;
}
.cfx-star::before { content: "\2726"; }
@keyframes cfx-spin { to { transform: rotate(360deg); } }
@keyframes cfx-star-twinkle { from { opacity: 0.5; } to { opacity: 1; } }

/* --- paralysis sparks --- */
.cfx-spark {
    position: absolute; top: 50%; left: 50%; width: 2px; height: 30%;
    background: linear-gradient(180deg, rgba(255,240,120,0), rgba(255,240,120,0.95));
    transform-origin: top center;
    transform: rotate(var(--a));
    animation: cfx-spark-flick 0.4s steps(2) infinite;
    opacity: 0;
}
@keyframes cfx-spark-flick { 0%,100% { opacity: 0; } 50% { opacity: 1; } }

/* --- restrained web --- */
.cfx-web {
    border-radius: 50%;
    background:
        repeating-conic-gradient(from 0deg, rgba(230,230,240,0.5) 0deg 2deg, transparent 2deg 30deg),
        radial-gradient(circle, transparent 40%, rgba(230,230,240,0.35) 41%, transparent 45%, rgba(230,230,240,0.3) 60%, transparent 63%);
    opacity: 0.7;
}

/* --- grappled grip ring --- */
.cfx-grip {
    border-radius: 50%;
    border: 3px dashed rgba(220,170,110,0.9);
    animation: cfx-grip-clamp 1.8s ease-in-out infinite;
}
@keyframes cfx-grip-clamp {
    0%,100% { transform: scale(1.05); opacity: 0.6; }
    50%     { transform: scale(0.92); opacity: 1; }
}

/* --- frightened: the token shakes + sweat drops fling off --- */
.token.token-frightened .token-face { animation: cfx-shiver 0.16s linear infinite; }
@keyframes cfx-shiver {
    0% { transform: translate(0,0); } 25% { transform: translate(-1.5px,1px); }
    50% { transform: translate(1.5px,-1px); } 75% { transform: translate(-1px,-1.5px); }
    100% { transform: translate(1px,1.5px); }
}
.cfx-sweat {
    position: absolute; top: 18%; left: 50%; width: 6px; height: 8px;
    margin-left: -3px;
    background: radial-gradient(circle at 40% 30%, #cfefff, #4aa6d6);
    border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
    transform: rotate(var(--a)) translateY(0);
    animation: cfx-sweat-fly 1s ease-in infinite;
    opacity: 0;
}
@keyframes cfx-sweat-fly {
    0% { transform: rotate(var(--a)) translateY(0) scale(0.6); opacity: 0; }
    30% { opacity: 0.9; }
    100% { transform: rotate(var(--a)) translateY(-140%) scale(1); opacity: 0; }
}

/* --- petrified stone --- */
.cfx-stone {
    background:
        linear-gradient(135deg, rgba(120,120,120,0.55), rgba(90,90,90,0.55)),
        radial-gradient(circle at 60% 40%, transparent 60%, rgba(40,40,40,0.5) 100%);
    mix-blend-mode: luminosity;
}
.cfx-stone::after {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(60deg, transparent 44%, rgba(30,30,30,0.6) 45%, transparent 47%),
                linear-gradient(120deg, transparent 60%, rgba(30,30,30,0.5) 61%, transparent 63%);
}

/* --- prone dust --- */
.cfx-dust {
    position: absolute; bottom: 0; width: 7px; height: 7px; border-radius: 50%;
    background: rgba(190,160,120,0.7);
    animation: cfx-dust-puff 1.6s ease-out infinite; opacity: 0;
}
@keyframes cfx-dust-puff {
    0% { transform: translate(0,0) scale(0.4); opacity: 0; }
    30% { opacity: 0.7; }
    100% { transform: translate(var(--dx,10px),-40%) scale(1.3); opacity: 0; }
}

/* --- blinded band --- */
.cfx-blind {
    background: linear-gradient(180deg, transparent 30%, rgba(10,10,15,0.85) 40%, rgba(10,10,15,0.85) 55%, transparent 65%);
}

/* --- deafened mute rings --- */
.cfx-mute {
    position: absolute; top: 50%; left: 50%; width: 40%; height: 40%; margin: -20% 0 0 -20%;
    border: 2px solid rgba(150,165,180,0.8); border-radius: 50%;
    animation: cfx-mute-ring 1.8s ease-out infinite; opacity: 0;
}
@keyframes cfx-mute-ring {
    0% { transform: scale(0.4); opacity: 0.8; }
    100% { transform: scale(1.8); opacity: 0; }
}

/* --- invisible shimmer --- */
.cfx-invis {
    border-radius: 50%;
    background: linear-gradient(120deg, transparent 30%, rgba(190,230,255,0.35) 50%, transparent 70%);
    animation: cfx-invis-shimmer 2.4s linear infinite;
}
@keyframes cfx-invis-shimmer {
    0% { transform: translateX(-60%); opacity: 0.2; }
    50% { opacity: 0.6; }
    100% { transform: translateX(60%); opacity: 0.2; }
}

/* v0.9.35: recurring condition damage - popover rows + floating numbers */
.condition-damage-block { margin-top: 8px; }
.condition-damage-row {
    display: flex; align-items: center; gap: 6px; margin: 4px 0; font-size: 0.85rem;
}
.condition-damage-row .cd-label { min-width: 96px; }
.condition-damage-row .cd-dice { width: 64px; }
.condition-damage-row .cd-every { width: 48px; }
.condition-damage-row .cd-every-label { color: #b9a888; font-size: 0.78rem; }

.token-damage-popups {
    position: absolute; left: 50%; top: -6px; transform: translateX(-50%);
    pointer-events: none; z-index: 20; white-space: nowrap;
}
.dmg-float {
    display: inline-block;
    font-weight: 900; font-size: 20px;
    text-shadow: 0 2px 4px #000, 0 0 8px rgba(0,0,0,0.6);
    animation: dmg-float-up 2.2s ease-out forwards;
    opacity: 0;
}
@keyframes dmg-float-up {
    0%   { transform: translateY(6px) scale(0.6); opacity: 0; }
    15%  { transform: translateY(0) scale(1.15); opacity: 1; }
    35%  { transform: translateY(-8px) scale(1); opacity: 1; }
    100% { transform: translateY(-42px) scale(0.95); opacity: 0; }
}

/* v0.9.36: character-sheet defenses + condition damage type */
.defenses-grid { display: grid; grid-template-columns: 1fr; gap: 4px; }
.defenses-grid input { width: 100%; }
.condition-damage-row .cd-type { width: 72px; }

/* v0.9.37: DM status-effect palette */
.status-effects-panel .status-chip-tray {
    display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0;
}
.status-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 8px; border-radius: 14px; cursor: grab;
    background: color-mix(in srgb, var(--chip, #c0673a) 30%, #1a130c);
    border: 1px solid var(--chip, #c0673a);
    font-size: 0.82rem; user-select: none;
}
.status-chip:active { cursor: grabbing; }
.status-chip-icon { font-size: 1rem; }
.status-chip-name { font-weight: 700; }
.status-chip-meta { font-size: 0.7rem; color: #d8c4a4; }
.status-chip-del {
    background: transparent; border: none; color: #e8b7b0; cursor: pointer;
    font-size: 1rem; line-height: 1; padding: 0 2px;
}
.status-add-form { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.status-add-form input, .status-add-form select { width: 100%; }
.status-add-row { display: flex; align-items: center; gap: 6px; }
.status-add-row input[type="color"] { width: 42px; flex: none; padding: 0; }
.token.status-drop-target {
    outline: 3px dashed #ffcf6b;
    outline-offset: 2px;
    filter: brightness(1.2);
}

/* v0.9.38: push-map button + player/prep view indicator */
.push-map-button.push-ready {
    background: #2f9e44;
    border-color: #37b355;
    animation: push-ready-pulse 1.6s ease-in-out infinite;
}
@keyframes push-ready-pulse {
    0%,100% { box-shadow: 0 0 0 rgba(55,179,85,0); }
    50%     { box-shadow: 0 0 10px rgba(55,179,85,0.8); }
}
.map-view-indicator {
    display: inline-flex; flex-direction: column; gap: 1px;
    margin-left: 10px; font-size: 0.72rem; line-height: 1.2;
    vertical-align: middle;
}
.map-view-indicator .mvi-players b { color: #ffcf6b; }
.map-view-indicator .mvi-prep b { color: #7bd88f; }
.map-view-indicator .mvi-synced { color: #9fce9f; }

/* v0.9.38 fix: keep the editor/board toolbar within its column.
   The long hint paragraph was acting as a flex item with a big min-content
   width, forcing the whole toolbar wider than the board and clipping both
   edges. Make the hint (and any full-width children) break to their own row,
   and hard-cap the toolbar so it can never exceed its column. */
.board-toolbar {
    min-width: 0;
    max-width: 100%;
    overflow-x: hidden;
}
.board-toolbar > .hint {
    flex: 1 0 100%;
    width: 100%;
    margin: 2px 0 0 0;
}
.board-toolbar > .calendar-strip {
    flex: 1 0 100%;
    width: 100%;
}
.board-toolbar button,
.board-toolbar .button {
    flex: 0 0 auto;      /* size to their label, then wrap - don't stretch */
    white-space: nowrap;
}

/* v0.9.39: settings dropdown, upload popup, tray dismiss, mark-as-player */
.settings-dropdown { position: relative; display: inline-block; }
.settings-toggle { white-space: nowrap; }
.settings-menu {
    position: fixed;               /* escape the toolbar's overflow-x:hidden clip */
    z-index: 200;
    background: #1c140c; border: 1px solid #b9873f; border-radius: 8px;
    padding: 6px; min-width: 180px; display: flex; flex-direction: column; gap: 4px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.6);
}
.settings-menu .settings-item { width: 100%; text-align: left; }
.settings-menu[hidden] { display: none; }

.upload-token-popup {
    position: fixed; inset: 0; z-index: 300;
    background: rgba(0,0,0,0.6); display: flex; align-items: center; justify-content: center;
}
.upload-token-popup[hidden] { display: none; }
.upload-token-popup-inner {
    background: #17110b; border: 1px solid #b9873f; border-radius: 12px;
    padding: 18px; width: min(440px, 92vw); max-height: 88vh; overflow-y: auto;
}
.upload-token-popup-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.upload-token-popup-head button { background: transparent; border: none; color: #e8c9a0; font-size: 1.4rem; cursor: pointer; }

.token-library-upload {
    margin-left: auto; font-size: 0.75rem; padding: 2px 8px;
    background: #2f6a3a; border: 1px solid #46a057; border-radius: 6px; cursor: pointer;
}
.token-library-tray-head button { margin-left: 4px; }
.token-library-restore {
    position: absolute; left: 12px; bottom: 12px; z-index: 40;
    padding: 6px 12px; background: #1c140c; border: 1px solid #b9873f;
    border-radius: 8px; cursor: pointer; font-weight: 700;
}
.token-library-restore[hidden] { display: none; }

/* mark-as-player hides only the NPC-only sections (v0.9.45) */
.popover-section.player-hidden { display: none; }
.player-mark-label { color: #ffcf6b; font-weight: 600; }

/* duration field on condition damage */
.condition-damage-row .cd-turns { width: 52px; }

/* v0.9.39: read-only effect card players see when clicking a token */
.fx-card { padding: 4px 2px; }
.fx-card h3 { margin: 4px 0 8px; font-size: 0.95rem; color: #ffcf6b; }
.fx-card-row {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px;
    padding: 5px 6px; margin: 3px 0; border-radius: 6px;
    background: rgba(255,255,255,0.04);
}
.fx-card-name { font-weight: 700; text-transform: capitalize; }
.fx-card-dmg { color: #ff9a6b; font-size: 0.85rem; }
.fx-card-dur { color: #9fd0ff; font-size: 0.82rem; margin-left: auto; }

/* v0.9.39 fix: clean, non-ragged play-board top bar.
   Previously the calendar strip + indicator were mixed in with the DM buttons,
   so each landed on its own line and the row fragmented into 5 ragged rows even
   on wide screens. Now the calendar sits under the heading, and the DM buttons
   form one tidy group that wraps as a block. */
.board-top-heading { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.board-top-heading .calendar-strip { margin-top: 2px; }

body.page-board .board-top-actions {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
    flex-wrap: nowrap;
}
.board-action-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: flex-end;
}
.board-action-buttons button,
.board-action-buttons .button {
    flex: 0 0 auto;
    white-space: nowrap;
}
.map-view-indicator {
    display: flex; flex-direction: row; flex-wrap: wrap; gap: 4px 12px;
    margin-left: 0; font-size: 0.72rem; line-height: 1.2;
    justify-content: flex-end;
}

/* v0.9.40: grouped sidebar panels with section headers + icons */
.panel-group { margin-bottom: 14px; }
.panel-group-title {
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #c9a15a;
    padding: 4px 6px 6px;
    margin-top: 4px;
    border-bottom: 1px solid rgba(201,161,90,0.25);
    margin-bottom: 6px;
}
.panel-ico {
    display: inline-block;
    width: 1.3em;
    text-align: center;
    margin-right: 2px;
    filter: saturate(0.9);
}
/* tighten the panels within a group so they read as a set */
.panel-group details { margin-bottom: 5px; }

/* v0.9.40: push-to-players button in the editor header */
.editor-header-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
}
.editor-header-actions .map-view-indicator {
    flex: 1 0 100%;
    justify-content: flex-end;
}

/* v0.9.42: damage-type defense chips (4-state click-to-cycle) */
.damage-type-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 6px;
}
.damage-type-chip {
    display: flex; flex-direction: column; align-items: center; gap: 2px;
    padding: 6px 4px; border-radius: 8px; cursor: pointer;
    background: #241a10; border: 1px solid #5a4a33; color: #d8c4a4;
    font-size: 0.78rem; text-transform: capitalize; transition: all 0.12s;
}
.damage-type-chip .dtc-state { font-size: 0.6rem; font-weight: 800; letter-spacing: 0.05em; opacity: 0.7; }
.damage-type-chip[data-state="resistant"] { background: #123a2a; border-color: #2f9e5a; color: #9fe6b8; }
.damage-type-chip[data-state="immune"]    { background: #0f2a4a; border-color: #3a7ad0; color: #a8cfff; }
.damage-type-chip[data-state="vulnerable"]{ background: #4a1414; border-color: #d04a3a; color: #ffb0a8; }
.damage-type-chip[data-state="resistant"] .dtc-state,
.damage-type-chip[data-state="immune"] .dtc-state,
.damage-type-chip[data-state="vulnerable"] .dtc-state { opacity: 1; }
.damage-type-chip:hover { filter: brightness(1.15); }

/* v0.9.46: token -> character sheet link dropdown */
.player-link-label { display: block; margin-top: 6px; font-weight: 600; color: #ffcf6b; }
.player-link-select { width: 100%; margin-top: 3px; }

/* v0.9.46: halted-token banner with quick release */
.token-locked-banner {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    background: #4a1414; border: 1px solid #d04a3a; color: #ffcdc6;
    border-radius: 8px; padding: 7px 10px; margin: 6px 0; font-size: 0.85rem;
}
.token-locked-banner button {
    background: #2f9e44; border: 1px solid #37b355; border-radius: 6px;
    padding: 3px 10px; cursor: pointer; white-space: nowrap;
}

/* v0.9.52: conditions that actually do something */
/* Blinded: the world goes dark, but you can still feel for your own token and
   move it. Everything except your own tokens is hidden; the viewport itself
   goes black. */
.map-viewport.board-blinded { background: #000; }
.map-viewport.board-blinded #map-image,
.map-viewport.board-blinded #grid-layer,
.map-viewport.board-blinded #fog-layer,
.map-viewport.board-blinded #obstruction-layer,
.map-viewport.board-blinded #light-glow-layer,
.map-viewport.board-blinded #world-spot-layer,
.map-viewport.board-blinded #weather-layer,
.map-viewport.board-blinded .token:not(.token-mine) { visibility: hidden; }
.map-viewport.board-blinded .token.token-mine { opacity: 0.85; filter: grayscale(0.7); }
.blind-overlay {
    position: absolute; left: 0; right: 0; bottom: 12px; z-index: 95;
    display: flex; align-items: center; justify-content: center;
    color: #8a8a8a; font-size: 0.9rem; letter-spacing: 0.05em; pointer-events: none;
    text-align: center; padding: 0 12px;
}
.token.token-invisible-hidden { display: none !important; }
.token.token-invisible-faded { opacity: 0.45; filter: saturate(0.4); }
.fx-card-rule {
    flex: 1 0 100%; font-size: 0.78rem; color: #cbb9a0; opacity: 0.95; margin-top: 2px;
}

/* v0.9.52: stock a shop straight from the databases */
.store-db-picker {
    display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
    background: rgba(255,255,255,0.04); border: 1px solid #5a4a33;
    border-radius: 8px; padding: 8px 10px; margin: 6px 0 10px;
}
.store-db-picker input { flex: 1 1 240px; }
.store-db-picker .hint { flex: 1 0 100%; margin: 0; }

/* v0.9.54: table backup page */
.backup-layout { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 14px; align-items: start; }
.backup-summary { display: flex; flex-wrap: wrap; gap: 10px 18px; margin: 10px 0 14px; font-size: 0.88rem; }
.backup-summary strong { color: #ffcf6b; }
.primary-button { display: inline-block; background: #2f6a3a; border: 1px solid #46a057; }
.danger-hint { color: #ffb0a8; }

/* v0.9.57: wildshape active toggle */
.wildshape-active-toggle { margin: 8px 0 2px; font-size: 0.95rem; }
.wildshape-active-toggle strong { color: #7bd88f; }

/* v0.9.61: entry counts on the databases page */
.builtin-count {
    font-size: 0.72rem; font-weight: 700; color: #c9a15a;
    background: rgba(201,161,90,0.15); border: 1px solid rgba(201,161,90,0.35);
    border-radius: 10px; padding: 1px 8px; margin-left: 8px; vertical-align: middle;
}

/* v0.9.63: the World Map is a two-row screen (toolbar + viewport).
   The shared board shell has three rows for editor/board pages; on /world
   that put the viewport in an auto-sized row and left the flexible row empty,
   collapsing a loaded JPG into the thin strip visible in the bug report. */
body.page-world .world-board-shell {
    grid-template-rows: auto minmax(0, 1fr);
    min-height: 0;
}


/* v0.9.65: players see only the world map itself. The DM-only management
   sidebar is not rendered, so the board uses the full page width. */
body.page-world .editor-layout.world-player-layout {
    grid-template-columns: minmax(0, 1fr);
}

/* v0.9.68: live search results when stocking a shop from the databases */
.store-db-results {
    flex: 1 0 100%;
    max-height: 260px; overflow-y: auto; overscroll-behavior: contain;
    border: 1px solid #5a4a33; border-radius: 8px; background: #17110b;
    margin-top: 6px; padding: 4px;
}
.store-db-results[hidden] { display: none; }
.store-db-hit {
    display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
    width: 100%; text-align: left; background: transparent; border: none;
    border-radius: 6px; padding: 6px 8px; cursor: pointer; color: inherit;
}
.store-db-hit:hover, .store-db-hit:focus { background: rgba(255,207,107,0.14); }
.store-db-hit .hit-name { font-weight: 700; }
.store-db-hit .hit-meta { font-size: 0.75rem; color: #cbb9a0; }


/* v0.9.69: attack throw and dice modifier */
.dice-bonus-row { display:flex; align-items:center; justify-content:space-between; gap:10px; margin:10px 0; }
.dice-bonus-row input { width:88px; }
.attack-throw-box { display:grid; grid-template-columns:auto minmax(72px, 110px) minmax(100px, 1fr); gap:8px; align-items:center; margin:10px 0; padding:10px; border:1px solid var(--border); border-radius:12px; background:rgba(0,0,0,0.14); }
.attack-throw-box .hint { grid-column:1 / -1; margin:0; }
#attack-throw-button { cursor:grab; }
#attack-throw-button.attack-armed { outline:3px solid rgba(255, 85, 85, 0.75); box-shadow:0 0 18px rgba(255, 85, 85, 0.45); }
.token.attack-selectable { cursor:crosshair; }
.token.attack-drop-target, .token.attack-selectable:hover { box-shadow:0 0 0 5px rgba(255, 85, 85, 0.9), 0 0 28px rgba(255, 85, 85, 0.65); }


/* v0.9.70: DM damage, safe folder deletion and grid-step waypoint ruler */
.folder-tile-actions {
    display: flex;
    gap: 8px;
    margin-top: auto;
}
.folder-tile-actions button {
    flex: 1;
    min-width: 0;
    padding: 7px 8px;
}
.measure-layer .measure-total-label {
    fill: #ffdc83;
    font-size: 15px;
}
.measure-layer .measure-temp line {
    opacity: 0.88;
}


/* v0.9.74: smoother world-place dragging */
.world-spot {
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
    will-change: left, top;
}
body.role-dm .world-spot.dragging {
    cursor: grabbing;
    z-index: 30;
}
body.role-dm .world-spot.dragging .world-spot-label {
    box-shadow: 0 0 0 2px rgba(255, 207, 107, 0.55), 0 4px 14px rgba(0,0,0,0.55);
}

/* v0.9.81 - database-backed inventory and spell light sources */
.database-light-toggle {
    padding: .55rem .7rem;
    border: 1px solid color-mix(in srgb, var(--accent, #d3a54a) 45%, transparent);
    border-radius: 10px;
    background: color-mix(in srgb, var(--panel, #1f1830) 85%, transparent);
}
.database-light-fields {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: .75rem;
    padding: .75rem;
    border-left: 3px solid var(--accent, #d3a54a);
    border-radius: 8px;
    background: color-mix(in srgb, var(--panel-2, #29203d) 88%, transparent);
}
.database-light-fields[hidden] { display: none !important; }
.database-light-fields small { display: block; margin-top: .25rem; }
.database-light-badge {
    display: inline-flex;
    margin: .5rem 0 0;
    padding: .3rem .6rem;
    border: 1px solid #e3a23a;
    border-radius: 999px;
    color: #ffe4a3;
    background: rgba(227, 162, 58, .12);
    font-size: .82rem;
    font-weight: 700;
}
.light-source-picker {
    display: grid;
    gap: .55rem;
}
.light-source-picker select { width: 100%; }
.light-source-active {
    display: grid;
    gap: .25rem;
    padding: .6rem .7rem;
    border: 1px solid rgba(244, 172, 57, .55);
    border-radius: 10px;
    background: rgba(244, 138, 33, .1);
}
.light-source-active strong { color: #ffd38a; }
.light-source-meta { font-size: .82rem; opacity: .8; }
@media (max-width: 720px) {
    .database-light-fields { grid-template-columns: 1fr; }
}

/* v0.9.82: player-managed concentration and automatic save indicator */
.token-concentration-badge {
    position: absolute;
    top: -13px;
    left: 50%;
    z-index: 7;
    display: grid;
    width: 22px;
    height: 22px;
    place-items: center;
    transform: translateX(-50%);
    border: 1px solid rgba(255, 224, 114, 0.95);
    border-radius: 50%;
    background: radial-gradient(circle, #fff2a8 0 18%, #8f54df 48%, #26113f 100%);
    color: #fff5b5;
    font-size: 0.88rem;
    line-height: 1;
    text-shadow: 0 0 6px #fff1a1;
    box-shadow: 0 0 10px rgba(166, 92, 244, 0.8), 0 2px 4px rgba(0,0,0,0.7);
}

.concentration-card {
    margin: 4px 0 10px;
    padding: 10px;
    border: 1px solid rgba(184, 118, 255, 0.42);
    border-radius: 9px;
    background: linear-gradient(145deg, rgba(104, 48, 159, 0.18), rgba(255, 204, 87, 0.05));
}
.concentration-card label { display: block; margin: 0 0 5px; font-size: 0.82rem; font-weight: 700; }
.concentration-card input, .concentration-card select { width: 100%; box-sizing: border-box; }
.concentration-card .hint { margin: 7px 0 9px; font-size: 0.76rem; line-height: 1.4; }
.concentration-actions { display: flex; flex-wrap: wrap; gap: 7px; }
.concentration-actions button { flex: 1 1 145px; }
.concentration-current {
    padding: 9px 11px;
    border-radius: 7px;
    background: rgba(0,0,0,0.2);
    color: #ead5ff;
    font-weight: 800;
    overflow-wrap: anywhere;
}

/* v0.9.83: character-sheet concentration selector */
.warning-hint { color: #dca8a8; }

/* ======================================================================
   v0.9.88 — shared component structure across every appearance theme

   Tavern originally supplied both its visual skin and the only layout rules
   for several components. Switching to Arcane, Dungeon, Daylight, Forest,
   Infernal, or Contrast therefore made account rows, party controls, dice,
   quest-board helpers, and small action buttons fall back to raw block flow.
   These rules define structure once; each theme still supplies its own color,
   texture, border, and typography through variables/overrides.
   ====================================================================== */

/* Admin dashboard and Party account management */
.admin-grid {
    display: grid;
    gap: 16px;
}

.admin-tables-card {
    padding-bottom: 20px;
}

.admin-table-block {
    margin-top: 14px;
    padding: 14px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--panel2);
    background: color-mix(in srgb, var(--panel2) 82%, transparent);
}

.admin-table-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 10px;
    padding-bottom: 10px;
    border-bottom: 1px dashed var(--border);
}

.admin-table-head-actions,
.quest-acceptance-actions,
.trade-offer-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

.admin-table-head-actions form,
.admin-account-row > form {
    margin: 0;
}

.admin-account-list,
.quest-acceptance-list,
.town-map-bind-list,
.quest-board-picker {
    display: grid;
    gap: 8px;
}

.admin-account-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    min-width: 0;
    padding: 8px 10px;
    border: 1px solid color-mix(in srgb, var(--border) 45%, transparent);
    border-radius: 10px;
    background: rgba(0, 0, 0, 0.18);
}

.admin-account-row strong {
    min-width: 90px;
}
/* The redesigned admin page nests its <strong> one level deeper, inside
   .admin-account-identity (for the ellipsis-truncate treatment on long
   names) - but the older rule above is a descendant selector, so it still
   matched at any depth and forced a stray 90px minimum width onto every
   account name, leaving uneven gaps before the reset/remove buttons on
   short names. Reset it back to natural sizing for the new layout. */
.admin-console .admin-account-row strong {
    min-width: 0;
}

.inline-reset-form {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    margin-left: auto !important;
}

.inline-reset-form input {
    width: 150px;
    min-width: 120px;
}

.small-button {
    width: auto;
    padding: 6px 10px;
    font-size: 0.78rem;
    line-height: 1.2;
}

.code-pill {
    font-family: var(--display-font, inherit);
    letter-spacing: 0.1em;
    font-size: 0.85rem;
}

.big-code {
    display: inline-block;
    padding: 6px 14px;
    font-size: 1.3rem;
}

.table-code-display {
    display: grid;
    gap: 6px;
    margin-bottom: 4px;
}

.account-card {
    max-width: 460px;
}

.code-input {
    text-align: center;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    font-family: var(--display-font, inherit);
}

.login-code-hint {
    line-height: 1.5;
}

/* Dice popover must remain a popover in every theme. */
.dice-popover {
    position: fixed;
    top: 64px;
    right: 16px;
    z-index: 80;
    display: none;
    width: min(262px, calc(100vw - 32px));
    padding: 14px;
    color: var(--text);
    background: var(--panel2);
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: var(--shadow);
}

.dice-popover.open {
    display: block;
}

.dice-popover h3 {
    margin: 0 0 10px;
    text-align: center;
    font-size: 1rem;
}

.dice-popover-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 6px;
}

.dice-popover-grid button {
    min-width: 0;
    padding: 10px 4px;
    font-size: 0.9rem;
}

.dice-popover-grid button[data-die="20"] {
    grid-column: span 2;
}

.dice-popover-result {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 44px;
    margin-top: 10px;
    padding: 6px;
    text-align: center;
    color: var(--gold);
    background: rgba(0, 0, 0, 0.2);
    border: 1px dashed var(--border);
    border-radius: 8px;
    font-family: var(--display-font, inherit);
    font-size: 1.05rem;
}

.dice-popover-result .die-total {
    color: var(--gold);
    font-size: 1.5rem;
}

.dice-popover .hint {
    text-align: center;
}

/* Quest-board, trade, and town-management structure. Themes may decorate it. */
.quest-corkboard {
    column-width: 230px;
    column-gap: 22px;
    padding: 20px 14px 4px;
}

.quest-board-note {
    position: relative;
    display: inline-block;
    width: 100%;
    box-sizing: border-box;
    break-inside: avoid;
    margin: 0 0 18px;
}

.quest-board-pin {
    position: absolute;
    top: -14px;
    left: 50%;
    z-index: 1;
    transform: translateX(-50%);
    line-height: 1;
}

.quest-board-pin-dagger {
    top: -12px;
    transform: translateX(-50%) rotate(-38deg);
}

.quest-board-pin-nail {
    display: inline-flex;
}

.quest-board-objectives {
    margin: 0 0 10px;
    padding-left: 18px;
}

.quest-board-note button {
    width: 100%;
}

.quest-board-accepted-badge {
    display: block;
    padding: 8px;
    text-align: center;
}

.quest-board-picker {
    margin: 10px 0 16px;
    max-height: 340px;
    overflow-y: auto;
    padding-right: 4px;
    display: grid;
    gap: 6px;
}

/* Search row above the quest-board picker: filter box + live pinned count. */
.quest-board-search-row {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 10px 0 6px;
}
.quest-board-search-row input {
    flex: 1;
    padding: 9px 12px;
    border-radius: 10px;
    background: var(--input-bg, rgba(0, 0, 0, 0.3));
    color: var(--text);
    border: 1px solid var(--border);
}
.quest-board-search-row input:focus { outline: none; border-color: var(--gold); }
.quest-board-pinned-count {
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--gold);
    white-space: nowrap;
    padding: 4px 10px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--accent, var(--gold)) 16%, transparent);
}
.quest-board-group-label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--muted);
    font-weight: 700;
    margin: 8px 2px 2px;
}
.quest-board-group-label:first-child { margin-top: 0; }

.quest-board-picker-row,
.town-map-bind-row {
    padding: 8px 12px;
    border: 1px solid color-mix(in srgb, var(--border) 42%, transparent);
    border-radius: 10px;
    background: rgba(0, 0, 0, 0.16);
}

.quest-acceptances-box {
    margin-bottom: 16px;
    padding-bottom: 14px;
    border-bottom: 1px dashed var(--border);
}

.quest-acceptance-row,
.trade-offer-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px;
    padding: 8px 12px;
    border: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
    border-radius: 10px;
    background: rgba(0, 0, 0, 0.14);
}

.trade-offer-row {
    margin-bottom: 6px;
}

.town-map-bind-list {
    margin: 10px 0 12px;
}
.town-map-bound-summary {
    margin: 6px 0 12px; padding: 8px 12px; border-radius: 10px;
    background: color-mix(in srgb, var(--gold) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--gold) 40%, transparent);
    color: var(--text); font-size: 0.88rem;
}
.town-map-bind-details { padding: 8px 12px; }
.town-map-bind-details > summary { font-size: 0.92rem; font-weight: 700; color: var(--muted); }
.town-map-bind-details[open] > summary { color: var(--text); margin-bottom: 6px; }

/* Map/token helpers that previously only appeared correctly in Tavern. */
.trap-badge {
    position: absolute;
    top: -8px;
    right: -8px;
    z-index: 3;
    font-size: 0.95rem;
    filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.7));
}

.torch-burning {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 10px;
    color: var(--gold);
    background: color-mix(in srgb, var(--accent) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
    border-radius: 10px;
    font-family: var(--display-font, inherit);
}

.badge.player-sold,
.badge.buyback-grace {
    border-color: color-mix(in srgb, var(--green) 55%, transparent);
    color: var(--green);
}

.town-enter-button {
    width: 100%;
}

/* Keyboard and blocked-movement feedback should not depend on the skin. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

@keyframes token-bump-shared {
    0%   { transform: translate(-50%, -50%) translate(0, 0); }
    25%  { transform: translate(-50%, -50%) translate(var(--bump-x, 6px), var(--bump-y, 0)); }
    50%  { transform: translate(-50%, -50%) translate(calc(var(--bump-x, 6px) * -0.6), calc(var(--bump-y, 0) * -0.6)); }
    75%  { transform: translate(-50%, -50%) translate(calc(var(--bump-x, 6px) * 0.3), calc(var(--bump-y, 0) * 0.3)); }
    100% { transform: translate(-50%, -50%) translate(0, 0); }
}

.token.token-bump {
    animation: token-bump-shared 220ms ease;
    border-color: var(--danger);
}

@media (max-width: 760px) {
    .admin-table-head-actions {
        width: 100%;
    }

    .admin-table-head-actions form,
    .admin-table-head-actions button {
        flex: 1 1 auto;
    }

    .admin-account-row {
        align-items: stretch;
    }

    .admin-account-row > .hint {
        flex: 1 1 100%;
    }

    .inline-reset-form {
        width: 100%;
        margin-left: 0 !important;
    }

    .inline-reset-form input {
        flex: 1 1 auto;
        width: auto;
    }
}

/* v0.9.90: concentration lives in the token right-click menu, directly
   beneath Archer Range. Keep the controls compact and theme-aware. */
.archer-range-menu {
    width: min(310px, calc(100vw - 20px));
    min-width: 240px;
    max-height: min(520px, calc(100vh - 20px));
    overflow-y: auto;
}
.archer-menu-section {
    display: grid;
    gap: 6px;
}
.archer-menu-section > strong {
    color: var(--accent);
    font-size: 0.84rem;
    letter-spacing: 0.035em;
}
.archer-menu-divider {
    height: 1px;
    margin: 3px 0;
    background: var(--border);
    opacity: 0.9;
}
.concentration-menu-section label {
    margin: 0;
    font-size: 0.76rem;
    color: var(--muted);
}
.concentration-menu-section select,
.concentration-menu-section input {
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
}
.concentration-menu-section .concentration-actions {
    margin-top: 2px;
}
.concentration-menu-section .concentration-current {
    margin-top: 1px;
}


/* v0.9.91: compact status creation, completed quest history */
.status-add-form { gap: 9px; }
.status-add-form label { margin: 0; }
.status-add-form label > span {
    display: block;
    margin: 0 0 4px;
    color: var(--muted, #d8c4a4);
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
}
.status-add-fields {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(78px, .42fr);
    gap: 8px;
}
.status-add-fields input,
.status-condition-field select,
.status-add-form #status-add-btn { width: 100%; min-width: 0; }
.status-add-hint { margin: -2px 0 0; font-size: .72rem; }
.quest-complete-button { background: #2f7a46; border-color: #4fa86a; }
.quest-complete-badge { color: #baf5c8; border-color: rgba(79,168,106,.55); }
.quest-history-page { max-width: 1100px; margin: 0 auto; }
.quest-history-active { margin-bottom: 16px; }
.quest-history-list { display: grid; gap: 14px; }
.quest-history-card { position: relative; overflow: hidden; }
.quest-history-card::before {
    content: ""; position: absolute; inset: 0 auto 0 0; width: 4px;
    background: color-mix(in srgb, var(--accent, #d2a74b) 75%, #4fa86a);
}
.quest-history-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 15px; }
.quest-history-head h2 { margin: 0 0 4px; }
.quest-history-date { white-space: nowrap; color: var(--muted, #b9ac93); font-size: .78rem; }
.quest-history-objectives { margin: 13px 0 0; padding-left: 20px; }
.quest-history-objectives li { margin: 5px 0; }
@media (max-width: 560px) {
    .status-add-fields { grid-template-columns: 1fr; }
    .quest-history-head { display: block; }
    .quest-history-date { display: block; margin-top: 5px; }
}


/* v0.9.94: explicit obstruction removal and precise wall cursor */
.map-viewport.obstruction-draw-mode {
    /* A crosshair has its hotspot in the visual centre, so the preview point
       and the saved wall endpoint visibly match the exact cursor location. */
    cursor: crosshair;
}

.map-viewport.obstruction-remove-mode {
    cursor: default;
}

body.role-dm .map-viewport.obstruction-remove-mode .wall-line,
body.role-dm .map-viewport.obstruction-remove-mode .door-line {
    cursor: pointer;
    stroke-width: 10;
    filter: drop-shadow(0 0 5px rgba(255, 99, 118, 0.8));
}

body.role-dm .map-viewport.obstruction-draw-mode .wall-line,
body.role-dm .map-viewport.obstruction-draw-mode .door-line {
    cursor: crosshair;
}

/* ======================================================================
   v0.9.96 — Campaign Control admin console
   A themed administration dashboard with a command header, operational
   cards, campaign registry, and compact account roster. All structure is
   shared; existing appearance themes continue to supply the palette.
   ====================================================================== */
.sr-only {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

.admin-console {
    --admin-surface: color-mix(in srgb, var(--panel) 91%, transparent);
    --admin-raised: color-mix(in srgb, var(--panel2) 92%, transparent);
    --admin-soft: color-mix(in srgb, var(--accent) 9%, transparent);
    --admin-line: color-mix(in srgb, var(--border) 72%, transparent);
    width: min(1500px, calc(100% - 28px));
    margin: 18px auto 54px;
}

.admin-command-hero {
    position: relative;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 20px;
    min-height: 150px;
    padding: 28px 30px;
    overflow: hidden;
    border: 1px solid var(--admin-line);
    border-radius: 22px;
    background:
        linear-gradient(120deg, color-mix(in srgb, var(--accent) 13%, transparent), transparent 42%),
        linear-gradient(155deg, var(--admin-raised), var(--admin-surface));
    box-shadow: var(--shadow);
}

.admin-command-hero::before,
.admin-command-hero::after {
    content: "";
    position: absolute;
    pointer-events: none;
}

.admin-command-hero::before {
    inset: 0;
    opacity: .28;
    background:
        linear-gradient(90deg, transparent 49.5%, color-mix(in srgb, var(--border) 38%, transparent) 50%, transparent 50.5%),
        linear-gradient(0deg, transparent 49.5%, color-mix(in srgb, var(--border) 28%, transparent) 50%, transparent 50.5%);
    background-size: 46px 46px;
    mask-image: linear-gradient(90deg, transparent 18%, #000 60%);
}

.admin-command-hero::after {
    width: 330px;
    height: 330px;
    right: -125px;
    top: -135px;
    border: 1px solid color-mix(in srgb, var(--accent) 42%, transparent);
    border-radius: 50%;
    box-shadow:
        0 0 0 26px color-mix(in srgb, var(--accent) 4%, transparent),
        0 0 0 54px color-mix(in srgb, var(--accent) 3%, transparent);
}

.admin-command-mark {
    position: relative;
    z-index: 1;
    display: grid;
    width: 82px;
    height: 82px;
    place-items: center;
    border: 1px solid color-mix(in srgb, var(--accent) 66%, var(--border));
    border-radius: 22px;
    color: var(--accent);
    background: color-mix(in srgb, var(--accent) 10%, rgba(0,0,0,.2));
    box-shadow: inset 0 0 24px color-mix(in srgb, var(--accent) 8%, transparent);
}

.admin-command-mark svg { width: 54px; height: 54px; }
.admin-command-copy,
.admin-command-actions { position: relative; z-index: 1; }

.admin-eyebrow,
.admin-operation-kicker {
    display: block;
    margin: 0 0 6px;
    color: var(--accent);
    font-family: var(--display-font, inherit);
    font-size: .74rem;
    font-weight: 900;
    letter-spacing: .16em;
    text-transform: uppercase;
}

.admin-command-copy h1 {
    margin: 0;
    color: var(--text);
    font-family: var(--display-font, inherit);
    font-size: clamp(2rem, 4vw, 3.5rem);
    line-height: 1;
    letter-spacing: .02em;
}

.admin-command-copy > p:last-child {
    max-width: 720px;
    margin: 12px 0 0;
    color: var(--muted);
    font-size: 1rem;
    line-height: 1.55;
}

.admin-command-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 10px;
}

.admin-command-actions .button { text-decoration: none; white-space: nowrap; }
.admin-secondary-action {
    color: var(--text) !important;
    background: color-mix(in srgb, var(--panel2) 86%, transparent) !important;
}

.admin-stat-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 12px;
    margin: 14px 0 20px;
}

.admin-stat-card {
    display: flex;
    align-items: center;
    gap: 13px;
    min-width: 0;
    padding: 16px 18px;
    border: 1px solid var(--admin-line);
    border-radius: 15px;
    background: var(--admin-surface);
    box-shadow: 0 10px 26px rgba(0,0,0,.16);
}

.admin-stat-icon {
    display: grid;
    flex: 0 0 44px;
    width: 44px;
    height: 44px;
    place-items: center;
    border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--border));
    border-radius: 13px;
    color: var(--accent);
    background: color-mix(in srgb, var(--accent) 10%, transparent);
    font-size: .78rem;
    font-weight: 900;
    letter-spacing: .04em;
}

.admin-stat-card strong,
.admin-stat-card span { display: block; }
.admin-stat-card strong {
    color: var(--text);
    font-family: var(--display-font, inherit);
    font-size: 1.35rem;
    line-height: 1.1;
}
.admin-stat-card div > span { margin-top: 3px; color: var(--muted); font-size: .78rem; }
.admin-stat-card.needs-attention .admin-stat-icon { color: var(--rose); border-color: color-mix(in srgb, var(--rose) 45%, transparent); }
.admin-stat-card.is-ready .admin-stat-icon { color: var(--green); border-color: color-mix(in srgb, var(--green) 45%, transparent); }

.admin-operations-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.45fr) minmax(320px, .75fr);
    align-items: start;
    gap: 16px;
}

.admin-operation-column { display: grid; gap: 16px; }

.admin-operation-card {
    border: 1px solid var(--admin-line);
    border-radius: 17px;
    background: var(--admin-surface);
    box-shadow: 0 12px 30px rgba(0,0,0,.18);
    overflow: clip;
}

.admin-operation-card[open] {
    background:
        linear-gradient(155deg, color-mix(in srgb, var(--accent) 5%, transparent), transparent 42%),
        var(--admin-surface);
}

.admin-operation-featured { min-height: 100%; }

.admin-operation-card > summary {
    position: relative;
    display: grid;
    gap: 3px;
    padding: 18px 52px 18px 20px;
    cursor: pointer;
    list-style: none;
    user-select: none;
}
.admin-operation-card > summary::-webkit-details-marker { display: none; }
.admin-operation-card > summary::after {
    content: "+";
    position: absolute;
    top: 18px;
    right: 18px;
    display: grid;
    width: 28px;
    height: 28px;
    place-items: center;
    border: 1px solid var(--admin-line);
    border-radius: 50%;
    color: var(--accent);
    background: color-mix(in srgb, var(--panel2) 88%, transparent);
    font-size: 1.1rem;
    line-height: 1;
}
.admin-operation-card[open] > summary::after { content: "−"; }
.admin-operation-card > summary:hover { background: color-mix(in srgb, var(--accent) 5%, transparent); }

.admin-operation-title {
    color: var(--text);
    font-family: var(--display-font, inherit);
    font-size: 1.3rem;
    font-weight: 900;
}
.admin-operation-summary { color: var(--muted); font-size: .82rem; line-height: 1.45; }
.admin-import-hint { color: var(--muted); font-size: .8rem; line-height: 1.5; margin: 2px 0 6px; padding: 10px 12px; border-radius: 10px; background: color-mix(in srgb, var(--panel) 50%, transparent); border: 1px solid var(--border); }

.admin-form-stack {
    display: grid;
    gap: 13px;
    padding: 18px 20px 20px;
    border-top: 1px solid var(--admin-line);
}

.admin-form-stack label,
.admin-field-grid label {
    display: grid;
    gap: 6px;
    min-width: 0;
}
.admin-form-stack label > span,
.admin-field-grid label > span {
    color: var(--muted);
    font-size: .75rem;
    font-weight: 800;
    letter-spacing: .035em;
}

.admin-field-grid {
    display: grid;
    gap: 12px;
}
.admin-account-fields { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.admin-backup-fields { grid-template-columns: minmax(0, 1fr) 180px; }

.admin-form-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding-top: 4px;
}
.admin-form-footer .hint { max-width: 650px; margin: 0; }
.admin-form-footer button { flex: 0 0 auto; }

.admin-backup-card { margin-top: 16px; }
.admin-backup-layout {
    display: grid;
    grid-template-columns: minmax(0, 1.4fr) minmax(280px, .6fr);
    border-top: 1px solid var(--admin-line);
}
.admin-backup-layout > .admin-form-stack { border-top: 0; }
.admin-backup-actions {
    display: grid;
    align-content: center;
    gap: 14px;
    padding: 20px;
    border-left: 1px solid var(--admin-line);
    background: color-mix(in srgb, var(--panel2) 48%, transparent);
}
.admin-backup-actions form,
.admin-backup-actions button { width: 100%; margin: 0; }
.admin-download-list { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; }
.admin-download-list > span:first-child { flex: 1 1 100%; color: var(--muted); font-size: .75rem; font-weight: 800; }
.admin-download-list .badge { text-decoration: none; }

.admin-registry { margin-top: 28px; }
.admin-section-heading {
    display: flex;
    align-items: end;
    justify-content: space-between;
    gap: 20px;
    margin-bottom: 14px;
    padding: 0 2px;
}
.admin-section-heading h2 {
    margin: 0;
    color: var(--text);
    font-family: var(--display-font, inherit);
    font-size: clamp(1.65rem, 3vw, 2.35rem);
}
.admin-section-heading p:last-child { max-width: 700px; margin: 7px 0 0; color: var(--muted); }
.admin-search { width: min(330px, 100%); }
.admin-search input { width: 100%; }

.admin-campaign-grid { display: grid; gap: 15px; }
.admin-campaign-card {
    border: 1px solid var(--admin-line);
    border-radius: 18px;
    background: var(--admin-surface);
    box-shadow: 0 14px 32px rgba(0,0,0,.17);
    overflow: hidden;
}
.admin-campaign-card[hidden] { display: none; }

.admin-campaign-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 15px;
    padding: 17px 18px;
    border-bottom: 1px solid var(--admin-line);
    background:
        linear-gradient(90deg, color-mix(in srgb, var(--accent) 8%, transparent), transparent 58%),
        color-mix(in srgb, var(--panel2) 58%, transparent);
}

.admin-campaign-identity {
    display: flex;
    align-items: center;
    min-width: 0;
    gap: 13px;
}
.admin-campaign-seal {
    display: grid;
    flex: 0 0 48px;
    width: 48px;
    height: 48px;
    place-items: center;
    border: 1px solid color-mix(in srgb, var(--accent) 62%, var(--border));
    border-radius: 15px;
    color: var(--accent);
    background: color-mix(in srgb, var(--accent) 10%, transparent);
    font-family: var(--display-font, inherit);
    font-size: 1.3rem;
    font-weight: 900;
}
.admin-campaign-head h3 { margin: 0; color: var(--text); font-family: var(--display-font, inherit); font-size: 1.25rem; }
.admin-campaign-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 7px 12px; margin-top: 5px; color: var(--muted); font-size: .75rem; }

.admin-roster { display: grid; gap: 13px; padding: 16px 18px 18px; }
.admin-roster-section { display: grid; gap: 7px; }
.admin-roster-section h4 {
    margin: 0 0 1px;
    color: var(--muted);
    font-size: .72rem;
    letter-spacing: .13em;
    text-transform: uppercase;
}

.admin-console .admin-account-row {
    display: grid;
    grid-template-columns: 38px minmax(150px, .8fr) minmax(260px, 1.2fr) auto;
    align-items: center;
    gap: 10px;
    min-width: 0;
    padding: 9px 10px;
    border: 1px solid color-mix(in srgb, var(--border) 42%, transparent);
    border-radius: 12px;
    background: color-mix(in srgb, var(--panel2) 42%, transparent);
}
.admin-account-avatar {
    display: grid;
    width: 34px;
    height: 34px;
    place-items: center;
    border: 1px solid var(--admin-line);
    border-radius: 11px;
    color: var(--text);
    background: color-mix(in srgb, var(--accent) 9%, transparent);
    font-size: .64rem;
    font-weight: 900;
}
.admin-account-avatar.dm { color: var(--accent); }
.admin-account-avatar.player { color: var(--blue); }
.admin-account-identity { min-width: 0; }
.admin-account-identity strong,
.admin-account-identity span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-account-identity strong { color: var(--text); }
.admin-account-identity span { margin-top: 2px; color: var(--muted); font-size: .73rem; }

.admin-console .inline-reset-form {
    display: grid;
    grid-template-columns: minmax(130px, 1fr) auto;
    align-items: center;
    gap: 7px;
    width: 100%;
    min-width: 0;
    margin: 0 !important;
}
.admin-console .inline-reset-form input { width: 100%; min-width: 0; }
.admin-console .admin-account-row > form:last-child { margin: 0; }

.admin-roster-empty,
.admin-empty-state {
    padding: 28px;
    text-align: center;
    border: 1px dashed var(--admin-line);
    border-radius: 15px;
    color: var(--muted);
    background: color-mix(in srgb, var(--panel2) 34%, transparent);
}
.admin-roster-empty p { margin: 0 0 7px; }
.admin-roster-empty a { color: var(--accent); }
.admin-empty-state { padding: 48px 24px; }
.admin-empty-state h3 { margin: 10px 0 4px; color: var(--text); }
.admin-empty-state p { margin: 0 auto 16px; max-width: 520px; }
.admin-empty-mark {
    display: grid;
    width: 56px;
    height: 56px;
    margin: auto;
    place-items: center;
    border: 1px solid var(--admin-line);
    border-radius: 18px;
    color: var(--accent);
    background: var(--admin-soft);
    font-size: 2rem;
}
.admin-search-empty { padding: 28px; text-align: center; color: var(--muted); }

html[data-theme="tavern"] .admin-command-hero,
html[data-theme="tavern"] .admin-operation-card,
html[data-theme="tavern"] .admin-campaign-card,
html[data-theme="tavern"] .admin-stat-card {
    box-shadow: inset 0 1px rgba(255,230,175,.04), 0 14px 34px rgba(0,0,0,.3);
}

html[data-theme="dungeon"] .admin-command-mark,
html[data-theme="dungeon"] .admin-campaign-seal,
html[data-theme="dungeon"] .admin-stat-icon {
    border-radius: 6px;
}

html[data-theme="daylight"] .admin-console {
    --admin-surface: rgba(255,255,255,.86);
    --admin-raised: rgba(250,247,239,.94);
}

html[data-theme="contrast"] .admin-operation-card,
html[data-theme="contrast"] .admin-campaign-card,
html[data-theme="contrast"] .admin-command-hero,
html[data-theme="contrast"] .admin-stat-card {
    border-width: 2px;
    box-shadow: none;
}

@media (max-width: 1050px) {
    .admin-command-hero { grid-template-columns: auto minmax(0, 1fr); }
    .admin-command-actions { grid-column: 1 / -1; justify-content: flex-start; }
    .admin-operations-grid { grid-template-columns: 1fr; }
    .admin-account-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .admin-console .admin-account-row { grid-template-columns: 38px minmax(120px, .65fr) minmax(240px, 1.35fr) auto; }
}

@media (max-width: 820px) {
    .admin-stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .admin-backup-layout { grid-template-columns: 1fr; }
    .admin-backup-actions { border-top: 1px solid var(--admin-line); border-left: 0; }
    .admin-section-heading { align-items: stretch; flex-direction: column; }
    .admin-search { width: 100%; }
    .admin-console .admin-account-row {
        grid-template-columns: 38px minmax(0, 1fr) auto;
    }
    .admin-console .inline-reset-form { grid-column: 1 / -1; }
}

@media (max-width: 600px) {
    .admin-console { width: min(100% - 16px, 1500px); margin-top: 10px; }
    .admin-command-hero { grid-template-columns: 1fr; padding: 22px 20px; }
    .admin-command-mark { width: 64px; height: 64px; border-radius: 17px; }
    .admin-command-mark svg { width: 42px; height: 42px; }
    .admin-command-actions { grid-column: auto; align-items: stretch; flex-direction: column; }
    .admin-command-actions .button { text-align: center; }
    .admin-stat-grid { grid-template-columns: 1fr; }
    .admin-account-fields,
    .admin-backup-fields { grid-template-columns: 1fr; }
    .admin-form-footer { align-items: stretch; flex-direction: column; }
    .admin-form-footer button { width: 100%; }
    .admin-campaign-head { align-items: stretch; }
    .admin-table-head-actions { width: 100%; }
    .admin-table-head-actions form { flex: 1 1 140px; }
    .admin-table-head-actions button { width: 100%; }
    .admin-console .admin-account-row { grid-template-columns: 38px minmax(0, 1fr); }
    .admin-console .admin-account-row > form:last-child { grid-column: 1 / -1; }
    .admin-console .admin-account-row > form:last-child button { width: 100%; }
}

/* v0.9.97 — complete portable table downloads */
.admin-download-list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}
.admin-download-list > span:first-child,
.admin-download-list > small {
    flex-basis: 100%;
}
.admin-full-download {
    white-space: nowrap;
    text-decoration: none;
}
@media (max-width: 760px) {
    .admin-table-head-actions .admin-full-download {
        width: 100%;
        text-align: center;
    }
}


/* v0.9.103: a quest board can be mounted inside every tavern. */
.tavern-visit-actions { display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; margin:6px 0 16px; }
.tavern-visit-actions .hint { margin:0; }
.tavern-quest-board-editor { margin-top:18px; padding:16px; border:1px solid var(--line); border-radius:14px; background:color-mix(in srgb,var(--panel) 82%,transparent); }
.tavern-quest-board-editor h3 { margin-top:0; }

/* ============================================================
   QUEST BOOK + QUEST CREATOR  (v0.9.77)
   ============================================================ */

/* ---- Category tags (shared) ---- */
.quest-tag {
    display: inline-block;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    vertical-align: middle;
}
.quest-tag-main { background: rgba(255, 212, 110, 0.18); color: var(--gold); border: 1px solid rgba(255, 212, 110, 0.5); }
.quest-tag-side { background: rgba(123, 220, 255, 0.16); color: var(--blue); border: 1px solid rgba(123, 220, 255, 0.45); }

/* ---- Quest creator: category toggle ---- */
.quest-category-toggle { display: flex; gap: 10px; margin-bottom: 6px; flex-wrap: wrap; }
.quest-cat-option { position: relative; cursor: pointer; flex: 1; min-width: 140px; }
.quest-cat-option input { position: absolute; opacity: 0; pointer-events: none; }
.quest-cat-option span {
    display: block; text-align: center; padding: 10px 12px;
    border: 1px solid var(--border); border-radius: 12px;
    background: rgba(0,0,0,0.18); color: var(--muted); font-weight: 600;
    transition: border-color .15s, background .15s, color .15s;
}
.quest-cat-option input:checked + span {
    border-color: var(--gold); color: var(--text);
    background: rgba(255, 212, 110, 0.14);
    box-shadow: 0 0 0 1px rgba(255, 212, 110, 0.4) inset;
}
.quest-cat-option input:focus-visible + span { outline: 2px solid var(--gold); outline-offset: 2px; }

/* ---- Quest creator: objective rows with + / remove ---- */
.objective-rows { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.objective-row { display: flex; align-items: center; gap: 8px; }
.objective-row input { flex: 1; }
.objective-grip { color: var(--muted); opacity: 0.5; cursor: default; user-select: none; font-size: 0.9rem; }
.objective-remove {
    flex: 0 0 auto; width: 34px; height: 34px; padding: 0;
    border-radius: 9px; font-size: 0.85rem; line-height: 1;
}
.add-objective-button {
    align-self: flex-start; margin-bottom: 12px;
    background: rgba(109, 255, 181, 0.12); color: var(--green);
    border: 1px dashed rgba(109, 255, 181, 0.5);
}
.add-objective-button:hover { border-style: solid; background: rgba(109, 255, 181, 0.2); }

.quest-edit-head { display: flex; align-items: center; gap: 10px; justify-content: space-between; }
.primary-save { background: rgba(255, 212, 110, 0.2); border-color: var(--gold); color: var(--text); font-weight: 700; }
.quest-unsaved-hint { color: var(--gold); }

/* ---- Quest creator: party leader box ---- */
.quest-leader-box { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border); }
.quest-leader-box h3 { margin: 0 0 4px; }
.quest-leader-form { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.quest-leader-form select { flex: 1; min-width: 120px; }

/* ============================================================
   QUEST BOOK PAGE — book-look
   ============================================================ */
.questbook { max-width: 1000px; margin: 0 auto; }

.questbook-tabs { display: flex; gap: 6px; margin-bottom: -1px; padding-left: 10px; flex-wrap: wrap; }
.questbook-tab {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 10px 16px 12px; border: 1px solid var(--border); border-bottom: none;
    border-radius: 12px 12px 0 0; background: rgba(0,0,0,0.28); color: var(--muted);
    font-weight: 600; cursor: pointer; position: relative; top: 1px;
    transition: background .15s, color .15s;
}
.questbook-tab:hover { color: var(--text); }
.questbook-tab.active {
    background: linear-gradient(180deg, #efe3c4, #e7d9b6);
    color: #3a2c10; border-color: rgba(255, 212, 110, 0.55);
}
.qb-tab-icon { font-size: 1rem; }
.qb-count {
    display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 5px;
    border-radius: 999px; font-size: 0.72rem; font-weight: 800;
    background: rgba(0,0,0,0.22); color: inherit;
}
.questbook-tab.active .qb-count { background: rgba(58, 44, 16, 0.18); }

/* The book itself — aged parchment pages with a centre spine */
.questbook-book {
    position: relative;
    border: 1px solid rgba(255, 212, 110, 0.55);
    border-radius: 6px 16px 16px 16px;
    background:
        radial-gradient(120% 90% at 50% 0%, #f3e8cd 0%, #ecdcbb 55%, #e2cfa5 100%);
    box-shadow: var(--shadow), inset 0 0 60px rgba(120, 85, 30, 0.18);
    padding: 30px clamp(20px, 5vw, 60px);
    min-height: 420px;
    overflow: hidden;
}
/* faint centre gutter to suggest two pages */
.questbook-spine {
    position: absolute; top: 12px; bottom: 12px; left: 50%; width: 40px;
    transform: translateX(-50%);
    background: linear-gradient(90deg, transparent, rgba(120, 85, 30, 0.16) 45%, rgba(120, 85, 30, 0.22) 50%, rgba(120, 85, 30, 0.16) 55%, transparent);
    pointer-events: none;
}
@media (max-width: 720px) { .questbook-spine { display: none; } }

.questbook-page-inner { position: relative; z-index: 1; }
.questbook-heading {
    margin: 0 0 18px; color: #5a3f14; font-size: 1.5rem;
    border-bottom: 2px solid rgba(120, 85, 30, 0.28); padding-bottom: 10px;
}

.questbook-entry {
    border-bottom: 1px dashed rgba(120, 85, 30, 0.3);
    padding: 14px 0 16px; color: #3f2f14;
}
.questbook-entry:last-child { border-bottom: none; }
.questbook-entry-head { display: flex; align-items: center; gap: 10px; }
.questbook-entry h3 { margin: 0; color: #43310f; font-size: 1.2rem; }
.questbook-entry p { margin: 6px 0 8px; color: #5a4522; line-height: 1.6; }
.questbook-entry.is-active { background: rgba(255, 212, 110, 0.22); border-radius: 10px; padding: 14px 14px 16px; }
.quest-active-badge { background: #b9852a; color: #fff6df; }

.questbook-objectives { margin: 6px 0 0; padding-left: 20px; }
.questbook-objectives li { color: #5a4522; margin-bottom: 4px; line-height: 1.5; }

.questbook-entry.is-completed h3 { text-decoration: line-through; text-decoration-color: rgba(120,85,30,0.5); }
.questbook-stamp {
    margin-left: auto; transform: rotate(-8deg);
    border: 2px solid #9c3b2f; color: #9c3b2f;
    padding: 2px 10px; border-radius: 6px; font-weight: 800;
    font-size: 0.78rem; letter-spacing: 0.08em; opacity: 0.8;
}
.questbook-meta { color: #6b5228 !important; margin-top: 8px; }
.questbook-empty { color: #6b5228; font-style: italic; padding: 24px 0; }

.questbook-switch-form { margin-top: 10px; }
.questbook-switch {
    background: rgba(90, 63, 20, 0.14); color: #5a3f14;
    border: 1px solid rgba(120, 85, 30, 0.5);
}
.questbook-switch:hover { background: rgba(90, 63, 20, 0.24); }

.questbook-leader-note { text-align: center; color: var(--muted); margin-top: 14px; }

/* page-turn animation when switching tabs */
@keyframes qb-page-turn {
    0%   { opacity: 0; transform: rotateY(-12deg) translateX(-14px); transform-origin: left center; }
    100% { opacity: 1; transform: rotateY(0) translateX(0); }
}
.questbook-page.page-turn { animation: qb-page-turn .28s ease; }
@media (prefers-reduced-motion: reduce) { .questbook-page.page-turn { animation: none; } }

/* A token the DM has marked "Invisible to players": the DM sees it dimmed
   with a dashed outline so it's clearly hidden, while its light still shows.
   Players never receive the drawn element at all. */
.token.token-hidden-from-players {
    opacity: 0.5;
    border-style: dashed !important;
    border-color: rgba(123, 220, 255, 0.85) !important;
}
.token.token-hidden-from-players::before {
    content: "\1F441";           /* eye glyph */
    position: absolute;
    top: -8px; right: -8px;
    font-size: 12px;
    opacity: 0.85;
    filter: grayscale(1);
    pointer-events: none;
}

/* ---- Quest Book: click-to-open accordion entries (v0.9.77) ---- */
.questbook-entry { display: block; }
/* summary is the always-visible closed row: just the title + badge */
.questbook-entry > summary.questbook-entry-head {
    display: flex; align-items: center; gap: 10px;
    cursor: pointer; list-style: none; padding: 4px 0;
}
.questbook-entry > summary.questbook-entry-head::-webkit-details-marker { display: none; }
.questbook-entry > summary:focus-visible { outline: 2px solid #b9852a; outline-offset: 3px; border-radius: 6px; }
.questbook-caret {
    color: #9a6b1e; font-size: 0.8rem; transition: transform .18s ease;
    flex: 0 0 auto; line-height: 1;
}
.questbook-entry[open] > summary .questbook-caret { transform: rotate(90deg); }
/* the expanding content */
.questbook-entry-body { padding: 6px 0 4px 22px; }
.questbook-entry-body p:first-child { margin-top: 8px; }
@media (prefers-reduced-motion: reduce) { .questbook-caret { transition: none; } }

.questbook-header-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.questbook-create-button {
    background: rgba(255, 212, 110, 0.2) !important;
    border-color: var(--gold) !important;
    color: var(--text) !important; font-weight: 700;
}

/* ---- Store item editor: compact "balloon" accordion (v0.9.79) ---- */
.store-item-balloon {
    border: 1px solid var(--border);
    border-radius: 12px;
    background: rgba(0,0,0,0.18);
    margin-bottom: 8px;
    overflow: hidden;
}
.store-item-balloon > summary.store-item-balloon-summary {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 12px; cursor: pointer; list-style: none;
}
.store-item-balloon > summary::-webkit-details-marker { display: none; }
.store-item-balloon > summary:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
.store-item-caret { color: var(--gold); font-size: 0.8rem; transition: transform .18s ease; flex: 0 0 auto; }
.store-item-balloon[open] > summary .store-item-caret { transform: rotate(90deg); }
.store-item-balloon-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.store-item-balloon-meta { color: var(--muted); font-size: 0.85rem; flex: 0 0 auto; }
.store-item-balloon-body { padding: 4px 12px 12px; }
.store-item-balloon .small-danger { flex: 0 0 auto; padding: 4px 10px; font-size: 0.78rem; }
@media (prefers-reduced-motion: reduce) { .store-item-caret { transition: none; } }

/* ---- Quest Book: remove completed quest button ---- */
.questbook-delete-form { margin-top: 10px; }
.questbook-delete {
    background: rgba(156, 59, 47, 0.18); color: #9c3b2f;
    border: 1px solid rgba(156, 59, 47, 0.6); font-size: 0.85rem;
}
.questbook-delete:hover { background: rgba(156, 59, 47, 0.3); }

/* ---- Databases: flash a freshly-copied custom entry ---- */
@keyframes db-entry-flash {
    0%, 100% { box-shadow: 0 0 0 0 rgba(255, 212, 110, 0); }
    30% { box-shadow: 0 0 0 3px rgba(255, 212, 110, 0.65); }
}
.database-entry-flash { animation: db-entry-flash 1.6s ease 2; border-radius: 10px; }

/* =======================================================================
   DATABASES PAGE — "Keeper's Index" makeover (v0.9.86)
   All colors come from theme variables so it restyles with every theme.
   ===================================================================== */
.db-page { max-width: 1180px; margin: 0 auto; padding-bottom: 40px; }

/* --- header --- */
.db-header {
    display: flex; justify-content: space-between; align-items: flex-end;
    gap: 20px; flex-wrap: wrap; margin-bottom: 22px;
}
.db-eyebrow {
    display: inline-block; font-size: 0.72rem; letter-spacing: 0.22em;
    text-transform: uppercase; color: var(--accent, var(--gold));
    font-weight: 700; margin-bottom: 4px;
}
.db-header h1 { margin: 0; font-size: 2rem; line-height: 1.1; }
.db-sub { color: var(--muted); margin: 6px 0 0; max-width: 52ch; }
.db-header-actions { display: flex; gap: 10px; align-items: center; }

.db-add-button {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 11px 20px; border-radius: 12px; font-weight: 700; cursor: pointer;
    background: var(--control-bg, linear-gradient(180deg, #ffe28a, #ffbd4d));
    color: var(--control-text, #21132f);
    border: 1px solid var(--gold);
    box-shadow: 0 6px 18px color-mix(in srgb, var(--accent, #ffd46e) 22%, transparent);
    transition: transform .12s, box-shadow .12s;
}
.db-add-button:hover { transform: translateY(-1px); box-shadow: 0 10px 26px color-mix(in srgb, var(--accent, #ffd46e) 34%, transparent); }
.db-add-plus { font-size: 1.2rem; line-height: 1; }
.db-ghost {
    padding: 10px 16px; border-radius: 12px; font-weight: 600; cursor: pointer;
    background: transparent; color: var(--text);
    border: 1px solid var(--border); transition: border-color .12s, background .12s;
}
.db-ghost:hover { border-color: var(--gold); background: color-mix(in srgb, var(--panel) 60%, transparent); }

/* --- type rail --- */
.db-rail {
    display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 24px;
    padding-bottom: 16px; border-bottom: 1px solid var(--border);
}
.db-rail-tab {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 9px 15px; border-radius: 999px; cursor: pointer;
    background: color-mix(in srgb, var(--panel) 70%, transparent);
    border: 1px solid var(--border); color: var(--muted);
    font-weight: 600; transition: color .12s, border-color .12s, background .12s;
}
.db-rail-tab:hover { color: var(--text); border-color: var(--gold); }
.db-rail-tab.is-active {
    color: var(--control-text, #21132f);
    background: var(--control-bg, linear-gradient(180deg, #ffe28a, #ffbd4d));
    border-color: var(--gold);
}
.db-rail-icon { font-size: 1.05rem; }
.db-rail-count {
    min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px;
    display: inline-grid; place-items: center; font-size: 0.72rem; font-weight: 800;
    background: color-mix(in srgb, var(--bg) 55%, transparent);
}
.db-rail-tab.is-active .db-rail-count { background: color-mix(in srgb, var(--control-text, #21132f) 16%, transparent); }

/* --- library head --- */
.db-library-head { margin-bottom: 18px; }
.db-library-head h2 { margin: 0; font-size: 1.5rem; }
.db-library-blurb { color: var(--muted); margin: 4px 0 0; }
.db-section-label {
    font-size: 0.82rem; letter-spacing: 0.12em; text-transform: uppercase;
    color: var(--muted); margin: 26px 0 12px; display: flex; align-items: center; gap: 8px;
}
.db-pill {
    min-width: 22px; height: 20px; padding: 0 7px; border-radius: 999px;
    display: inline-grid; place-items: center; font-size: 0.72rem; font-weight: 800;
    background: color-mix(in srgb, var(--accent, var(--gold)) 20%, transparent);
    color: var(--gold); letter-spacing: 0;
}

/* --- entry cards --- */
.db-card-grid {
    display: grid; gap: 14px;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
.db-card {
    position: relative; display: flex; flex-direction: column; gap: 8px;
    padding: 16px; border-radius: 16px;
    background: linear-gradient(180deg, var(--panel2), var(--panel));
    border: 1px solid var(--border);
    box-shadow: var(--shadow);
}
.db-card-top { display: flex; justify-content: space-between; gap: 10px; align-items: flex-start; }
.db-card-thumb {
    width: 100%; height: 120px; object-fit: cover; border-radius: 10px;
    border: 1px solid var(--border); margin: -4px 0 2px;
}
.db-card h4 { margin: 0; font-size: 1.1rem; line-height: 1.2; color: var(--gold); }
.db-card-tags { display: flex; flex-wrap: wrap; gap: 4px; justify-content: flex-end; }

/* --- Image field in the edit modal (Wildshape) --- */
.db-image-field { }
.db-image-preview-row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.db-image-preview {
    width: 96px; height: 96px; object-fit: cover; border-radius: 10px;
    border: 1px solid var(--border); flex: 0 0 auto;
}
.db-image-preview-empty {
    display: flex; align-items: center; justify-content: center;
    color: var(--muted); font-size: .74rem; text-align: center;
    background: rgba(0,0,0,0.2);
}
.db-image-controls { display: flex; flex-direction: column; gap: 8px; flex: 1; min-width: 180px; }
.db-image-controls input[type="file"] { font-size: .82rem; }
.db-tag {
    font-size: 0.66rem; font-weight: 700; padding: 2px 8px; border-radius: 999px;
    background: color-mix(in srgb, var(--panel) 40%, transparent);
    border: 1px solid var(--border); color: var(--muted); white-space: nowrap;
}
.db-tag-rarity { color: var(--gold); border-color: color-mix(in srgb, var(--gold) 50%, transparent); }
.db-tag-heal { color: var(--green, #6dffb5); border-color: color-mix(in srgb, var(--green, #6dffb5) 50%, transparent); }
.db-tag-light { color: var(--blue, #7bdcff); border-color: color-mix(in srgb, var(--blue, #7bdcff) 50%, transparent); }
.db-card-stat {
    margin: 0; font-size: 0.9rem; display: flex; gap: 8px; align-items: baseline;
}
.db-card-stat span {
    font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.08em;
    color: var(--muted); min-width: 96px; flex: 0 0 auto;
}
.db-card-desc { margin: 4px 0 0; color: var(--muted); font-size: 0.86rem; line-height: 1.45; }
.db-card-actions { margin-top: auto; padding-top: 10px; display: flex; gap: 8px; }
.db-card-edit {
    flex: 1; padding: 8px; border-radius: 10px; cursor: pointer; font-weight: 600;
    background: color-mix(in srgb, var(--accent, var(--gold)) 16%, transparent);
    border: 1px solid color-mix(in srgb, var(--gold) 45%, transparent); color: var(--text);
}
.db-card-edit:hover { border-color: var(--gold); }
.db-card-delete {
    padding: 8px 12px; border-radius: 10px; cursor: pointer;
    background: color-mix(in srgb, var(--danger, #ff6376) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--danger, #ff6376) 45%, transparent);
    color: var(--danger, #ff6376); font-weight: 600;
}
.db-card-delete:hover { background: color-mix(in srgb, var(--danger, #ff6376) 26%, transparent); }
.db-inline { display: inline; margin: 0; }

.db-card-builtin { opacity: 0.92; }
.db-card-builtin h4 { color: var(--text); }
.db-card-builtin .db-card-actions { padding-top: 10px; }
.db-card-view {
    flex: 1; padding: 8px; border-radius: 10px; cursor: pointer; font-weight: 600;
    background: transparent; border: 1px solid var(--border); color: var(--muted);
}
.db-card-view:hover { border-color: var(--gold); color: var(--text); }
.db-card-copy {
    flex: 1; padding: 8px; border-radius: 10px; cursor: pointer; font-weight: 600;
    background: transparent; border: 1px dashed var(--border); color: var(--muted);
}
.db-card-copy:hover { border-style: solid; border-color: var(--gold); color: var(--text); }

/* --- read-only "Open Item" view modal --- */
.db-view-modal { width: min(560px, 100%); }
.db-view-modal-body { padding: 20px 22px 26px; }
.db-view-desc { color: var(--text); line-height: 1.5; margin: 0 0 16px; }
.db-view-fields { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; }
.db-view-field {
    display: flex; flex-direction: column; gap: 3px; padding: 8px 12px;
    border: 1px solid var(--border); border-radius: 10px; background: color-mix(in srgb, var(--panel) 60%, transparent);
}
.db-view-field span { font-size: 0.72rem; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.db-view-field strong { color: var(--text); font-weight: 600; }

/* --- empty state --- */
.db-empty {
    grid-column: 1 / -1; text-align: center; padding: 40px 20px;
    border: 1px dashed var(--border); border-radius: 16px; color: var(--muted);
}
.db-empty-add {
    margin-top: 10px; padding: 9px 18px; border-radius: 10px; cursor: pointer; font-weight: 600;
    background: var(--control-bg, linear-gradient(180deg, #ffe28a, #ffbd4d));
    color: var(--control-text, #21132f); border: 1px solid var(--gold);
}

/* --- built-ins accordion --- */
.db-builtins { margin-top: 30px; border-top: 1px solid var(--border); padding-top: 16px; }
.db-builtins > summary {
    cursor: pointer; font-weight: 700; font-size: 1rem; list-style: none;
    display: flex; align-items: center; gap: 10px; color: var(--text);
}
.db-builtins > summary::-webkit-details-marker { display: none; }
.db-builtins > summary::before { content: "\25B8"; color: var(--gold); transition: transform .15s; }
.db-builtins[open] > summary::before { transform: rotate(90deg); }
.db-builtins .db-card-grid { margin-top: 14px; }
.db-hint { color: var(--muted); font-size: 0.85rem; margin: 8px 0; }

/* --- modal --- */
.db-modal-backdrop {
    position: fixed; inset: 0; z-index: 200;
    background: color-mix(in srgb, var(--bg) 78%, rgba(0,0,0,0.7));
    display: grid; place-items: start center; padding: 5vh 16px; overflow-y: auto;
}
.db-modal-backdrop[hidden] { display: none; }
.db-modal {
    width: min(720px, 100%);
    background: linear-gradient(180deg, var(--panel2), var(--panel));
    border: 1px solid var(--gold); border-radius: 20px;
    box-shadow: var(--shadow); overflow: hidden;
}
.db-modal-head {
    display: flex; justify-content: space-between; align-items: center;
    padding: 18px 22px; border-bottom: 1px solid var(--border);
}
.db-modal-head h2 { margin: 0; font-size: 1.3rem; }
.db-modal-close {
    background: none; border: none; color: var(--muted); font-size: 1.6rem;
    cursor: pointer; line-height: 1; padding: 0 4px;
}
.db-modal-close:hover { color: var(--text); }
.db-modal-step { padding: 22px; }
.db-modal-lead { margin: 0 0 16px; color: var(--muted); }

/* type picker */
.db-type-picker { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; }
.db-type-choice {
    display: flex; flex-direction: column; gap: 4px; text-align: left;
    padding: 16px; border-radius: 14px; cursor: pointer;
    background: color-mix(in srgb, var(--panel) 60%, transparent);
    border: 1px solid var(--border); color: var(--text); transition: border-color .12s, transform .12s;
}
.db-type-choice:hover { border-color: var(--gold); transform: translateY(-2px); }
.db-type-icon { font-size: 1.6rem; }
.db-type-choice strong { font-size: 1.05rem; }
.db-type-choice small { color: var(--muted); font-size: 0.8rem; line-height: 1.35; }

/* form built by JS */
.db-field-group { margin-bottom: 18px; }
.db-field-group-title {
    display: block; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.1em;
    color: var(--accent, var(--gold)); font-weight: 700; margin-bottom: 8px;
}
.db-field-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; }
.db-field { display: flex; flex-direction: column; gap: 5px; }
.db-field.db-field-wide { grid-column: 1 / -1; margin-bottom: 16px; }
.db-field label { font-size: 0.8rem; color: var(--muted); font-weight: 600; }
.db-field input, .db-field select, .db-field textarea {
    padding: 9px 11px; border-radius: 10px;
    background: var(--input-bg, rgba(0,0,0,0.3)); color: var(--text);
    border: 1px solid var(--border); font-size: 0.92rem;
}
.db-field textarea { min-height: 72px; resize: vertical; }
.db-field input:focus, .db-field select:focus, .db-field textarea:focus {
    outline: none; border-color: var(--gold);
}
.db-toggle-row { display: flex; flex-wrap: wrap; gap: 16px; margin: 4px 0 16px; }
.db-check { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; color: var(--text); font-size: 0.9rem; }
.db-check input { width: 17px; height: 17px; accent-color: var(--gold); }
.db-conditional {
    margin: 0 0 16px; padding: 14px; border-radius: 12px;
    background: color-mix(in srgb, var(--panel) 50%, transparent);
    border: 1px solid var(--border);
}
.db-modal-foot {
    display: flex; justify-content: flex-end; gap: 10px; margin-top: 8px;
    padding-top: 16px; border-top: 1px solid var(--border);
}

/* flash a freshly-copied entry */
@keyframes db-card-flash {
    0%, 100% { box-shadow: var(--shadow); }
    30% { box-shadow: 0 0 0 3px var(--gold); }
}
.db-card.db-flash { animation: db-card-flash 1.4s ease 2; }

.db-bestiary-grid {
    display: grid; gap: 14px;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
.db-bestiary-discovered {
    border-color: color-mix(in srgb, var(--gold) 50%, var(--border));
    background: linear-gradient(180deg, color-mix(in srgb, var(--gold) 6%, var(--panel2)), var(--panel));
}
.db-bestiary-toggle {
    margin-top: 4px; font-size: 0.82rem; color: var(--muted);
}
.db-bestiary-discovered .db-bestiary-toggle {
    color: var(--gold); font-weight: 600;
}
.db-bestiary-full {
    margin: 8px 0; border-top: 1px solid var(--border); padding-top: 8px;
}
.db-bestiary-full summary {
    cursor: pointer; color: var(--gold); font-size: 0.82rem; font-weight: 600;
    list-style: none; display: flex; align-items: center; gap: 4px;
}
.db-bestiary-full summary::-webkit-details-marker { display: none; }
.db-bestiary-full summary::before { content: "\25b8"; transition: transform 0.15s; }
.db-bestiary-full[open] summary::before { transform: rotate(90deg); }
.db-bestiary-full summary:hover { color: #ffd98f; }
.db-bestiary-statline {
    font-size: 0.82rem; color: var(--text); margin: 6px 0; line-height: 1.5;
}
.db-bestiary-statline strong { color: var(--gold); margin-right: 4px; }
.db-bestiary-full .db-card-edit {
    margin-top: 8px;
}
.bestiary-page-line {
    margin: 2px 0 0; font-size: 0.86rem; color: var(--text); line-height: 1.4;
}
.bestiary-page-line span {
    font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--muted); display: block; margin-bottom: 1px;
}
.bestiary-page-empty {
    text-align: center; padding: 60px 20px; color: var(--muted);
}
.bestiary-page-empty p:first-child {
    font-size: 1.1rem; color: var(--text); margin-bottom: 6px;
}

/* ============ Manual page (chapter book, like the Bestiary) ============ */
.manual-book { margin-top: 18px; max-width: 900px; }
.manual-empty { text-align: center; padding: 40px 20px; color: var(--muted); }

.manual-toc-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 12px;
}
.manual-toc-card {
    display: flex; flex-direction: column; align-items: center; gap: 6px;
    padding: 22px 16px;
    border: 1px solid var(--border); border-radius: 12px;
    background: linear-gradient(180deg, var(--panel2), var(--panel));
    cursor: pointer; text-align: center;
}
.manual-toc-card:hover { border-color: var(--gold); background: color-mix(in srgb, var(--gold) 6%, var(--panel2)); }
.manual-toc-icon { font-size: 2rem; }
.manual-toc-name {
    font-family: var(--display-font, Georgia, serif); color: var(--gold); font-size: 1.02rem;
}
.manual-toc-count { font-size: .74rem; color: var(--muted); }

.manual-chapter-nav {
    display: flex; align-items: center; gap: 14px; margin-bottom: 14px;
}
.manual-chapter-nav button {
    background: none; border: 1px solid var(--border); color: var(--muted);
    padding: 6px 12px; border-radius: 8px; cursor: pointer; font-size: .82rem;
}
.manual-chapter-nav button:hover { border-color: var(--gold); color: var(--text); }
.manual-chapter-title {
    margin: 0; font-family: var(--display-font, Georgia, serif); color: var(--gold); font-size: 1.25rem;
}

.manual-topics { display: grid; gap: 6px; }
.manual-topic {
    padding: 10px 14px; border: 1px solid var(--border); border-radius: 10px;
    background: rgba(0,0,0,0.15);
}
.manual-topic summary {
    cursor: pointer; font-weight: 700; color: var(--text); font-size: .92rem;
}
.manual-topic[open] summary { color: var(--gold); margin-bottom: 6px; }
.manual-topic p { margin: 0; color: var(--muted); font-size: .86rem; line-height: 1.5; }

/* ============ Bestiary: book UI ============ */
.bestiary-book-page { max-width: 1100px; }
.bestiary-book { margin-top: 18px; perspective: 1800px; }

.bestiary-cover {
    display: flex; justify-content: center;
}
.bestiary-cover-inner {
    width: min(700px, 100%);
    padding: 34px 38px 30px;
    border-radius: 10px;
    border: 1px solid var(--border);
    background:
        linear-gradient(160deg, color-mix(in srgb, var(--gold) 7%, transparent), transparent 55%),
        linear-gradient(180deg, var(--panel2), var(--panel));
    box-shadow: var(--shadow), inset 0 0 0 6px color-mix(in srgb, var(--gold) 10%, transparent);
}
.bestiary-cover-title {
    margin: 0 0 18px; text-align: center;
    font-family: var(--display-font, Georgia, serif);
    color: var(--gold); letter-spacing: .04em;
    padding-bottom: 12px; border-bottom: 1px solid var(--border);
}
.bestiary-toc-list { display: grid; gap: 8px; }
.bestiary-toc-row {
    display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
    padding: 11px 14px;
    border: 1px solid transparent; border-bottom: 1px dotted var(--border);
    border-radius: 8px;
    background: transparent; cursor: pointer; text-align: left;
    font-family: var(--display-font, Georgia, serif); font-size: 1.02rem; color: var(--text);
}
.bestiary-toc-row:hover { border-color: var(--gold); background: color-mix(in srgb, var(--gold) 6%, transparent); }
.bestiary-toc-name::after {
    content: ""; display: inline-block; width: 100%;
}
.bestiary-toc-progress {
    flex: 0 0 auto; font-family: system-ui, sans-serif; font-size: .78rem;
    color: var(--gold); white-space: nowrap;
}
.bestiary-toc-progress-empty { color: var(--muted); }

.bestiary-chapter-nav {
    display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
    margin-bottom: 14px;
}
.bestiary-toc-back {
    background: none; border: 1px solid var(--border); color: var(--muted);
    padding: 6px 12px; border-radius: 8px; cursor: pointer; font-size: .82rem;
}
.bestiary-toc-back:hover { border-color: var(--gold); color: var(--text); }
.bestiary-chapter-title {
    margin: 0; font-family: var(--display-font, Georgia, serif); color: var(--gold);
    font-size: 1.3rem; text-align: center; flex: 1;
}
.bestiary-chapter-progress { font-size: .8rem; color: var(--muted); white-space: nowrap; }

.bestiary-spread {
    display: grid; grid-template-columns: 1fr auto 1fr;
    align-items: stretch; gap: 0;
    min-height: 360px;
    border-radius: 6px;
    box-shadow: var(--shadow);
    transition: opacity .18s ease, transform .18s ease;
}
.bestiary-spread-turn-active.bestiary-spread-turn-next { animation: bestiary-turn-next .38s ease; }
.bestiary-spread-turn-active.bestiary-spread-turn-prev { animation: bestiary-turn-prev .38s ease; }
@keyframes bestiary-turn-next {
    0% { opacity: 0; transform: rotateY(-6deg) translateX(14px); }
    100% { opacity: 1; transform: none; }
}
@keyframes bestiary-turn-prev {
    0% { opacity: 0; transform: rotateY(6deg) translateX(-14px); }
    100% { opacity: 1; transform: none; }
}

.bestiary-spine {
    width: 14px;
    background:
        linear-gradient(90deg, rgba(0,0,0,.32), rgba(0,0,0,.05) 30%, rgba(0,0,0,.05) 70%, rgba(0,0,0,.32)),
        color-mix(in srgb, var(--gold) 10%, var(--panel2));
    box-shadow: inset 0 0 12px rgba(0,0,0,.4);
}

.bestiary-page {
    position: relative;
    padding: 26px 26px 40px;
    background:
        radial-gradient(circle at 15% 8%, color-mix(in srgb, var(--gold) 5%, transparent), transparent 40%),
        var(--panel2);
    border: 1px solid var(--border);
    display: flex; flex-direction: column; min-width: 0;
}
.bestiary-spread > .bestiary-page:first-child { border-radius: 6px 0 0 6px; border-right: none; }
.bestiary-spread > .bestiary-page:last-child { border-radius: 0 6px 6px 0; border-left: none; }
.bestiary-page-blank { background: var(--panel2); }

.bestiary-page-head {
    display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
    padding-bottom: 8px; margin-bottom: 8px; border-bottom: 1px solid var(--border);
}
.bestiary-page-head h3 {
    margin: 0; font-family: var(--display-font, Georgia, serif); color: var(--gold); font-size: 1.15rem;
}
.bestiary-page-cr { font-size: .74rem; color: var(--muted); white-space: nowrap; }
.bestiary-page-plate {
    display: flex; align-items: center; justify-content: center;
    width: 92px; height: 92px; margin: 4px auto 12px;
    border-radius: 50%;
    border: 2px solid color-mix(in srgb, var(--gold) 40%, var(--border));
    background: radial-gradient(circle at 30% 25%, color-mix(in srgb, var(--gold) 12%, transparent), rgba(0,0,0,0.25));
    overflow: hidden; flex: 0 0 auto;
}
.bestiary-page-plate img { width: 100%; height: 100%; object-fit: contain; padding: 6px; }
.bestiary-page-plate-glyph { font-size: 2.4rem; line-height: 1; }
.bestiary-page-desc { margin: 0 0 10px; color: var(--text); font-size: .9rem; line-height: 1.5; }
.bestiary-page-number {
    position: absolute; bottom: 12px; left: 0; right: 0; text-align: center;
    margin: 0; font-size: .72rem; color: var(--muted);
}

.bestiary-mystery-mark {
    flex: 1; display: flex; align-items: center; justify-content: center;
    font-family: var(--display-font, Georgia, serif);
    font-size: 4.2rem; color: color-mix(in srgb, var(--muted) 70%, transparent);
    text-shadow: 0 0 18px color-mix(in srgb, var(--gold) 20%, transparent);
}
.bestiary-mystery-caption {
    margin: 0; text-align: center; color: var(--muted); font-size: .82rem; font-style: italic;
}

.bestiary-page-controls {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    margin-top: 14px;
}
.bestiary-page-controls button {
    padding: 8px 16px; border-radius: 8px; border: 1px solid var(--border);
    background: var(--panel2); color: var(--text); cursor: pointer; font-size: .86rem;
}
.bestiary-page-controls button:hover:not(:disabled) { border-color: var(--gold); color: var(--gold); }
.bestiary-page-controls button:disabled { opacity: .35; cursor: default; }
.bestiary-page-indicator { font-size: .78rem; color: var(--muted); }

@media (max-width: 720px) {
    .bestiary-spread { grid-template-columns: 1fr; }
    .bestiary-spine { display: none; }
    .bestiary-spread > .bestiary-page:first-child,
    .bestiary-spread > .bestiary-page:last-child { border-radius: 6px; border: 1px solid var(--border); margin-bottom: 10px; }
}

@media (max-width: 640px) {
    .db-header { align-items: flex-start; }
    .db-card-grid { grid-template-columns: 1fr; }
}

/* Loot gold: DM editor input + player take-gold row (v0.9.88) */
.token-loot-gold-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.token-loot-gold-row input { width: 120px; padding: 8px 10px; border-radius: 10px; background: var(--input-bg, rgba(0,0,0,0.3)); color: var(--text); border: 1px solid var(--border); }
.loot-gold-row {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 12px 16px; margin-bottom: 14px; border-radius: 12px;
    background: color-mix(in srgb, var(--gold) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--gold) 45%, transparent);
}
.loot-gold-amount { font-weight: 800; font-size: 1.1rem; color: var(--gold); }
.loot-gold-row button {
    padding: 8px 18px; border-radius: 10px; cursor: pointer; font-weight: 700;
    background: var(--control-bg, linear-gradient(180deg, #ffe28a, #ffbd4d));
    color: var(--control-text, #21132f); border: 1px solid var(--gold);
}

/* =======================================================================
   PERFORMANCE: reduce continuous repaints on low-power clients (v0.9.92)
   Weather and the whole-screen ambient effects are the heaviest recurring
   GPU cost. Under prefers-reduced-motion they're turned off entirely. The
   decorative token condition-FX also stop animating (the icons still show).
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {
    .weather-rain, .weather-snow, .weather-fog, .weather-storm,
    .rain-drop, .snow-flake { animation: none !important; }
    .cfx-aura, .cfx-bubble, .cfx-heart, .cfx-zzz, .cfx-orbit, .cfx-star,
    .cfx-spark, .cfx-grip, .token-frightened .token-face, .cfx-sweat,
    .cfx-dust, .cfx-mute, .cfx-invis, .light-glow-rect, .unseen-fog {
        animation: none !important;
    }
    html[data-theme="tavern"] body::before { animation: none !important; }
}

/* Library token properties editor (right-click a My Tokens icon) v0.9.103 */
.library-token-editor {
    position: fixed; z-index: 400; width: 280px;
    background: linear-gradient(180deg, var(--panel2), var(--panel));
    border: 1px solid var(--gold); border-radius: 14px;
    box-shadow: var(--shadow); padding: 14px; color: var(--text);
    display: flex; flex-direction: column; gap: 10px;
}
.lte-head { display: flex; justify-content: space-between; align-items: center; }
.lte-close { background: none; border: none; color: var(--muted); font-size: 1.3rem; cursor: pointer; line-height: 1; }
.lte-close:hover { color: var(--text); }
.lte-field { display: flex; flex-direction: column; gap: 4px; font-size: 0.82rem; color: var(--muted); }
.lte-field input, .lte-field select {
    padding: 8px 10px; border-radius: 9px; background: var(--input-bg, rgba(0,0,0,0.3));
    color: var(--text); border: 1px solid var(--border); font-size: 0.9rem;
}
.lte-field input[type="color"] { height: 38px; padding: 3px; cursor: pointer; }
.lte-hint { font-size: 0.76rem; color: var(--muted); line-height: 1.4; margin: 0; }
.lte-check { display: flex; align-items: center; gap: 8px; font-size: 0.86rem; cursor: pointer; }
.lte-check input { width: 16px; height: 16px; accent-color: var(--gold); }
.lte-foot { display: flex; justify-content: flex-end; }
.lte-save {
    padding: 8px 20px; border-radius: 10px; cursor: pointer; font-weight: 700;
    background: var(--control-bg, linear-gradient(180deg, #ffe28a, #ffbd4d));
    color: var(--control-text, #21132f); border: 1px solid var(--gold);
}

/* Map manager: download button + import tile (v0.9.112) */
.map-tile-actions { margin-top: 8px; display: flex; justify-content: center; gap: 6px; flex-wrap: wrap; }
.map-tile-actions button {
    padding: 5px 12px; border-radius: 8px; cursor: pointer; font-size: 0.8rem;
    background: var(--control-bg, rgba(255,190,74,0.15)); color: var(--gold, #e0a13c);
    border: 1px solid var(--border, #5a4632);
}
.map-tile-actions button:hover { background: var(--gold, #e0a13c); color: var(--bg, #1a120b); }
.import-map-tile .selector-folder-icon { color: var(--gold, #e0a13c); }

/* Token search popup + enemy statblock fields (v0.9.113) */
.token-source-search {
    padding: 4px 10px; border-radius: 8px; cursor: pointer; font-size: 0.82rem; white-space: nowrap;
    background: var(--control-bg, rgba(255,190,74,0.12)); color: var(--gold, #e0a13c);
    border: 1px solid var(--border, #5a4632);
}
.token-source-search:hover { background: var(--gold, #e0a13c); color: var(--bg, #1a120b); }
.token-search-popup-overlay {
    position: fixed; inset: 0; z-index: 500; background: rgba(0,0,0,0.55);
    display: flex; align-items: center; justify-content: center;
}
.token-search-popup {
    width: min(880px, 92vw); max-height: 86vh; display: flex; flex-direction: column;
    background: linear-gradient(180deg, var(--panel2), var(--panel));
    border: 1px solid var(--gold); border-radius: 16px; box-shadow: var(--shadow);
    padding: 18px; color: var(--text);
}
.tsp-head { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.tsp-head strong { font-size: 1.05rem; }
.tsp-head #tsp-search { flex: 1; padding: 9px 12px; border-radius: 10px; background: var(--input-bg, rgba(0,0,0,0.3)); color: var(--text); border: 1px solid var(--border); font-size: 0.95rem; }
.tsp-head #tsp-cat { padding: 9px 10px; border-radius: 10px; background: var(--input-bg, rgba(0,0,0,0.3)); color: var(--text); border: 1px solid var(--border); }
.tsp-close { background: none; border: none; color: var(--muted); font-size: 1.5rem; cursor: pointer; line-height: 1; }
.tsp-close:hover { color: var(--text); }
.tsp-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 12px;
    overflow-y: auto; padding: 4px; flex: 1;
}
.tsp-chip {
    display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 12px 8px;
    background: var(--panel2, rgba(0,0,0,0.2)); border: 1px solid var(--border); border-radius: 12px;
    cursor: pointer; color: var(--text);
}
.tsp-chip:hover { border-color: var(--gold); background: color-mix(in srgb, var(--gold) 12%, transparent); }
.tsp-glyph { width: 56px; height: 56px; border-radius: 50%; display: flex; align-items: center; justify-content: center; overflow: hidden; font-weight: 700; }
.tsp-glyph img { width: 100%; height: 100%; object-fit: cover; }
.tsp-name { font-size: 0.85rem; text-align: center; }
.tsp-cat-tag { font-size: 0.68rem; color: var(--muted); text-transform: capitalize; }
.tsp-hint { color: var(--muted); font-size: 0.8rem; margin: 10px 0 0; text-align: center; }
.lte-statblock { display: flex; gap: 8px; }
.lte-statblock .lte-field { flex: 1; }
.lte-delete {
    padding: 8px 16px; border-radius: 10px; cursor: pointer; font-weight: 600; margin-right: auto;
    background: rgba(180,60,50,0.18); color: #ff9a8a; border: 1px solid rgba(180,60,50,0.5);
}
.lte-delete:hover { background: rgba(180,60,50,0.35); }
.token-statblock-tag { font-size: 0.66rem; color: var(--muted); display: block; }

/* ===== Combat radial action menu (v0.9.119 fixed-position controls) ===== */
/* Registered so the hover "nudge" (see --cr-hover-push below) is a real,
   animatable length rather than an inert custom property. */
@property --cr-hover-push {
    syntax: "<length>";
    inherits: false;
    initial-value: 0px;
}
.combat-radial {
    position: fixed;
    inset: 0;
    z-index: 480;
    pointer-events: auto;
    background: rgba(0,0,0,.08);
}
.cr-stage {
    --cr-radius: 176px;
    position: fixed;
    width: 0;
    height: 0;
    filter: drop-shadow(0 18px 30px rgba(0,0,0,.48));
}
.cr-wheel-ring {
    position: absolute;
    left: 50%; top: 50%;
    width: calc(var(--cr-radius) * 2.03);
    height: calc(var(--cr-radius) * 2.03);
    transform: translate(-50%,-50%);
    border-radius: 50%;
    border: 2px solid color-mix(in srgb,var(--gold) 72%,transparent);
    box-shadow: 0 0 0 9px color-mix(in srgb,var(--gold) 8%,transparent), inset 0 0 55px rgba(0,0,0,.44), 0 0 45px color-mix(in srgb,var(--gold) 20%,transparent);
    background: radial-gradient(circle, transparent 38%, color-mix(in srgb,var(--panel) 76%,transparent) 39% 57%, transparent 58%);
    pointer-events: none;
}
.cr-orbit { position: absolute; inset: 0; }
.cr-action-node {
    --cr-hover-push: 0px;
    --cr-node-position:
        translate(-50%,-50%)
        rotate(var(--cr-angle))
        translateY(calc((var(--cr-radius) + var(--cr-hover-push)) * -1))
        rotate(calc(var(--cr-angle) * -1));
    position: absolute;
    left: 0; top: 0;
    width: clamp(86px, 8vw, 124px);
    min-height: 58px;
    transform: var(--cr-node-position);
    display: grid;
    grid-template-columns: 30px 1fr;
    align-items: center;
    gap: 7px;
    padding: 8px 10px;
    border-radius: 15px;
    border: 1px solid color-mix(in srgb,var(--gold) 60%,var(--border));
    background: linear-gradient(180deg,color-mix(in srgb,var(--panel2) 94%,transparent),color-mix(in srgb,var(--panel) 96%,transparent));
    color: var(--text);
    cursor: pointer;
    text-align: left;
    box-shadow: 0 8px 18px rgba(0,0,0,.42);
    transition: none;
    touch-action: manipulation;
}
/* The global button:hover rule applies translateY(-1px). On an orbit
   button that replaced the complete radial transform, making the option jump
   into the hub before mouseup and preventing the click from firing. Keep the
   orbit transform unchanged in every interactive state. */
button.cr-action-node,
button.cr-action-node:hover,
button.cr-action-node:focus,
button.cr-action-node:focus-visible,
button.cr-action-node:active {
    transform: var(--cr-node-position) !important;
    translate: none !important;
    rotate: none !important;
    scale: none !important;
    animation: none !important;
    outline: none;
}
/* A gentle outward drift on hover so each spoke feels like a physical token
   you can nudge - kept small (10px) so the cursor stays on the button, and
   only the outward distance changes, never the transform's shape, so the
   pointerdown click still fires reliably.

   --cr-hover-push MUST be registered with @property as a real <length>, or
   changing it on :hover does nothing: plain (unregistered) custom properties
   don't trigger transitions and don't reliably re-resolve a transform that
   nests them. Registering it makes the value typed and animatable, so we
   transition the VARIABLE itself and the transform re-resolves each frame. */
button.cr-action-node {
    transition: transform .16s ease, --cr-hover-push .16s ease, border-color .16s ease, box-shadow .16s ease, background .16s ease !important;
}
/* Set the FULL transform explicitly on hover (push baked in) rather than only
   flipping a variable. A change to the transform's declared value transitions
   reliably in every browser, so the outward drift works even where @property
   isn't supported. The shape/angle are identical to the rest transform - only
   the outward distance grows - so the pointerdown click still fires. */
button.cr-action-node:hover,
button.cr-action-node:focus-visible {
    --cr-hover-push: 10px !important;
    transform:
        translate(-50%,-50%)
        rotate(var(--cr-angle))
        translateY(calc((var(--cr-radius) + 10px) * -1))
        rotate(calc(var(--cr-angle) * -1)) !important;
}
button.cr-action-node:active {
    --cr-hover-push: 4px !important;
    transform:
        translate(-50%,-50%)
        rotate(var(--cr-angle))
        translateY(calc((var(--cr-radius) + 4px) * -1))
        rotate(calc(var(--cr-angle) * -1)) !important;
    transition: transform .05s ease !important;
}
button.cr-action-node:hover,
button.cr-action-node:focus-visible,
button.cr-action-node:active {
    border-color: var(--gold);
    background: linear-gradient(180deg,color-mix(in srgb,var(--gold) 24%,var(--panel2)),var(--panel));
    box-shadow: 0 10px 24px rgba(0,0,0,.52), 0 0 0 2px color-mix(in srgb,var(--gold) 22%,transparent);
}
/* Tabs, close and page buttons must also remain physically still under every
   theme. Theme styles may change their colour, but never their position. */
.combat-radial button:not(.cr-action-node),
.combat-radial button:not(.cr-action-node):hover,
.combat-radial button:not(.cr-action-node):focus,
.combat-radial button:not(.cr-action-node):focus-visible,
.combat-radial button:not(.cr-action-node):active {
    transform: none !important;
    translate: none !important;
    rotate: none !important;
    scale: none !important;
    animation: none !important;
    transition: none !important;
}
.cr-action-node.is-disabled { opacity: .5; cursor: default; }
.cr-node-icon {
    width: 30px; height: 30px;
    display: grid; place-items: center;
    border-radius: 50%;
    background: color-mix(in srgb,var(--gold) 17%,transparent);
    color: var(--gold);
    font-size: 1.05rem;
}
.cr-node-label { font-size: .78rem; font-weight: 800; line-height: 1.12; overflow-wrap: anywhere; }
.cr-hub {
    position: absolute;
    left: 0; top: 0;
    width: 210px;
    min-height: 170px;
    transform: translate(-50%,-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 15px 14px 12px;
    border-radius: 50%;
    border: 2px solid var(--gold);
    background: radial-gradient(circle at 45% 34%,color-mix(in srgb,var(--panel2) 96%,transparent),var(--panel) 73%);
    color: var(--text);
    box-shadow: inset 0 0 30px rgba(0,0,0,.5),0 0 24px color-mix(in srgb,var(--gold) 18%,transparent);
    text-align: center;
}
.cr-close { position: absolute; right: 24px; top: 15px; width: 26px; height: 26px; padding: 0; border-radius: 50%; border: 1px solid var(--border); background: transparent; color: var(--muted); cursor: pointer; }
.cr-name { max-width: 135px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--gold); }
.cr-econ { display: flex; gap: 6px; }
.cr-slot-summary {
    max-width: 178px;
    padding: 3px 7px;
    border-radius: 8px;
    background: color-mix(in srgb,var(--panel2) 80%,transparent);
    border: 1px solid color-mix(in srgb,var(--gold) 32%,var(--border));
    color: var(--gold);
    font-size: .62rem;
    font-weight: 750;
    line-height: 1.2;
}
.cr-slot-summary[hidden] { display: none; }
.cr-pip { font-size: .7rem; padding: 3px 8px; border-radius: 999px; background: color-mix(in srgb,var(--gold) 19%,transparent); color: var(--gold); }
.cr-pip.spent { opacity: .48; text-decoration: line-through; }
.cr-tabs { display: flex; gap: 4px; }
.cr-tab { padding: 5px 7px; border-radius: 8px; border: 1px solid var(--border); background: transparent; color: var(--muted); cursor: pointer; font-size: .69rem; }
.cr-tab.active { background: var(--accent); border-color: var(--gold); color: #1a1204; font-weight: 800; }
.cr-preview { display: flex; flex-direction: column; gap: 2px; max-width: 170px; min-height: 37px; }
.cr-preview strong { font-size: .76rem; }
.cr-preview small { color: var(--muted); font-size: .62rem; line-height: 1.25; max-height: 31px; overflow: hidden; }
.cr-page-controls { display: flex; align-items: center; gap: 8px; font-size: .68rem; color: var(--muted); }
.cr-page-controls button { width: 24px; height: 22px; padding: 0; border-radius: 7px; border: 1px solid var(--border); background: transparent; color: var(--text); cursor: pointer; }
.cr-page-controls button:disabled { opacity: .25; cursor: default; }
.token.combat-radial-origin::after {
    content: "";
    position: absolute;
    inset: -14px;
    border-radius: 50%;
    border: 3px solid var(--gold);
    box-shadow: 0 0 0 5px color-mix(in srgb,var(--gold) 18%,transparent),0 0 24px var(--gold);
    animation: cr-origin-pulse 1.15s ease-in-out infinite alternate;
    pointer-events: none;
    z-index: 10;
}
@keyframes cr-origin-pulse { from { transform: scale(.96); opacity: .68; } to { transform: scale(1.04); opacity: 1; } }
.cr-target-prompt {
    position: fixed; top: 14px; left: 50%; transform: translateX(-50%); z-index: 500;
    background: var(--gold); color: #1a1204; padding: 8px 18px; border-radius: 20px;
    font-weight: 800; font-size: .9rem; box-shadow: var(--shadow);
}
body.cr-targeting .token { cursor: crosshair !important; }
body.cr-targeting .token:hover { filter: brightness(1.15) drop-shadow(0 0 12px var(--gold)); }
.cr-result-toast {
    position: fixed;
    left: 50%; top: 84px;
    transform: translate(-50%,-14px);
    z-index: 520;
    min-width: 260px; max-width: min(560px,90vw);
    display: flex; flex-direction: column; gap: 3px;
    padding: 12px 18px;
    border-radius: 14px;
    border: 1px solid var(--gold);
    background: linear-gradient(180deg,var(--panel2),var(--panel));
    color: var(--text);
    box-shadow: var(--shadow);
    opacity: 0;
    transition: opacity .2s ease,transform .2s ease;
    pointer-events: none;
    text-align: center;
}
.cr-result-toast.show { opacity: 1; transform: translate(-50%,0); }
.cr-result-toast.is-hit strong { color: #83e28c; }
.cr-result-toast.is-miss strong { color: #ff9a8a; }
.cr-result-toast span { color: var(--muted); font-size: .82rem; }
.action-econ-pill { display: inline-flex; gap: 8px; background: color-mix(in srgb,var(--gold) 15%,transparent); }
.action-econ-pill .spent { opacity: .45; text-decoration: line-through; }
@media (max-width: 700px) {
    .cr-hub { width: 166px; min-height: 146px; padding: 12px 9px; }
    .cr-action-node { width: 88px; min-height: 50px; padding: 6px; grid-template-columns: 24px 1fr; }
    .cr-node-icon { width: 24px; height: 24px; font-size: .88rem; }
    .cr-node-label { font-size: .66rem; }
    .cr-preview { max-width: 135px; }
    .cr-preview small { display: none; }
}

/* Roll overlays live on the page rather than inside a token, so a live state
   redraw cannot remove them before the result lands. */
.dice-roll-anim.is-screen-fixed {
    position: fixed;
    transform: translateX(-50%);
    z-index: 530;
}


/* DM per-player combat-wheel classification */
.combat-bonus-editor {
    display: grid;
    gap: 4px;
    max-height: 230px;
    overflow: auto;
    padding: 7px;
    border: 1px solid var(--border);
    border-radius: 9px;
    background: color-mix(in srgb,var(--panel2) 72%,transparent);
}
.combat-bonus-choice { margin: 0; padding: 3px 2px; }
.combat-bonus-choice:has(input:disabled) { opacity: .7; }
.combat-auto-bonus {
    margin-left: auto;
    padding: 1px 5px;
    border-radius: 999px;
    color: var(--gold);
    background: color-mix(in srgb,var(--gold) 15%,transparent);
    font-size: .62rem;
    font-weight: 700;
}


/* v0.9.120: DM bonus-action editor moved to the token right-click menu. */
.dm-bonus-action-section .hint {
    margin: 0;
    font-size: .72rem;
    line-height: 1.35;
}
.archer-bonus-editor {
    max-height: 210px;
}
.archer-bonus-editor .combat-bonus-choice,
.lte-bonus-editor .combat-bonus-choice {
    display: flex;
    align-items: center;
    gap: 7px;
}
.dm-bonus-action-section > button {
    width: 100%;
}
.library-token-editor {
    width: min(340px, calc(100vw - 20px));
    max-height: calc(100vh - 20px);
    overflow-y: auto;
}
.lte-bonus-section {
    display: grid;
    gap: 7px;
    padding: 9px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: color-mix(in srgb,var(--panel2) 72%,transparent);
}
.lte-bonus-section > strong {
    color: var(--accent);
    font-size: .84rem;
}
.lte-bonus-editor {
    max-height: 220px;
}

/* v0.9.121 dungeon exploration controls */
.dungeon-settings-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
    margin-bottom: 10px;
}
.dungeon-setting-group {
    min-width: 0;
    margin: 0;
    padding: 9px 10px;
    border: 1px solid var(--border);
    border-radius: 10px;
}
.dungeon-setting-group legend {
    padding: 0 5px;
    color: var(--gold);
    font-weight: 800;
}
.dungeon-setting-group .checkbox-label {
    margin: 5px 0;
}
.dungeon-turn-current {
    display: grid;
    gap: 4px;
    margin-bottom: 9px;
}
.dungeon-turn-current strong { color: var(--gold); }
.dungeon-turn-order {
    display: grid;
    gap: 4px;
    margin: 8px 0 10px;
}
.dungeon-turn-order span {
    padding: 5px 7px;
    border: 1px solid transparent;
    border-radius: 8px;
    color: var(--muted);
}
.dungeon-turn-order span.active {
    border-color: var(--border);
    background: var(--panel2);
    color: var(--text);
    font-weight: 800;
}
@media (max-width: 680px) {
    .dungeon-settings-grid { grid-template-columns: 1fr; }
}

/* v0.9.121 — 1080p desktop density.
   Browser 90% zoom gave the desired amount of room, but applying CSS `zoom`
   to the board would also scale the coordinate system used by map dragging.
   Instead, compact the surrounding board/editor chrome by roughly 10%. */
@media (min-width: 1200px) {
    body.page-board .board-layout {
        grid-template-columns: minmax(0, 1fr) 306px;
        gap: 9px;
    }
    body.page-editor .editor-layout {
        grid-template-columns: 306px minmax(0, 1fr);
        gap: 9px;
    }
    body.page-board .board-shell,
    body.page-editor .board-shell,
    body.page-board .right-panel,
    body.page-editor .side-panel {
        padding: 9px;
    }
    body.page-board .board-action-buttons,
    body.page-board .board-toolbar,
    body.page-editor .board-toolbar {
        gap: 6px;
    }
    body.page-board .board-action-buttons button,
    body.page-board .board-action-buttons .button,
    body.page-board .board-toolbar button,
    body.page-board .board-toolbar .button,
    body.page-editor .board-toolbar button,
    body.page-editor .board-toolbar .button {
        padding: 7px 10px;
        font-size: 0.9rem;
        border-radius: 10px;
    }
    body.page-board .right-panel details,
    body.page-editor .side-panel details {
        padding: 9px;
        margin-bottom: 7px;
    }
    body.page-board .right-panel summary,
    body.page-editor .side-panel summary {
        font-size: 1rem;
    }
}


/* v0.9.125: World Map party-position marker */
.world-party-marker { position:absolute; transform:translate(-50%,-82%); z-index:24; pointer-events:none; display:flex; flex-direction:column; align-items:center; filter:drop-shadow(0 5px 5px rgba(0,0,0,.65)); }
.world-party-marker img { width:82px; height:98px; object-fit:contain; }
.world-party-marker span { margin-top:-15px; padding:2px 9px; border-radius:8px; border:2px solid #e0a02c; background:rgba(42,24,8,.94); color:#f5d38f; font:700 13px Georgia,serif; white-space:nowrap; box-shadow:0 2px 7px rgba(0,0,0,.5); }
.world-party-panel { display:grid; gap:5px; padding:4px 0 7px; }

/* v0.9.126 — board/editor 1080p workspace density.
   These selectors use :has() because the legacy page-board/page-editor body
   classes are not emitted by base.html. We shrink chrome, never the map layer,
   so token/grid coordinates stay unchanged. */
@media (min-width:1100px) {
    body:has(.board-layout) > .topbar,
    body:has(.editor-layout) > .topbar {
        gap:7px;
        padding:5px 8px;
    }
    body:has(.board-layout) > .topbar .brand,
    body:has(.editor-layout) > .topbar .brand { font-size:.95rem; }
    body:has(.board-layout) > .topbar .app-name,
    body:has(.editor-layout) > .topbar .app-name { font-size:1.12rem; }
    body:has(.board-layout) > .topbar nav,
    body:has(.editor-layout) > .topbar nav { gap:4px; }
    body:has(.board-layout) > .topbar a,
    body:has(.board-layout) > .topbar button,
    body:has(.editor-layout) > .topbar a,
    body:has(.editor-layout) > .topbar button {
        padding:6px 8px;
        border-radius:8px;
        font-size:.78rem;
        white-space:nowrap;
    }
    body:has(.board-layout) > .topbar .account-pill,
    body:has(.editor-layout) > .topbar .account-pill {
        padding:4px 7px;
        font-size:.72rem;
        white-space:nowrap;
    }

    body:has(.board-layout) main,
    body:has(.editor-layout) main { padding:5px 6px; }

    body:has(.board-layout) .board-layout {
        grid-template-columns:minmax(0,1fr) 286px;
        gap:6px;
        height:calc(100vh - 52px);
    }
    body:has(.editor-layout) .editor-layout {
        grid-template-columns:286px minmax(0,1fr);
        gap:6px;
        height:calc(100vh - 99px);
    }

    body:has(.board-layout) .board-shell,
    body:has(.editor-layout) .board-shell {
        padding:6px;
        gap:4px;
        border-radius:12px;
        min-height:0;
    }
    body:has(.board-layout) .right-panel,
    body:has(.editor-layout) .side-panel {
        padding:6px;
        border-radius:12px;
    }

    body:has(.board-layout) .board-top {
        margin:0 0 2px;
        gap:7px;
        align-items:center;
    }
    body:has(.board-layout) .board-top h1 { margin:0; font-size:1.35rem; }
    body:has(.board-layout) .board-top-heading { gap:1px; }
    body:has(.board-layout) .board-top-heading .hint { margin:0; font-size:.72rem; }
    body:has(.board-layout) .calendar-strip { gap:4px; }
    body:has(.board-layout) .calendar-pill { padding:3px 7px; font-size:.72rem; }
    body:has(.board-layout) .board-top-actions { gap:3px; }
    body:has(.board-layout) .board-action-buttons { gap:4px; }
    body:has(.board-layout) .board-action-buttons button,
    body:has(.board-layout) .board-action-buttons .button {
        padding:5px 7px;
        border-radius:8px;
        font-size:.72rem;
        min-height:29px;
    }
    body:has(.board-layout) .map-view-indicator { font-size:.62rem; gap:2px 8px; }

    body:has(.board-layout) .board-toolbar,
    body:has(.editor-layout) .board-toolbar { gap:4px; }
    body:has(.board-layout) .board-toolbar button,
    body:has(.board-layout) .board-toolbar .button,
    body:has(.editor-layout) .board-toolbar button,
    body:has(.editor-layout) .board-toolbar .button {
        padding:5px 7px;
        border-radius:8px;
        font-size:.72rem;
        min-height:29px;
    }

    body:has(.board-layout) .right-panel details,
    body:has(.editor-layout) .side-panel details {
        padding:6px;
        margin-bottom:5px;
        border-radius:10px;
    }
    body:has(.board-layout) .right-panel summary,
    body:has(.editor-layout) .side-panel summary { font-size:.86rem; }
    body:has(.board-layout) .panel-group-title { font-size:.67rem; margin:4px 2px; }

    body:has(.editor-layout) .page-title {
        margin:0 0 4px;
        gap:8px;
        min-height:0;
    }
    body:has(.editor-layout) .page-title h1 { margin:0; font-size:1.45rem; }
    body:has(.editor-layout) .page-title p { margin:1px 0 0; font-size:.72rem; }
    body:has(.editor-layout) .editor-header-actions { gap:4px; }
    body:has(.editor-layout) .editor-header-actions button,
    body:has(.editor-layout) .editor-header-actions .button {
        padding:5px 7px;
        border-radius:8px;
        font-size:.72rem;
    }
    body:has(.editor-layout) .editor-board .hint { margin:2px 0; font-size:.68rem; line-height:1.2; }
}

@media (min-width:1100px) and (max-height:950px) {
    body:has(.board-layout) .board-layout { height:calc(100vh - 48px); }
    body:has(.editor-layout) .editor-layout { height:calc(100vh - 90px); }
    body:has(.board-layout) .right-panel details,
    body:has(.editor-layout) .side-panel details { padding:5px; margin-bottom:4px; }
    body:has(.board-layout) .board-action-buttons button,
    body:has(.board-layout) .board-action-buttons .button,
    body:has(.board-layout) .board-toolbar button,
    body:has(.board-layout) .board-toolbar .button,
    body:has(.editor-layout) .board-toolbar button,
    body:has(.editor-layout) .board-toolbar .button { padding:4px 6px; min-height:27px; }
}

@media (min-width:1100px) {
    body:has(.board-layout) .flash-stack,
    body:has(.editor-layout) .flash-stack { gap:3px; margin-bottom:4px; }
    body:has(.board-layout) .flash,
    body:has(.editor-layout) .flash { padding:5px 8px; border-radius:8px; font-size:.72rem; }
}

@media (min-width:1100px) and (max-height:950px) {
    /* The editor's long wall/door instruction paragraph was consuming an
       entire map row on 1080p. The controls already carry titles/tooltips. */
    body:has(.editor-layout) .editor-board > .board-toolbar > .hint { display:none; }
    body:has(.editor-layout) .page-title p { display:none; }
}

/* --- Token library preload screen (DM only) --- */
.token-preload-screen {
    position: fixed; inset: 0; z-index: 9999;
    display: flex; align-items: center; justify-content: center;
    background: radial-gradient(circle at 50% 40%, var(--panel2), var(--bg, #1a120b) 80%);
}
.token-preload-box {
    max-width: 420px; width: 90%; text-align: center;
    padding: 32px 28px; border-radius: 16px;
    background: var(--panel); border: 1px solid var(--border);
    box-shadow: var(--shadow);
}
.token-preload-title {
    font-family: var(--display-font); font-size: 1.3rem; color: var(--gold);
    margin: 0 0 8px;
}
.token-preload-sub {
    font-size: 0.86rem; color: var(--muted); margin: 0 0 18px; line-height: 1.5;
}
.token-preload-bar {
    height: 8px; border-radius: 999px; overflow: hidden;
    background: rgba(0, 0, 0, 0.35); margin-bottom: 8px;
}
.token-preload-fill {
    height: 100%; width: 0%; background: var(--gold);
    transition: width 0.2s ease-out;
}
.token-preload-count {
    font-size: 0.78rem; color: var(--muted); margin: 0 0 16px;
}
.token-preload-skip {
    background: none; border: 1px solid var(--border); color: var(--muted);
    border-radius: 8px; padding: 6px 14px; font-size: 0.78rem; cursor: pointer;
}
.token-preload-skip:hover { color: var(--gold); border-color: var(--gold); }
.token-preload-screen.token-preload-hidden { display: none; }

/* --- Soundboard (DM only; players have no soundboard UI at all) --- */
.soundboard-row {
    display: flex; gap: 6px; align-items: stretch; margin-bottom: 6px;
}
.soundboard-play {
    flex: 1; text-align: left; font-size: 0.82rem;
    padding: 7px 10px; border-radius: 8px;
    border: 1px solid var(--border); background: rgba(0, 0, 0, 0.2);
    color: var(--text); cursor: pointer;
}
.soundboard-play:hover { border-color: var(--gold); color: var(--gold); }
.soundboard-loop {
    font-size: 0.68rem; color: var(--muted); border: 1px solid var(--border);
    border-radius: 999px; padding: 1px 6px; margin-left: 4px;
}
.soundboard-del {
    flex: 0 0 auto; width: 30px; border-radius: 8px;
    border: 1px solid var(--border); background: rgba(0, 0, 0, 0.2);
    color: var(--muted); cursor: pointer; font-size: 1rem; line-height: 1;
}
.soundboard-del:hover { color: #ff6a5a; border-color: #ff6a5a; }
#soundboard-stop { width: 100%; margin: 4px 0 10px; }
.soundboard-upload {
    display: flex; flex-direction: column; gap: 8px;
    border-top: 1px solid var(--border); padding-top: 10px;
}
.soundboard-upload label { font-size: 0.78rem; color: var(--muted); }
.soundboard-upload input[type="file"] { font-size: 0.76rem; width: 100%; }
.soundboard-upload input[type="text"] { width: 100%; }
