/* =========================================================
   d20Craft — Main Stylesheet
   ========================================================= */

@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;600;700&family=Cinzel+Decorative:wght@400;700&family=Crimson+Pro:ital,wght@0,300;0,400;0,600;1,300;1,400&display=swap');

/* ----- Variables ---------------------------------------- */
:root {
    --campaign-accent:        var(--gold);
    --campaign-accent-faint:  var(--gold-faint);
    --campaign-accent-border: var(--gold-border);
    --campaign-accent-dim:    var(--gold-dim);
}

:root {
    --bg:          #0d0b09;
    --bg-raised:   #121008;
    --bg-card:     #1a1712;
    --bg-card-alt: #1e1c16;
    --bg-input:    #141210;
    --bg-overlay:  rgba(0,0,0,0.7);

    --gold:        #c9a227;
    --gold-bright: #e8c547;
    --gold-dim:    #876e18;
    --gold-faint:  rgba(201,162,39,0.12);
    --gold-border: rgba(201,162,39,0.28);

    --parchment:     #f0e6cc;
    --parchment-dim: #c8b896;

    --text:       #ddd5c4;
    --text-dim:   #9a907e;
    --text-muted: #6b5e4e;

    --border:     #231f18;
    --border-mid: #2e2a20;

    --red:        #7a1f2e;
    --red-text:   #e57373;
    --green:      #1e4a35;
    --green-text: #6dbf8c;
    --blue:       #1a2e4a;
    --blue-text:  #7ab4e8;
    --amber:      #4a3410;
    --amber-text: #e8c547;

    --font-heading:  'Cinzel', 'Palatino Linotype', 'Book Antiqua', Palatino, serif;
    --font-display:  'Cinzel Decorative', 'Cinzel', serif;
    --font-body:     'Crimson Pro', 'Palatino Linotype', Georgia, serif;
    --font-ui:       system-ui, -apple-system, 'Segoe UI', sans-serif;
    /* The display voice a campaign theme speaks in. Used once per page, on the
       page title, so a characterful face stays an event rather than a texture.
       Defaults to the heading face, so the base look is unchanged. */
    --font-title:    var(--font-heading);

    /* The site's own gold. Campaign themes repaint everything else, but never
       this — the logo is the one fixed thing across every campaign. */
    --logo:      #c9a227;
    --header-bg: rgba(13,11,9,0.96);
    /* The material the page is printed on; each theme swaps its own in. */
    --wash:
        radial-gradient(ellipse at 20% 10%, rgba(201,162,39,0.04) 0%, transparent 50%),
        radial-gradient(ellipse at 80% 90%, rgba(201,162,39,0.03) 0%, transparent 50%);

    --space-xs:  0.25rem;
    --space-sm:  0.5rem;
    --space-md:  1rem;
    --space-lg:  1.5rem;
    --space-xl:  2rem;
    --space-2xl: 3rem;
    --space-3xl: 5rem;

    --radius:    3px;
    --radius-lg: 6px;
    --shadow:    0 2px 12px rgba(0,0,0,0.5);
    --shadow-lg: 0 6px 32px rgba(0,0,0,0.7);
    --transition: 0.18s ease;

    --header-h: 64px;
    --campaign-bar-h: 74px;
    --container-w: 1100px;
}

/* ----- Reset -------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 16px; scroll-behavior: smooth; }
body {
    background: var(--bg);
    color: var(--text);
    font-family: var(--font-body);
    font-size: 1.0625rem;
    line-height: 1.65;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}
body::before {
    content: '';
    position: fixed;
    inset: 0;
    background-image: var(--wash);
    pointer-events: none;
    z-index: 0;
}
img { max-width: 100%; display: block; }
a { color: var(--gold); text-decoration: none; transition: color var(--transition); }
a:hover { color: var(--gold-bright); }
ul, ol { padding-left: 1.25em; }

/* ----- Layout ------------------------------------------- */
.container {
    width: 100%;
    max-width: var(--container-w);
    margin: 0 auto;
    padding: 0 var(--space-lg);
}

.site-main {
    flex: 1;
    padding-top: var(--space-2xl);
    padding-bottom: var(--space-3xl);
    position: relative;
    z-index: 1;
}

body.has-campaign .site-main {
    padding-top: var(--space-xl);
}

/* ----- Site Header -------------------------------------- */
.site-header {
    position: sticky;
    top: 0;
    z-index: 100;
    background: var(--header-bg);
    border-bottom: 1px solid var(--gold-border);
    backdrop-filter: blur(8px);
    height: var(--header-h);
}

.header-inner {
    max-width: var(--container-w);
    margin: 0 auto;
    padding: 0 var(--space-lg);
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-lg);
}

.site-logo {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    color: var(--logo);
    font-family: var(--font-display);
    font-size: 1.35rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    white-space: nowrap;
}
.site-logo:hover { color: #e8c547; }
.logo-icon { font-size: 1.1em; }

.site-nav {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
}

.nav-link {
    color: var(--text-dim);
    font-family: var(--font-ui);
    font-size: 0.85rem;
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 0.35rem 0.75rem;
    border-radius: var(--radius);
    transition: color var(--transition), background var(--transition);
}
.nav-link:hover { color: var(--gold); background: var(--gold-faint); }

.nav-link-cta {
    background: var(--gold-faint);
    border: 1px solid var(--gold-border);
    color: var(--gold);
}
.nav-link-cta:hover { background: var(--gold); color: var(--bg); }

.nav-link-admin { color: var(--amber-text); }
.nav-link-logout { color: var(--text-muted); }

.nav-user {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    padding-left: var(--space-md);
    border-left: 1px solid var(--border-mid);
}

.nav-username {
    font-family: var(--font-ui);
    font-size: 0.82rem;
    color: var(--text-dim);
}

.nav-toggle {
    display: none;
    flex-direction: column;
    gap: 5px;
    background: none;
    border: none;
    cursor: pointer;
    padding: 4px;
}
.nav-toggle span {
    display: block;
    width: 22px;
    height: 2px;
    background: var(--text-dim);
    border-radius: 2px;
    transition: var(--transition);
}

/* ----- Campaign Bar ------------------------------------- */
.campaign-bar {
    background: var(--bg-raised);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: var(--header-h);
    z-index: 90;
}
.campaign-bar-inner {
    max-width: var(--container-w);
    margin: 0 auto;
    padding: 0 var(--space-lg);
    height: var(--campaign-bar-h);
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 3px;
}

.campaign-bar-meta {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex: 0 0 auto;
}

/* Stays on the heading face, not --font-title: at 0.9rem a display face like
   Rye or Pirata One is decoration the reader has to fight. The bar still
   changes voice per theme, because --font-heading is themed too. */
.campaign-title {
    font-family: var(--font-heading);
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--gold);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 60vw;
}
.campaign-sep { color: var(--text-muted); }

.campaign-nav {
    display: flex;
    align-items: center;
    gap: 4px;
    overflow-x: auto;
    scrollbar-width: none;
}
.campaign-nav::-webkit-scrollbar { display: none; }
/* If the bar ever outruns its width (phones), fade the edge so it reads as
   "there's more" rather than as a clipped word. This is a sticky overlay, not
   a mask — a mask on this element would clip the plates nested inside it. */
.campaign-nav.is-scrollable::after {
    content: '';
    position: sticky;
    right: 0;
    flex: 0 0 2.5rem;
    align-self: stretch;
    margin-left: -2.5rem;
    pointer-events: none;
    background: linear-gradient(to right, transparent, var(--bg-raised));
    transition: opacity var(--transition);
}
.campaign-nav.is-scrollable.is-scrolled-end::after { opacity: 0; }
.cnav {
    font-family: var(--font-ui);
    font-size: 0.78rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--text-muted);
    padding: 0.3rem 0.85rem;
    border-radius: var(--radius);
    white-space: nowrap;
    transition: color var(--transition), background var(--transition);
}
.cnav:hover { color: var(--text); background: var(--bg-card); }
.cnav.active { color: var(--gold); background: var(--gold-faint); }

/* The group triggers open a plate rather than navigating, so they're buttons. */
button.cnav {
    border: 0;
    background: none;
    line-height: inherit;
    cursor: pointer;
}
.cnav-caret { margin-left: 3px; font-size: 0.6em; opacity: 0.6; vertical-align: middle; }
.cnav-group[data-open] > .cnav-trigger { color: var(--text); background: var(--bg-card); }
.cnav-group[data-open] > .cnav-trigger .cnav-caret { opacity: 1; }

/* ----- Campaign nav plates ------------------------------
   A group opens a "plate": a rail of sections (label + what it's for) beside
   live entity columns, divided by hinge rules. Positioned by main.js, which
   clamps it inside the viewport — nothing may run off the right edge. */
.cnav-group { position: relative; }

.cnav-panel {
    display: none;
    position: fixed;
    z-index: 300;
    background: var(--bg-card);
    border: 1px solid var(--border-mid);
    border-top: 1px solid var(--gold-border);
    border-radius: var(--radius);
    box-shadow: 0 14px 40px rgba(0,0,0,0.6);
}
.cnav-panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    padding: 0.5rem 0.9rem 0.45rem;
    border-bottom: 1px solid var(--border);
}
.cnav-eyebrow {
    font-family: var(--font-ui);
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.cnav-panel-body { display: flex; align-items: stretch; }

.cnav-rail {
    flex: 0 0 auto;
    width: 15rem;
    padding: 0.35rem;
    display: flex;
    flex-direction: column;
}
.cnav-panel-slim .cnav-rail { width: 14rem; }

.cnav-sec {
    display: block;
    padding: 0.4rem 0.55rem 0.45rem;
    border-radius: var(--radius);
    border-left: 2px solid transparent;
    transition: background var(--transition), border-color var(--transition);
}
.cnav-sec-label {
    display: block;
    font-family: var(--font-ui);
    font-size: 0.82rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--text);
}
.cnav-sec-blurb {
    display: block;
    font-family: var(--font-body);
    font-size: 0.82rem;
    line-height: 1.35;
    color: var(--text-muted);
}
.cnav-sec:hover { background: var(--bg-raised); border-left-color: var(--border-mid); }
.cnav-sec:hover .cnav-sec-label { color: var(--gold); }
.cnav-sec.active { background: var(--gold-faint); border-left-color: var(--gold); }
.cnav-sec.active .cnav-sec-label { color: var(--gold); }

.cnav-col {
    flex: 0 0 auto;
    width: 14rem;
    min-width: 0;
    border-left: 1px solid var(--border);
    padding: 0.35rem 0;
    display: flex;
    flex-direction: column;
}
.cnav-col-head {
    font-family: var(--font-ui);
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--text-muted);
    padding: 0.2rem 0.9rem 0.4rem;
}
.cnav-col-body { overflow-y: auto; max-height: 17rem; }

.cnav-dropdown-item {
    display: block;
    padding: 0.28rem 0.9rem;
    font-family: var(--font-ui);
    font-size: 0.8rem;
    color: var(--text-dim);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: color var(--transition), background var(--transition);
}
.cnav-dropdown-item:hover { background: var(--gold-faint); color: var(--gold); }
.cnav-dropdown-sub { color: var(--text-muted); font-size: 0.76rem; }

/* The GM's private tools read as their own plate — warm parchment wash and the
   same lock chip the site uses on secret records. */
.cnav-group-private .cnav-panel {
    background: linear-gradient(rgba(201,162,39,0.05), rgba(201,162,39,0.02)), var(--bg-card);
    border-color: rgba(201,162,39,0.28);
}
.cnav-group-private .cnav-panel-head { border-bottom-color: rgba(201,162,39,0.2); }
.cnav-group-private .cnav-sec:hover { background: rgba(201,162,39,0.08); }

/* Narrow viewports: the plate stacks into one column and scrolls as a sheet. */
@media (max-width: 700px) {
    .cnav-panel { overflow-y: auto; }
    .cnav-panel-body { flex-wrap: wrap; }
    .cnav-rail, .cnav-panel-slim .cnav-rail, .cnav-col { width: 100%; }
    .cnav-col {
        border-left: 0;
        border-top: 1px solid var(--border);
    }
    .cnav-col-body { max-height: none; }
}

/* ----- Expanding location tree in the nav dropdown ------ */
.cnav-tree-row { display: flex; align-items: stretch; }
.cnav-tree-row .cnav-dropdown-item { flex: 1 1 auto; }
.cnav-tree-toggle {
    flex: 0 0 auto;
    width: 1.5rem;
    border: 0;
    background: none;
    color: var(--text-muted);
    font-size: 0.7rem;
    line-height: 1;
    cursor: pointer;
    transition: transform var(--transition), color var(--transition);
}
.cnav-tree-toggle:hover { color: var(--gold); }
.cnav-tree-spacer { flex: 0 0 auto; width: 1.5rem; }
/* Sub-locations expand on hover (or when pinned open via the toggle on touch). */
.cnav-tree-children {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows var(--transition);
}
.cnav-tree-children-inner { overflow: hidden; }
.cnav-tree-node:hover > .cnav-tree-children,
.cnav-tree-node.open > .cnav-tree-children { grid-template-rows: 1fr; }
.cnav-tree-node:hover > .cnav-tree-row > .cnav-tree-toggle,
.cnav-tree-node.open > .cnav-tree-row > .cnav-tree-toggle { transform: rotate(90deg); }

/* ----- Typography --------------------------------------- */
h1, h2, h3, h4, h5 {
    font-family: var(--font-heading);
    font-weight: 600;
    color: var(--parchment);
    line-height: 1.25;
}
h1 { font-size: 2rem; margin-bottom: var(--space-md); }
h2 { font-size: 1.5rem; margin-bottom: var(--space-md); }
h3 { font-size: 1.2rem; margin-bottom: var(--space-sm); }
h4 { font-size: 1rem; margin-bottom: var(--space-xs); }

.page-header {
    margin-bottom: var(--space-2xl);
    padding-bottom: var(--space-lg);
    border-bottom: 1px solid var(--gold-border);
}
.page-header h1 { margin-bottom: var(--space-xs); font-family: var(--font-title); }
.page-subtitle {
    color: var(--text-dim);
    font-size: 1.05rem;
}

.section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--space-lg);
    gap: var(--space-md);
}

.ornament {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    color: var(--gold-dim);
    margin: var(--space-lg) 0;
}
.ornament::before, .ornament::after {
    content: '';
    flex: 1;
    height: 1px;
    background: linear-gradient(to right, transparent, var(--gold-border));
}
.ornament::after {
    background: linear-gradient(to left, transparent, var(--gold-border));
}

/* ----- Cards -------------------------------------------- */
.card {
    background: var(--bg-card);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-lg);
    padding: var(--space-xl);
    position: relative;
}
.card::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--gold-border), transparent);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}

.card-title {
    font-family: var(--font-heading);
    font-size: 1.1rem;
    color: var(--parchment);
    margin-bottom: var(--space-sm);
}
.card-body { color: var(--text-dim); }

.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: var(--space-lg);
}

/* A shelf of covers: the campaign's own plate on the left (see
   .campaign-spine), everything else stacked beside it. */
.campaign-card {
    background: var(--bg-card);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-lg);
    padding: var(--space-xl);
    display: grid;
    grid-template-columns: 54px minmax(0, 1fr);
    column-gap: var(--space-md);
    row-gap: var(--space-sm);
    align-content: start;
    transition: border-color var(--transition), transform var(--transition), box-shadow var(--transition);
    position: relative;
    overflow: hidden;
}
.campaign-card > *:not(.campaign-spine) { grid-column: 2; }
.campaign-card::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--gold-border), transparent);
}
.campaign-card:hover {
    border-color: var(--gold-border);
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
}

.campaign-card-title {
    font-family: var(--font-heading);
    font-size: 1.15rem;
    color: var(--parchment);
    font-weight: 600;
}

.campaign-card-desc {
    color: var(--text-dim);
    font-size: 0.95rem;
    flex: 1;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Stacked, not inline: the cover slot narrows this column, and an inline row
   wrapped mid-value and left the "·" dangling at the end of a line. */
.campaign-card-meta {
    display: flex;
    flex-direction: column;
    gap: 1px;
    margin-top: var(--space-sm);
    font-size: 0.82rem;
    color: var(--text-muted);
    font-family: var(--font-ui);
}
.campaign-card-meta > span { white-space: nowrap; }
.campaign-card-meta > .meta-sep { display: none; }

.section-card {
    background: var(--bg-card);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-lg);
    padding: var(--space-xl);
    display: flex;
    align-items: flex-start;
    gap: var(--space-lg);
    text-decoration: none;
    color: inherit;
    transition: border-color var(--transition), background var(--transition), transform var(--transition);
}
.section-card:hover {
    border-color: var(--gold-border);
    background: var(--bg-card-alt);
    transform: translateY(-1px);
    color: inherit;
}
.section-card-icon {
    font-size: 1.8rem;
    width: 2.5rem;
    text-align: center;
    flex-shrink: 0;
    margin-top: 2px;
}
.section-card-content {}
.section-card-title {
    font-family: var(--font-heading);
    font-size: 1rem;
    color: var(--parchment);
    margin-bottom: var(--space-xs);
}
.section-card-desc {
    font-size: 0.9rem;
    color: var(--text-dim);
}

/* ----- Badges ------------------------------------------- */
.badge {
    display: inline-flex;
    align-items: center;
    padding: 0.2em 0.6em;
    border-radius: 2px;
    font-family: var(--font-ui);
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
.badge-role-gm      { background: var(--gold-faint); color: var(--gold); border: 1px solid var(--gold-border); }
.badge-role-player  { background: var(--blue); color: var(--blue-text); border: 1px solid rgba(122,180,232,0.2); }
.badge-role-superadmin { background: var(--amber); color: var(--amber-text); border: 1px solid rgba(232,197,71,0.3); }

/* Theme chip — colours come from campaign_themes() as inline --chip vars, so a
   newly registered theme needs no CSS rule of its own. */
.badge-theme { background: var(--chip-faint); color: var(--chip); border: 1px solid var(--chip-border); }

/* ----- Forms -------------------------------------------- */
.form-card {
    background: var(--bg-card);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-lg);
    padding: var(--space-2xl);
    max-width: 480px;
    margin: 0 auto;
    position: relative;
}
.form-card::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--gold-border), transparent);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
.form-card-wide { max-width: 640px; }

.form-group {
    margin-bottom: var(--space-lg);
}
.form-group:last-of-type { margin-bottom: 0; }

label {
    display: block;
    font-family: var(--font-ui);
    font-size: 0.8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-dim);
    margin-bottom: var(--space-xs);
}
label .required { color: var(--red-text); margin-left: 2px; }

input[type="text"],
input[type="email"],
input[type="password"],
input[type="date"],
input[type="number"],
input[type="search"],
select,
textarea {
    width: 100%;
    background: var(--bg-input);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius);
    padding: 0.6rem 0.85rem;
    color: var(--text);
    font-family: var(--font-body);
    font-size: 1rem;
    transition: border-color var(--transition), box-shadow var(--transition);
    appearance: none;
}
input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--gold-dim);
    box-shadow: 0 0 0 3px var(--gold-faint);
}
input::placeholder, textarea::placeholder { color: var(--text-muted); }

select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23876e18' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.85rem center;
    padding-right: 2.5rem;
    cursor: pointer;
}

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

.form-hint {
    margin-top: var(--space-xs);
    font-size: 0.82rem;
    color: var(--text-muted);
    font-family: var(--font-ui);
}

.form-actions {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    margin-top: var(--space-xl);
    flex-wrap: wrap;
}

.form-footer {
    text-align: center;
    margin-top: var(--space-lg);
    color: var(--text-muted);
    font-family: var(--font-ui);
    font-size: 0.88rem;
}

/* ----- Buttons ------------------------------------------ */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-sm);
    padding: 0.6rem 1.4rem;
    border: 1px solid transparent;
    border-radius: var(--radius);
    font-family: var(--font-ui);
    font-size: 0.85rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    cursor: pointer;
    text-decoration: none;
    transition: all var(--transition);
    white-space: nowrap;
}
.btn:hover { text-decoration: none; }
.btn:disabled { opacity: 0.4; cursor: not-allowed; }

.btn-primary {
    background: var(--gold);
    color: #0d0b09;
    border-color: var(--gold);
}
.btn-primary:hover {
    background: var(--gold-bright);
    border-color: var(--gold-bright);
    color: #0d0b09;
    box-shadow: 0 0 16px rgba(201,162,39,0.25);
}

.btn-secondary {
    background: transparent;
    color: var(--text-dim);
    border-color: var(--border-mid);
}
.btn-secondary:hover {
    border-color: var(--text-muted);
    color: var(--text);
    background: var(--bg-card);
}

.btn-ghost {
    background: transparent;
    color: var(--gold-dim);
    border-color: var(--gold-border);
}
.btn-ghost:hover {
    background: var(--gold-faint);
    color: var(--gold);
    border-color: var(--gold-dim);
}

.btn-danger {
    background: transparent;
    color: var(--red-text);
    border-color: rgba(229,115,115,0.3);
}
.btn-danger:hover {
    background: rgba(122,31,46,0.2);
    border-color: var(--red-text);
}

.btn-sm {
    padding: 0.35rem 0.85rem;
    font-size: 0.75rem;
}

.btn-lg {
    padding: 0.8rem 2rem;
    font-size: 0.9rem;
}

/* ----- Alerts ------------------------------------------- */
.alert {
    padding: var(--space-md) var(--space-lg);
    border-radius: var(--radius);
    border-left: 3px solid;
    margin-bottom: var(--space-lg);
    font-family: var(--font-ui);
    font-size: 0.92rem;
}
.alert-success { background: var(--green); border-color: var(--green-text); color: var(--green-text); }
.alert-error   { background: var(--red);   border-color: var(--red-text);   color: var(--red-text); }
.alert-warning { background: var(--amber); border-color: var(--amber-text); color: var(--amber-text); }
.alert-info    { background: var(--blue);  border-color: var(--blue-text);  color: var(--blue-text); }

/* ----- Tables ------------------------------------------- */
.table-wrapper { overflow-x: auto; border-radius: var(--radius-lg); }
table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.95rem;
}
thead tr {
    background: var(--bg-raised);
    border-bottom: 1px solid var(--gold-border);
}
th {
    font-family: var(--font-ui);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    padding: 0.75rem 1rem;
    text-align: left;
}
td {
    padding: 0.8rem 1rem;
    border-bottom: 1px solid var(--border);
    color: var(--text);
    vertical-align: middle;
}
tbody tr:hover { background: var(--bg-card); }
tbody tr:last-child td { border-bottom: none; }

/* ----- Hero --------------------------------------------- */
.hero {
    text-align: center;
    padding: var(--space-3xl) 0 var(--space-2xl);
}
.hero-eyebrow {
    font-family: var(--font-ui);
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.18em;
    color: var(--gold-dim);
    margin-bottom: var(--space-md);
}
.hero-title {
    font-family: var(--font-display);
    font-size: clamp(2.2rem, 6vw, 3.5rem);
    color: var(--parchment);
    margin-bottom: var(--space-lg);
    line-height: 1.15;
    text-shadow: 0 2px 20px rgba(201,162,39,0.15);
}
.hero-title .accent { color: var(--gold); }
.hero-body {
    max-width: 580px;
    margin: 0 auto var(--space-xl);
    font-size: 1.1rem;
    color: var(--text-dim);
}
.hero-actions {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-md);
    flex-wrap: wrap;
}
.hero-divider {
    margin: var(--space-2xl) 0;
    border: none;
    border-top: 1px solid var(--gold-border);
    opacity: 0.5;
}

/* ----- Feature Grid ------------------------------------- */
.features {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: var(--space-lg);
    margin-top: var(--space-2xl);
}
.feature {
    padding: var(--space-xl);
    background: var(--bg-card);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-lg);
}
.feature-icon {
    font-size: 1.8rem;
    margin-bottom: var(--space-md);
}
.feature-title {
    font-family: var(--font-heading);
    font-size: 1rem;
    color: var(--parchment);
    margin-bottom: var(--space-xs);
}
.feature-desc {
    font-size: 0.92rem;
    color: var(--text-dim);
}

/* ----- Stats Bar ---------------------------------------- */
.stats-row {
    display: flex;
    gap: var(--space-lg);
    flex-wrap: wrap;
    margin-bottom: var(--space-2xl);
}
.stat-box {
    background: var(--bg-card);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-lg);
    padding: var(--space-lg) var(--space-xl);
    text-align: center;
    flex: 1;
    min-width: 120px;
}
.stat-number {
    font-family: var(--font-heading);
    font-size: 1.8rem;
    color: var(--gold);
    display: block;
    line-height: 1;
    margin-bottom: var(--space-xs);
}
.stat-label {
    font-family: var(--font-ui);
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-muted);
}

/* ----- Invite Code Display ------------------------------ */
.invite-code-box {
    background: var(--bg-raised);
    border: 1px dashed var(--gold-border);
    border-radius: var(--radius);
    padding: var(--space-md) var(--space-lg);
    display: inline-flex;
    align-items: center;
    gap: var(--space-md);
}
.invite-code {
    font-family: var(--font-ui);
    font-size: 1.3rem;
    font-weight: 700;
    letter-spacing: 0.15em;
    color: var(--gold);
}
.copy-btn {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text-muted);
    padding: 0;
    font-size: 1rem;
    transition: color var(--transition);
}
.copy-btn:hover { color: var(--gold); }

/* ----- Empty States ------------------------------------- */
.empty-state {
    text-align: center;
    padding: var(--space-3xl) var(--space-lg);
    color: var(--text-muted);
}
.empty-icon { font-size: 3rem; margin-bottom: var(--space-lg); opacity: 0.4; }
.empty-title {
    font-family: var(--font-heading);
    font-size: 1.1rem;
    color: var(--text-dim);
    margin-bottom: var(--space-sm);
}
.empty-desc { font-size: 0.92rem; margin-bottom: var(--space-lg); }

/* ----- Site Footer -------------------------------------- */
.site-footer {
    border-top: 1px solid var(--border);
    padding: var(--space-xl) 0;
    position: relative;
    z-index: 1;
}
.footer-inner {
    max-width: var(--container-w);
    margin: 0 auto;
    padding: 0 var(--space-lg);
    text-align: center;
}
.footer-brand {
    display: inline-flex;
    align-items: center;
    gap: var(--space-sm);
    font-family: var(--font-display);
    font-size: 1rem;
    color: var(--gold-dim);
    margin-bottom: var(--space-sm);
}
.footer-tagline {
    font-style: italic;
    color: var(--text-muted);
    font-size: 0.92rem;
    margin-bottom: var(--space-xs);
}
.footer-copy {
    font-family: var(--font-ui);
    font-size: 0.78rem;
    color: var(--text-muted);
}

/* ----- Auth Page Layout --------------------------------- */
.auth-page {
    max-width: 480px;
    margin: 0 auto;
}
.auth-title {
    font-family: var(--font-display);
    text-align: center;
    margin-bottom: var(--space-2xl);
}

/* ----- Utility ------------------------------------------ */
.text-gold   { color: var(--gold); }
.text-dim    { color: var(--text-dim); }
.text-muted  { color: var(--text-muted); }
.text-center { text-align: center; }
.text-right  { text-align: right; }
.text-sm     { font-size: 0.88rem; }
.text-ui     { font-family: var(--font-ui); }
.mt-sm  { margin-top: var(--space-sm); }
.mt-md  { margin-top: var(--space-md); }
.mt-lg  { margin-top: var(--space-lg); }
.mt-xl  { margin-top: var(--space-xl); }
.mb-sm  { margin-bottom: var(--space-sm); }
.mb-md  { margin-bottom: var(--space-md); }
.mb-lg  { margin-bottom: var(--space-lg); }
.mb-xl  { margin-bottom: var(--space-xl); }
.flex   { display: flex; }
.gap-sm { gap: var(--space-sm); }
.gap-md { gap: var(--space-md); }
.items-center { align-items: center; }
.items-end { align-items: flex-end; }
.justify-between { justify-content: space-between; }
.hidden { display: none; }

/* ----- Icons -------------------------------------------- */
.icon {
    width: 1em;
    height: 1em;
    flex-shrink: 0;
    vertical-align: -0.125em;
}
.site-logo .icon,
.footer-brand .icon { color: var(--gold); }
.feature-icon,
.section-card-icon { color: var(--gold-dim); transition: color var(--transition); }
.section-card:hover .section-card-icon { color: var(--gold); }
.empty-icon { color: var(--gold-dim); }
.ornament { font-size: 1.4rem; }
.copy-btn .icon { width: 1.1em; height: 1.1em; }

/* ----- Media thumbnails --------------------------------- */
.media-card { padding-top: 0; }
.media-card .thumb {
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 16 / 10;
    margin: 0 calc(-1 * var(--space-xl)) var(--space-sm);
    background: var(--bg-raised);
    border-bottom: 1px solid var(--border-mid);
    overflow: hidden;
}
.media-card .thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform var(--transition);
}
.media-card:hover .thumb img { transform: scale(1.04); }
.thumb-placeholder { color: var(--text-muted); font-size: 2.75rem; }
.thumb-placeholder .icon { opacity: 0.5; }

/* File thumbnail used inside table rows */
.file-cell { display: flex; align-items: center; gap: var(--space-md); }
.file-thumb {
    width: 42px;
    height: 42px;
    flex-shrink: 0;
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--bg-raised);
    border: 1px solid var(--border-mid);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
    font-size: 1.2rem;
}
.file-thumb img { width: 100%; height: 100%; object-fit: cover; }

/* ----- Location detail ---------------------------------- */
.loc-breadcrumb {
    font-family: var(--font-ui);
    font-size: 0.8rem;
    color: var(--text-muted);
    margin-bottom: var(--space-md);
}
.loc-breadcrumb a { color: var(--text-muted); }
.loc-breadcrumb a:hover { color: var(--gold); }
.loc-breadcrumb .sep { opacity: 0.5; margin: 0 0.4rem; }

.loc-section { margin-top: var(--space-2xl); }
.loc-section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    margin-bottom: var(--space-md);
    flex-wrap: wrap;
}
.loc-section-head h2 { margin: 0; }

.attach-list { display: flex; flex-direction: column; gap: var(--space-sm); }
.attach-item {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    padding: var(--space-sm) var(--space-md);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg-raised);
}
.attach-item .file-thumb { width: 48px; height: 48px; }
.attach-meta { min-width: 0; flex: 1; }
.attach-name { font-weight: 600; word-break: break-word; }
.attach-sub {
    font-family: var(--font-ui);
    font-size: 0.75rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.attach-actions { display: flex; gap: var(--space-sm); flex-shrink: 0; align-items: center; }

.attach-add-row {
    display: grid;
    grid-template-columns: 1fr 1fr auto;
    gap: var(--space-md);
    align-items: end;
}
@media (max-width: 640px) {
    .attach-add-row { grid-template-columns: 1fr; }
    .attach-item { flex-wrap: wrap; }
}

/* ----- Rich Text Editor (Quill dark overrides) ---------- */
.rich-editor-wrap {
    border: 1px solid var(--border-mid);
    border-radius: var(--radius);
    overflow: hidden;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.rich-editor-wrap:focus-within {
    border-color: var(--gold-dim);
    box-shadow: 0 0 0 3px var(--gold-faint);
}
.rich-editor-value { display: none !important; }

.ql-toolbar.ql-snow {
    background: var(--bg-raised);
    border: none;
    border-bottom: 1px solid var(--border-mid);
    padding: 6px 8px;
}
.ql-container.ql-snow {
    background: var(--bg-input);
    border: none;
    font-family: var(--font-body);
    font-size: 1rem;
    color: var(--text);
    min-height: 140px;
}
.ql-editor { min-height: 140px; padding: 0.6rem 0.85rem; }
.ql-editor.ql-blank::before {
    color: var(--text-muted);
    font-style: italic;
    left: 0.85rem;
}
.ql-snow .ql-stroke { stroke: var(--text-dim); }
.ql-snow .ql-fill, .ql-snow .ql-stroke.ql-fill { fill: var(--text-dim); }
.ql-snow.ql-toolbar button:hover .ql-stroke,
.ql-snow.ql-toolbar button.ql-active .ql-stroke { stroke: var(--gold); }
.ql-snow.ql-toolbar button:hover .ql-fill,
.ql-snow.ql-toolbar button.ql-active .ql-fill { fill: var(--gold); }
.ql-snow.ql-toolbar button:hover,
.ql-snow.ql-toolbar button.ql-active { color: var(--gold); }
.ql-snow .ql-picker { color: var(--text-dim); }
.ql-snow .ql-picker-label { border-color: var(--border-mid) !important; }
.ql-snow .ql-picker-options {
    background: var(--bg-card);
    border-color: var(--border-mid);
}
.ql-snow .ql-picker-item:hover { color: var(--gold); }
.ql-snow a { color: var(--gold); }
.ql-tooltip {
    background: var(--bg-card) !important;
    border-color: var(--border-mid) !important;
    color: var(--text) !important;
    box-shadow: var(--shadow) !important;
}
.ql-tooltip input[type=text] {
    background: var(--bg-input);
    border-color: var(--border-mid);
    color: var(--text);
}
.ql-tooltip a.ql-action, .ql-tooltip a.ql-remove { color: var(--gold) !important; }

/* ----- Rich Content Display (stored HTML output) -------- */
.rich-content {
    color: var(--text);
    line-height: 1.7;
    font-size: 1.0625rem;
}
.rich-content p { margin-bottom: 0.75em; }
.rich-content p:last-child { margin-bottom: 0; }
.rich-content h2 { font-size: 1.3rem; margin: 1.2em 0 0.5em; color: var(--parchment); }
.rich-content h3 { font-size: 1.1rem; margin: 1em 0 0.4em; color: var(--parchment); }
.rich-content ul, .rich-content ol { padding-left: 1.4em; margin-bottom: 0.75em; }
.rich-content li { margin-bottom: 0.25em; }
.rich-content blockquote {
    border-left: 3px solid var(--gold-border);
    margin: 0.8em 0;
    padding: 0.4em 1em;
    color: var(--text-dim);
    font-style: italic;
}
.rich-content a { color: var(--gold); }
.rich-content a:hover { color: var(--gold-bright); }
.rich-content strong, .rich-content b { color: var(--parchment); }

/* ----- Character Cards ---------------------------------- */
.char-card { display: flex; flex-direction: column; gap: var(--space-sm); }

.char-portrait {
    width: 100%;
    aspect-ratio: 3 / 4;
    overflow: hidden;
    border-radius: var(--radius);
    background: var(--bg-raised);
    border: 1px solid var(--border-mid);
    margin-bottom: var(--space-sm);
}
.char-portrait img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.char-portrait-placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-sm);
    color: var(--text-muted);
    font-size: 0.8rem;
    font-family: var(--font-ui);
}
.char-portrait-placeholder .icon { font-size: 3rem; opacity: 0.3; }

/* ----- Cards that lead with a thumbnail ----------------- */
/* Same idea as .char-card: opt out of .campaign-card's spine grid (there is no
   spine here) and stack the thumbnail above the text. Landscape, not 3/4 —
   the entity types using this (locations, shops) are generated landscape_4_3
   in image_owner_types(), so a portrait frame would crop the place out of the
   picture. It reads the pool's primary via the legacy image_path column. */
.entity-thumb-card { display: flex; flex-direction: column; gap: var(--space-sm); }
/* The head row brings its own bottom margin for the 48px .catalog-thumb layout
   it was built for; under a banner the flex gap already provides it. */
.entity-thumb-card .catalog-card-head { margin-bottom: 0; }
/* Not every one of these grids has a description — the location page's shop
   list doesn't — so there is nothing whose flex:1 absorbs the slack, and the
   meta lines end up ragged across a row. Where a .campaign-card-desc IS
   present it has already eaten the free space and this resolves to zero. */
.entity-thumb-card .campaign-card-meta { margin-top: auto; }

.entity-thumb {
    width: 100%;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: var(--radius);
    background: var(--bg-raised);
    border: 1px solid var(--border-mid);
    margin-bottom: var(--space-sm);
}
.entity-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.entity-thumb-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
}
.entity-thumb-empty .icon { font-size: 2.5rem; opacity: 0.3; }

/* ----- NPC Status Badges -------------------------------- */
.status-badge {
    display: inline-block;
    flex-shrink: 0;
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    font-family: var(--font-ui);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    white-space: nowrap;
    border: 1px solid transparent;
}
.status-alive    { background: rgba(45,106,79,0.18);  color: #6dbf8c; border-color: rgba(45,106,79,0.4); }
.status-friendly { background: rgba(58,125,90,0.20);  color: #7fd6a0; border-color: rgba(58,125,90,0.45); }
.status-neutral  { background: rgba(26,46,74,0.30);   color: #7ab4e8; border-color: rgba(26,46,74,0.6); }
.status-hostile  { background: rgba(122,31,46,0.22);  color: #e57373; border-color: rgba(122,31,46,0.45); }
.status-unknown  { background: var(--bg-card-alt);    color: var(--text-dim); border-color: var(--border-mid); }
.status-missing  { background: rgba(122,90,16,0.25);  color: #d4aa6d; border-color: rgba(122,90,16,0.5); }
.status-deceased { background: rgba(40,40,44,0.55);   color: #9a9a9a; border-color: rgba(90,90,90,0.5); }

/* ----- Party Roster (campaign home) --------------------- */
.party-roster {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-lg);
    padding: var(--space-lg);
}
.party-member {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-sm);
    text-decoration: none;
    color: var(--text);
    width: 72px;
    transition: transform var(--transition);
}
.party-member:hover { transform: translateY(-2px); color: var(--gold); }
.party-avatar {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    overflow: hidden;
    border: 2px solid var(--border-mid);
    background: var(--bg-raised);
    transition: border-color var(--transition);
}
.party-member:hover .party-avatar { border-color: var(--gold-dim); }
.party-avatar img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.party-avatar-placeholder {
    display: flex;
    width: 100%;
    height: 100%;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
}
.party-avatar-placeholder .icon { font-size: 1.6rem; opacity: 0.5; }
.party-member-name {
    font-size: 0.72rem;
    font-family: var(--font-ui);
    text-align: center;
    line-height: 1.2;
    max-width: 72px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ----- Character Profile (view) ------------------------- */
.char-profile {
    display: grid;
    grid-template-columns: 220px 1fr;
    gap: var(--space-2xl);
    align-items: start;
}
.char-profile-portrait {
    border-radius: var(--radius-lg);
    overflow: hidden;
    border: 1px solid var(--border-mid);
    background: var(--bg-raised);
    position: sticky;
    top: calc(var(--header-h) + var(--campaign-bar-h) + var(--space-lg));
}
.char-profile-portrait img { width: 100%; display: block; }
.char-profile-body { min-width: 0; }
/* No portrait → body is the first (and only) child; span the full width
   instead of being squeezed into the narrow 220px portrait column. */
.char-profile-body:first-child { grid-column: 1 / -1; }

.card-private {
    border-color: rgba(201,162,39,0.2);
    background: rgba(201,162,39,0.04);
}
.card-private-label {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    font-family: var(--font-ui);
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--gold-dim);
    margin-bottom: var(--space-md);
}

/* ----- GM Secret notes (polymorphic private info) ------- */
/* View-mode block: a muted, warded card that stands apart from public content. */
.secret-note {
    margin-top: var(--space-xl);
    border-color: rgba(201,162,39,0.32);
    background:
        linear-gradient(180deg, rgba(201,162,39,0.07), rgba(201,162,39,0.02)),
        repeating-linear-gradient(135deg, transparent 0 9px, rgba(201,162,39,0.035) 9px 10px);
}
.secret-note-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-sm);
    flex-wrap: wrap;
    margin-bottom: var(--space-md);
}
.secret-note-label {
    display: inline-flex;
    align-items: center;
    gap: var(--space-sm);
    font-family: var(--font-ui);
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--gold-dim);
}
.secret-note-label .icon { color: var(--gold); }
.secret-note-tag {
    font-family: var(--font-ui);
    font-size: 0.66rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--bg);
    background: var(--gold);
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    white-space: nowrap;
}
.secret-note-foot {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin-top: var(--space-md);
    padding-top: var(--space-md);
    border-top: 1px dashed rgba(201,162,39,0.25);
}
.secret-note-foot .icon { flex: none; }

/* Edit-form editor: the private rich text + per-player reveal checklist. */
.secret-editor {
    border: 1px solid rgba(201,162,39,0.25);
    border-radius: var(--radius);
    background: rgba(201,162,39,0.04);
    padding: var(--space-md) var(--space-md) var(--space-sm);
}
.secret-editor > label {
    display: inline-flex;
    align-items: center;
    gap: var(--space-sm);
    color: var(--gold-dim);
}
.secret-editor > label .icon { color: var(--gold); }
.secret-share { margin-top: var(--space-md); }
.secret-share-head {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin-bottom: var(--space-sm);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

/* ----- NPC core traits (the GM's roleplay card) --------- */
/* Read at the table mid-scene, so it is set as a reference card: label column,
   text column, nothing decorative competing with the five lines that matter.
   Warded like a secret note, but cooler — this one is never shared with anyone. */
.core-traits {
    margin-top: var(--space-xl);
    border-color: rgba(201,162,39,0.32);
    background: linear-gradient(180deg, rgba(201,162,39,0.06), rgba(201,162,39,0.015));
}
.core-traits-tag {
    font-family: var(--font-ui);
    font-size: 0.66rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--gold-dim);
    border: 1px solid rgba(201,162,39,0.32);
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    white-space: nowrap;
}
.core-traits-list { margin: 0; }
.core-trait {
    display: grid;
    grid-template-columns: 11rem 1fr;
    gap: var(--space-md);
    padding: var(--space-sm) 0;
    border-top: 1px dashed rgba(201,162,39,0.18);
}
.core-trait:first-child { border-top: 0; }
.core-trait dt {
    display: flex;
    align-items: baseline;
    gap: var(--space-sm);
    flex-wrap: wrap;
    font-family: var(--font-ui);
    font-size: 0.74rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--gold-dim);
    padding-top: 0.15rem;
}
.core-trait dd { margin: 0; color: var(--text); }
.core-trait-ai {
    font-size: 0.58rem;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 0 0.35rem;
}
.core-traits-panel { margin-top: var(--space-lg); }
@media (max-width: 640px) {
    .core-trait { grid-template-columns: 1fr; gap: 0.2rem; }
}

/* Edit-form fields: one stacked textarea per registered trait. */
.core-traits-editor {
    border: 1px solid rgba(201,162,39,0.25);
    border-radius: var(--radius);
    background: rgba(201,162,39,0.04);
    padding: var(--space-md) var(--space-md) var(--space-sm);
}
.core-traits-editor > label {
    display: inline-flex;
    align-items: center;
    gap: var(--space-sm);
    color: var(--gold-dim);
}
.core-traits-editor > label .icon { color: var(--gold); }
.core-trait-field { margin-top: var(--space-md); }
.core-trait-field > label {
    font-family: var(--font-ui);
    font-size: 0.74rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
}
.core-trait-field textarea { width: 100%; }

/* ----- Secret ENTITIES (whole-record visibility gate) --- */
/* Inline pill on list cards/rows the viewer can see but that are secret. */
.secret-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-family: var(--font-ui);
    font-size: 0.62rem;
    font-weight: 600;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--gold-dim);
    background: rgba(201,162,39,0.10);
    border: 1px solid rgba(201,162,39,0.32);
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    white-space: nowrap;
    vertical-align: middle;
}
.secret-chip .icon { width: 0.7em; height: 0.7em; color: var(--gold); }

/* View-page banner telling an allowed viewer this record is secret/special. */
.restrict-banner {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin-bottom: var(--space-lg);
    padding: 0.55rem 0.85rem;
    border: 1px solid rgba(201,162,39,0.32);
    border-left-width: 3px;
    border-radius: var(--radius);
    background: linear-gradient(180deg, rgba(201,162,39,0.08), rgba(201,162,39,0.02));
    font-family: var(--font-ui);
    font-size: 0.8rem;
    color: var(--gold-dim);
}
.restrict-banner .icon { flex: none; color: var(--gold); }

/* Edit-form toggle: the per-player allow-list collapses until "Secret" is on. */
.restrict-toggle-label {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    cursor: pointer;
    color: var(--gold-dim);
}
.restrict-toggle-label .icon { color: var(--gold); }
.restrict-body { margin-top: var(--space-sm); }
.restrict-body[hidden] { display: none; }
.restrict-details > summary {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    cursor: pointer;
    font-family: var(--font-ui);
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--gold-dim);
    list-style: none;
}
.restrict-details > summary::-webkit-details-marker { display: none; }
.restrict-details > summary .icon { color: var(--gold); }

/* ----- Character Edit Layout ---------------------------- */
.char-edit-layout {
    display: grid;
    grid-template-columns: 200px 1fr;
    gap: var(--space-2xl);
    align-items: start;
}
.char-edit-portrait-col { display: flex; flex-direction: column; align-items: center; }

.portrait-upload-area {
    width: 100%;
    aspect-ratio: 3 / 4;
    border: 2px dashed var(--border-mid);
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--bg-raised);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: border-color var(--transition);
}
.portrait-upload-area:hover { border-color: var(--gold-border); }
.portrait-upload-area img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.portrait-placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-sm);
    color: var(--text-muted);
    font-size: 0.8rem;
    font-family: var(--font-ui);
    padding: var(--space-md);
    text-align: center;
}
.portrait-placeholder .icon { font-size: 2.5rem; opacity: 0.3; }

/* ----- Responsive --------------------------------------- */
@media (max-width: 640px) {
    .char-profile {
        grid-template-columns: 1fr;
    }
    .char-profile-portrait {
        position: static;
        max-width: 200px;
        margin: 0 auto;
    }
    .char-edit-layout {
        grid-template-columns: 1fr;
    }
    .char-edit-portrait-col {
        max-width: 220px;
        margin: 0 auto;
    }
}

/* ----- Campaign Cover Art ------------------------------- */
/* A campaign's image is a *cover*, not a masthead. It gets to be big exactly
   once — on the overview, the campaign's title page — and everywhere else it
   appears only as information (the dashboard shelf) or as material (a wash
   inside chrome that already exists). It never occupies a band of its own,
   which is what made the old strip impossible to place. */

/* 1. The wash. The bar is ~78px tall, so any picture put behind it lands as an
   unreadable horizontal slice. Blurring past recognition is the point: what
   survives is the artwork's colour and weight, which is the part that says
   "this is your campaign". Costs zero layout height. */
/* The campaign bar is deliberately NOT the surface for this. It carries small
   muted type edge to edge, so art behind it has to be crushed until it is
   invisible to stay legible — the original strip's problem, only quieter.
   The page margins are the empty surface: on any monitor wider than the
   1100px container there is dead space either side of every page, and cards
   are opaque, so the artwork shows through where nothing else lives. It rides
   on body::after, a fixed layer above the theme's own --wash and below
   .site-main (z-index 1). */
body.has-cover-wash::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background-image: var(--cover-img);
    background-size: auto 125%;
    background-position: right -4% top -8%;
    background-repeat: no-repeat;
    opacity: 0.09;
    /* Fades to nothing before it reaches the column of text. No filter on this
       element, so the mask behaves predictably. */
    -webkit-mask-image: radial-gradient(120% 95% at 100% 0%, #000 0%, rgba(0,0,0,0.55) 42%, transparent 78%);
            mask-image: radial-gradient(120% 95% at 100% 0%, #000 0%, rgba(0,0,0,0.55) 42%, transparent 78%);
}

/* 2. The plate — the cover on the campaign overview, tipped in like a colour
   plate glued into a printed book: its own paper margin, its own shadow, set
   a degree off square. Straightens under the cursor. */
.page-header-cover {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-xl);
}
.campaign-plate {
    display: block;
    width: 176px;
    /* Weighted mount — deeper at the foot, the way a print is matted. The empty
       margin is the affordance; a "view full size" caption sat inside the
       artwork's own frame and read as UI litter. */
    padding: 8px 8px 22px;
    background: var(--parchment-dim);
    border-radius: 1px;
    box-shadow: 0 12px 28px rgba(0,0,0,0.6), 0 1px 0 rgba(255,255,255,0.12) inset;
    transform: rotate(-1deg);
    transition: transform 0.35s ease, box-shadow 0.35s ease;
    cursor: zoom-in;
}
.campaign-plate img {
    display: block;
    width: 100%;
    max-height: 226px;
    object-fit: cover;
    background: var(--bg);
}
.campaign-plate:hover,
.campaign-plate:focus-visible {
    transform: rotate(0deg) translateY(-3px);
    box-shadow: 0 18px 34px rgba(0,0,0,0.68), 0 1px 0 rgba(255,255,255,0.12) inset;
}
/* 3. The shelf. On the dashboard the cover is the fastest way to tell one
   campaign from another — the one place the image is information rather than
   atmosphere, so here it stays a picture. The slot is always rendered (blank
   campaigns get a stamped plate) because a thumbnail that came and went left
   the titles down the shelf ragged. */
.campaign-spine {
    position: relative;
    display: block;
    grid-row: 1 / -1;
    align-self: start;
    width: 100%;
    aspect-ratio: 3 / 4;
    border-radius: 2px;
    overflow: hidden;
    border: 1px solid var(--border-mid);
    box-shadow: 0 4px 14px rgba(0,0,0,0.55);
    transition: border-color var(--transition);
}
.campaign-spine img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.campaign-spine-blank {
    display: grid;
    place-items: center;
    background: var(--bg-card-alt);
}
/* The colour band an unillustrated module gets on its cover. */
.campaign-spine-blank::before {
    content: '';
    position: absolute;
    inset: 0 0 auto 0;
    height: 3px;
    background: var(--spine-accent);
    opacity: 0.85;
}
.campaign-spine-initials {
    font-family: var(--font-heading);
    font-size: 1.05rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    color: var(--spine-accent);
}
.campaign-card:hover .campaign-spine { border-color: var(--gold-border); }

@media (max-width: 640px) {
    .page-header-cover {
        grid-template-columns: auto minmax(0, 1fr);
    }
    .campaign-plate { width: 108px; padding: 5px 5px 14px; }
    .campaign-plate img { max-height: 148px; }
}
@media (prefers-reduced-motion: reduce) {
    .campaign-plate { transform: none; transition: none; }
    .campaign-plate:hover, .campaign-plate:focus-visible { transform: none; }
}

/* ----- Campaign Accent Overrides ------------------------ */
body.has-campaign .campaign-title {
    color: var(--campaign-accent);
}
body.has-campaign .cnav.active {
    color: var(--campaign-accent);
    background: var(--campaign-accent-faint);
}
body.has-campaign .page-header {
    border-bottom-color: var(--campaign-accent-border);
}

/* ----- Color Swatch Picker (campaign edit) -------------- */
.color-swatches {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-sm);
    margin-top: var(--space-sm);
}
.swatch-btn {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    border: 2px solid transparent;
    cursor: pointer;
    padding: 0;
    position: relative;
    transition: transform var(--transition), box-shadow var(--transition);
    outline-offset: 3px;
}
.swatch-btn:hover { transform: scale(1.12); }
.swatch-btn.selected {
    box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--parchment);
}
.swatch-btn-auto {
    background: var(--bg-card-alt);
    border-color: var(--border-mid);
    font-family: var(--font-ui);
    font-size: 0.6rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    width: auto;
    border-radius: var(--radius);
    padding: 0 0.5rem;
    line-height: 26px;
    height: 30px;
}
.swatch-btn-auto.selected {
    color: var(--parchment);
    border-color: var(--parchment);
}
.swatch-custom-wrap {
    position: relative;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    overflow: hidden;
    cursor: pointer;
    border: 2px solid var(--border-mid);
    transition: border-color var(--transition), box-shadow var(--transition);
    flex-shrink: 0;
}
.swatch-custom-wrap.selected {
    box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--parchment);
}
.swatch-custom-wrap input[type="color"] {
    position: absolute;
    inset: -4px;
    width: calc(100% + 8px);
    height: calc(100% + 8px);
    border: none;
    padding: 0;
    cursor: pointer;
    opacity: 1;
    background: none;
}
.swatch-custom-wrap input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
.swatch-custom-wrap input[type="color"]::-webkit-color-swatch { border: none; }
.swatch-hint {
    font-family: var(--font-ui);
    font-size: 0.72rem;
    color: var(--text-muted);
    margin-top: var(--space-xs);
}
.accent-preview {
    display: inline-flex;
    align-items: center;
    gap: var(--space-sm);
    margin-top: var(--space-sm);
    font-family: var(--font-ui);
    font-size: 0.8rem;
    color: var(--text-dim);
}
.accent-preview-dot {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    flex-shrink: 0;
}

/* ----- Cover Art setting (campaign edit) ---------------- */
/* The cover preview is the shared entity-image carousel now — the campaign is a
   registered image owner, so it gets the same pool, set-primary and generate
   controls as an NPC portrait rather than a bespoke single-file preview.
   Constrained because the cover reads as a plate, not a hero: at the card's full
   width the one image dwarfs every control under it. Only the carousel is
   narrowed, so the generate panel below it keeps the full width. */
.cover-images .carousel { max-width: 280px; }
.cover-blank {
    width: 160px;
    aspect-ratio: 3 / 4;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-sm);
    margin: 0 0 var(--space-md);
    border: 1px dashed var(--border-mid);
    border-radius: var(--radius);
    background: var(--bg-input);
    color: var(--text-muted);
    font-family: var(--font-ui);
    font-size: 0.72rem;
    text-align: center;
}

.cover-pick { margin-top: var(--space-lg); }
.cover-pick > summary {
    cursor: pointer;
    font-family: var(--font-ui);
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--gold-dim);
}
.cover-pick > summary:hover { color: var(--gold); }
.cover-pick-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
    gap: var(--space-sm);
    margin-top: var(--space-md);
    /* Long pools scroll rather than pushing the upload form off the screen. */
    max-height: 340px;
    overflow-y: auto;
}
.cover-pick-item {
    display: block;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg-input);
    overflow: hidden;
    cursor: pointer;
    text-align: left;
    transition: border-color 0.15s, transform 0.15s;
}
.cover-pick-item:hover {
    border-color: var(--gold);
    transform: translateY(-2px);
}
.cover-pick-item img {
    display: block;
    width: 100%;
    aspect-ratio: 3 / 4;
    object-fit: cover;
}
.cover-pick-cap {
    display: block;
    padding: 4px 6px 5px;
    font-family: var(--font-ui);
    line-height: 1.25;
}
.cover-pick-title {
    display: block;
    font-size: 0.72rem;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cover-pick-kind {
    display: block;
    font-size: 0.62rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.cover-where-head {
    margin: var(--space-lg) 0 var(--space-xs);
    font-family: var(--font-ui);
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.cover-where {
    margin: 0;
    padding-left: 1.1rem;
    font-size: 0.86rem;
    color: var(--text-dim);
}
.cover-where li { margin-bottom: 2px; }

/* An ordinary opt-in. Settings used to borrow the old red "remove banner"
   label, so every toggle on the page shouted in alert red uppercase — a switch
   that turns a feature *on* was styled like a delete. */
.check-row {
    display: flex;
    align-items: flex-start;
    gap: var(--space-sm);
    padding: var(--space-md);
    background: var(--bg-raised);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius);
    font-family: var(--font-ui);
    font-size: 0.85rem;
    font-weight: 600;
    text-transform: none;
    letter-spacing: 0;
    color: var(--text);
    cursor: pointer;
}
.check-row input[type="checkbox"] {
    width: auto;
    margin-top: 3px;
    accent-color: var(--campaign-accent);
}
.check-row .form-hint {
    text-transform: none;
    letter-spacing: 0;
    font-weight: 400;
}

@media (max-width: 768px) {
    .site-nav {
        display: none;
        position: absolute;
        top: var(--header-h);
        left: 0; right: 0;
        background: rgba(13,11,9,0.98);
        flex-direction: column;
        align-items: stretch;
        padding: var(--space-md);
        border-bottom: 1px solid var(--border-mid);
        gap: 4px;
    }
    .site-nav.open { display: flex; }
    .nav-toggle { display: flex; }
    .nav-user {
        flex-direction: column;
        align-items: flex-start;
        border-left: none;
        border-top: 1px solid var(--border-mid);
        padding-left: 0;
        padding-top: var(--space-sm);
        margin-top: var(--space-sm);
    }
    .campaign-nav .cnav { font-size: 0.72rem; padding: 0.25rem 0.5rem; }
    .features { grid-template-columns: 1fr; }
    .card-grid { grid-template-columns: 1fr; }
    h1 { font-size: 1.6rem; }
    .form-card { padding: var(--space-lg); }
    .stats-row { gap: var(--space-sm); }
}

/* =========================================================
   Comments, Discussion forum & roll-up
   ========================================================= */

/* ----- Monogram avatar (initials, deterministic hue) ---- */
.monogram {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.4rem;
    height: 2.4rem;
    flex: none;
    border-radius: 50%;
    font-family: var(--font-ui);
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: #fff;
    background: hsl(var(--mono-hue, 40) 38% 32%);
    border: 1px solid hsl(var(--mono-hue, 40) 40% 48% / 0.5);
    user-select: none;
}

/* ----- Section subheadings (discussion page) ------------ */
.section-subhead {
    font-family: var(--font-heading);
    color: var(--parchment);
    font-size: 1.15rem;
    margin: var(--space-2xl) 0 var(--space-md);
    display: flex;
    align-items: center;
    gap: var(--space-sm);
}
.section-subhead .icon { color: var(--campaign-accent); }

/* ----- Comment thread ----------------------------------- */
.comment-thread { margin-top: var(--space-2xl); }
.comment-thread-head {
    display: flex;
    align-items: baseline;
    gap: var(--space-sm);
    margin-bottom: var(--space-lg);
    padding-bottom: var(--space-sm);
    border-bottom: 1px solid var(--border-mid);
}
.comment-thread-head h2 { font-size: 1.3rem; color: var(--parchment); }
.comment-count { font-family: var(--font-ui); font-size: 0.8rem; color: var(--text-muted); }

.comment-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
    margin-bottom: var(--space-xl);
}
.comment { display: flex; gap: var(--space-md); }
.comment-avatar { flex: none; }
.comment-main {
    flex: 1;
    min-width: 0;
    background: var(--bg-card);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-lg);
    padding: var(--space-md) var(--space-lg);
}
.comment-head {
    display: flex;
    align-items: baseline;
    gap: var(--space-sm);
    flex-wrap: wrap;
    margin-bottom: var(--space-xs);
}
.comment-author { font-family: var(--font-ui); font-weight: 600; color: var(--parchment); font-size: 0.92rem; }
.comment-time { font-family: var(--font-ui); font-size: 0.75rem; color: var(--text-muted); }
.comment-body { font-size: 1rem; }
.comment-actions { display: flex; gap: var(--space-md); margin-top: var(--space-sm); }
.comment-action {
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
    font-family: var(--font-ui);
    font-size: 0.75rem;
    color: var(--text-muted);
    text-decoration: none;
    transition: color var(--transition);
}
.comment-action:hover { color: var(--gold); }
.comment-action-danger:hover { color: var(--red-text); }
.inline-form { display: inline; }
.comment-editing .comment-main { border-color: var(--gold-border); }
.comment-empty { color: var(--text-muted); font-style: italic; margin-bottom: var(--space-lg); }
.comment-locked {
    font-family: var(--font-ui);
    font-size: 0.85rem;
    color: var(--text-dim);
    padding: var(--space-md);
    background: var(--bg-card);
    border: 1px dashed var(--border-mid);
    border-radius: var(--radius);
}

/* ----- Comment post form (sits above the newest-first list) -- */
.comment-form { margin-bottom: var(--space-xl); padding-bottom: var(--space-lg); border-bottom: 1px solid var(--border-mid); }
.comment-form-row { display: flex; gap: var(--space-md); }
.comment-form-editor { flex: 1; min-width: 0; }

/* ----- Discussion thread (opening post) ----------------- */
.thread-op { display: flex; gap: var(--space-md); margin-bottom: var(--space-2xl); }
.thread-op-main { flex: 1; min-width: 0; }
.thread-op-body { margin-top: var(--space-sm); }

/* ----- Announcements ------------------------------------ */
.announcement-list { display: flex; flex-direction: column; gap: var(--space-md); }
.announcement {
    background: var(--bg-card);
    border: 1px solid var(--border-mid);
    border-left: 3px solid var(--campaign-accent, var(--gold));
    border-radius: var(--radius-lg);
    padding: var(--space-lg) var(--space-xl);
}
.announcement-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-md);
    margin-bottom: var(--space-sm);
}
.announcement-title {
    font-family: var(--font-heading);
    font-size: 1.15rem;
    color: var(--parchment);
    margin: 0 0 2px;
}
.announcement-meta { font-family: var(--font-ui); font-size: 0.75rem; color: var(--text-muted); }
.announcement-body { font-size: 1rem; }

/* ----- Activity feed ------------------------------------ */
.activity-list { padding: var(--space-sm) 0; }
.activity-item {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    padding: var(--space-sm) var(--space-lg);
    border-bottom: 1px solid var(--border-faint, var(--border-mid));
}
.activity-item:last-child { border-bottom: none; }
.activity-avatar { flex-shrink: 0; }
.activity-avatar .monogram { width: 1.9rem; height: 1.9rem; font-size: 0.72rem; }
.activity-text { flex: 1; min-width: 0; font-size: 0.95rem; line-height: 1.5; }
.activity-actor { font-weight: 600; color: var(--parchment); }
.activity-link {
    color: var(--gold-bright, var(--gold));
    text-decoration: none;
    white-space: nowrap;
}
.activity-link:hover { text-decoration: underline; }
.activity-link .icon { width: 0.85em; height: 0.85em; vertical-align: -1px; opacity: 0.8; }
.activity-time { flex-shrink: 0; white-space: nowrap; font-family: var(--font-ui); }

/* "N new" badge on dashboard campaign cards */
.new-badge {
    display: inline-flex;
    align-items: center;
    font-family: var(--font-ui);
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: #1a1206;
    background: var(--gold, #c8a24a);
    border-radius: 999px;
    padding: 2px 8px;
    line-height: 1.4;
}

/* ----- Forum topic list --------------------------------- */
.thread-list { display: flex; flex-direction: column; gap: var(--space-sm); }
.thread-row {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    padding: var(--space-md) var(--space-lg);
    background: var(--bg-card);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-lg);
    text-decoration: none;
    transition: border-color var(--transition), transform var(--transition);
}
.thread-row:hover { border-color: var(--campaign-accent-border); transform: translateX(2px); }
.thread-row-main { flex: 1; min-width: 0; }
.thread-row-title { font-family: var(--font-heading); font-size: 1.05rem; color: var(--parchment); }
.thread-row-meta { font-family: var(--font-ui); font-size: 0.78rem; color: var(--text-muted); margin-top: 2px; }
.thread-row-replies { flex: none; text-align: center; font-family: var(--font-ui); font-size: 0.72rem; color: var(--text-muted); }
.thread-row-replies b { display: block; font-size: 1.1rem; color: var(--parchment); }
.badge-pinned { background: var(--gold-faint); color: var(--gold); border: 1px solid var(--gold-border); }
.badge-locked { background: var(--bg-card-alt); color: var(--text-dim); border: 1px solid var(--border-mid); }

/* ----- Recent activity roll-up -------------------------- */
.activity-feed { display: flex; flex-direction: column; gap: var(--space-sm); }
.activity-item {
    display: flex;
    gap: var(--space-md);
    padding: var(--space-md);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    text-decoration: none;
    color: var(--text);
    transition: border-color var(--transition), background var(--transition);
}
.activity-item:hover { border-color: var(--campaign-accent-border); background: var(--bg-card); }
.activity-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.activity-head {
    font-family: var(--font-ui);
    font-size: 0.82rem;
    color: var(--text-dim);
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    flex-wrap: wrap;
}
.activity-author { color: var(--parchment); font-weight: 600; }
.activity-on { color: var(--text-muted); }
.activity-chip { display: inline-flex; align-items: center; gap: 4px; color: var(--gold); }
.activity-chip .icon { font-size: 0.95rem; }
.activity-type { color: var(--text-muted); }
.activity-snippet {
    color: var(--text-dim);
    font-size: 0.95rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.activity-time { font-family: var(--font-ui); font-size: 0.72rem; color: var(--text-muted); }

/* ----- Emoji picker ------------------------------------- */
.ql-emoji { color: var(--text-dim) !important; }
.ql-emoji:hover { color: var(--gold) !important; }
.emoji-picker {
    position: absolute;
    z-index: 1000;
    display: none;
    width: 280px;
    max-height: 220px;
    overflow-y: auto;
    background: var(--bg-card);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    padding: var(--space-sm);
}
.emoji-picker.open { display: block; }
.emoji-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 2px; }
.emoji-btn {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 1.25rem;
    line-height: 1;
    padding: 4px;
    border-radius: var(--radius);
    transition: background var(--transition);
}
.emoji-btn:hover { background: var(--gold-faint); }

/* =========================================================
   Sessions
   ========================================================= */

/* List page — session card */
.sess-card { transition: border-color var(--transition); }
.sess-card:hover { border-color: var(--campaign-accent, var(--gold-dim)); }
.sess-summary-preview {
    color: var(--text-dim);
    font-size: 0.95rem;
    line-height: 1.55;
    margin-bottom: var(--space-sm);
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.sess-card-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    margin-top: var(--space-sm);
    padding-top: var(--space-sm);
    border-top: 1px solid var(--border);
}
.sess-meta-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-family: var(--font-ui);
    font-size: 0.8rem;
    color: var(--text-muted);
}
.sess-meta-pill .icon { font-size: 0.9rem; }

/* Detail form — top meta row */
.sess-meta-row {
    display: grid;
    grid-template-columns: 6rem 1fr 9rem;
    gap: var(--space-lg);
    margin-bottom: var(--space-lg);
}
@media (max-width: 640px) {
    .sess-meta-row { grid-template-columns: 1fr; }
}

/* Detail page — participants */
.session-participants {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
}
.session-char-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
    padding: 0.35rem 0.75rem 0.35rem 0.4rem;
    background: var(--bg-raised);
    border: 1px solid var(--border);
    border-radius: 999px;
    text-decoration: none;
    color: inherit;
    transition: border-color var(--transition), background var(--transition);
}
.session-char-chip:hover { border-color: var(--campaign-accent, var(--gold-dim)); background: var(--bg-card); }
.session-char-avatar {
    width: 1.8rem;
    height: 1.8rem;
    border-radius: 50%;
    object-fit: cover;
    object-position: top;
    flex: none;
}
.session-char-mono { flex: none; }
.session-char-mono .monogram { width: 1.8rem; height: 1.8rem; font-size: 0.7rem; }
.session-char-name { font-weight: 600; color: var(--parchment); }
.session-char-player { color: var(--text-muted); font-size: 0.8rem; font-family: var(--font-ui); }

/* Detail form — character checklist */
.sess-char-checklist {
    display: flex;
    flex-direction: column;
    gap: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
}
.sess-char-check {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    padding: 0.6rem var(--space-md);
    cursor: pointer;
    border-bottom: 1px solid var(--border);
    transition: background var(--transition);
}
.sess-char-check:last-child { border-bottom: none; }
.sess-char-check:hover { background: var(--bg-raised); }
.sess-char-check input[type="checkbox"] { width: 1rem; height: 1rem; flex: none; accent-color: var(--campaign-accent, var(--gold)); }
.sess-char-check-name { font-weight: 600; color: var(--parchment); flex: 1; }
.sess-char-check-player { color: var(--text-muted); }

/* Link rows (NPC <-> Location) — checkbox + per-row relationship select */
.link-row {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    padding: 0.45rem var(--space-md);
    border-bottom: 1px solid var(--border);
    transition: background var(--transition);
}
.link-row:last-child { border-bottom: none; }
.link-row:hover { background: var(--bg-raised); }
.link-row-main { display: flex; align-items: center; gap: var(--space-sm); flex: 1; min-width: 0; cursor: pointer; }
.link-row-main input[type="checkbox"] { width: 1rem; height: 1rem; flex: none; accent-color: var(--campaign-accent, var(--gold)); }
.link-row-role { flex: none; width: auto; min-width: 9rem; padding: 0.3rem 0.5rem; font-size: 0.85rem; }
.link-row-role:disabled { opacity: 0.4; }

/* Type-to-filter box injected above long checklists (main.js) */
.link-search { margin-bottom: var(--space-sm); }
.sess-char-checklist.is-searchable { max-height: 20rem; overflow-y: auto; }
.link-search-empty { padding: 0.6rem var(--space-md); color: var(--text-muted); font-style: italic; }

.rel-badge {
    display: inline-block;
    font-family: var(--font-ui);
    font-size: 0.66rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 2px 8px;
    border-radius: 20px;
    background: var(--campaign-accent-faint, var(--gold-faint));
    color: var(--campaign-accent, var(--gold));
    border: 1px solid var(--campaign-accent-border, var(--gold-border));
}

/* ── Admin: game-systems list ─────────────────────────────────────────────── */
.rule-system-list { display: flex; flex-direction: column; gap: var(--space-sm); }
.rule-system-row {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: var(--space-md);
    padding: var(--space-sm) var(--space-md);
    background: var(--bg-card-alt);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-lg);
}
.rule-system-row.is-hidden { opacity: 0.6; }
.rule-system-edit {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: var(--space-sm); flex: 1 1 420px; margin: 0;
}
.rule-system-edit input { margin: 0; }
.rule-system-edit .rs-sort { width: 64px; }
.rule-system-edit .rs-name { flex: 1 1 160px; min-width: 140px; }
.rule-system-edit .rs-link { flex: 2 1 220px; min-width: 160px; }
.rule-system-meta {
    display: flex; align-items: center; gap: var(--space-sm);
    flex-wrap: wrap; margin-left: auto;
}
.rule-system-meta form { margin: 0; }

/* ── Campaign meta chips (system / currency on overview) ──────────────────── */
.campaign-meta-chips { display: flex; flex-wrap: wrap; gap: var(--space-sm); }
.meta-chip {
    display: inline-flex; align-items: center; gap: 0.4rem;
    padding: 0.25rem 0.6rem;
    background: var(--bg-card-alt);
    border: 1px solid var(--border-mid);
    border-radius: 999px;
    font-family: var(--font-ui);
    font-size: 0.82rem;
    color: var(--text-dim);
}
.meta-chip .icon { color: var(--campaign-accent, var(--gold)); }
.meta-chip strong { color: var(--parchment); font-weight: 600; }
.meta-chip a { color: var(--parchment); text-decoration: none; }
.meta-chip a:hover { text-decoration: underline; }

/* ===== Shops & Item Catalog ============================== */

/* Item-kind badge (Good / Service) — sibling of .status-badge */
.kind-badge {
    display: inline-block;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    font-family: var(--font-ui);
    font-size: 0.65rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    white-space: nowrap;
    border: 1px solid transparent;
    vertical-align: middle;
}
.kind-good    { background: var(--gold-faint);        color: var(--gold-bright); border-color: var(--gold-border); }
.kind-service { background: rgba(26,46,74,0.30);      color: #7ab4e8;            border-color: rgba(26,46,74,0.6); }

/* Price tag */
.price-tag {
    flex-shrink: 0;
    font-family: var(--font-ui);
    font-weight: 700;
    color: var(--gold-bright);
    white-space: nowrap;
}
.price-tag-lg { font-size: 1.25rem; }

/* Price-modifier chip on shop cards */
.price-mod-chip {
    flex-shrink: 0;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    font-family: var(--font-ui);
    font-size: 0.68rem;
    font-weight: 700;
    white-space: nowrap;
    border: 1px solid transparent;
}
.price-mod-chip.up   { background: rgba(122,31,46,0.22); color: var(--red-text);   border-color: rgba(122,31,46,0.45); }
.price-mod-chip.down { background: rgba(30,74,53,0.25);  color: var(--green-text); border-color: rgba(30,74,53,0.5); }

/* Catalog / shop cards with a leading thumbnail */
.catalog-card-head {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin-bottom: var(--space-sm);
}
.catalog-card-head > div { flex: 1; }
.catalog-thumb {
    flex-shrink: 0;
    width: 48px;
    height: 48px;
    border-radius: var(--radius);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-input);
    border: 1px solid var(--border-mid);
}
.catalog-thumb.sm { width: 40px; height: 40px; }
.catalog-thumb img { width: 100%; height: 100%; object-fit: cover; }
.catalog-thumb-empty .icon { font-size: 1.4rem; color: var(--gold-dim); }

/* Storefront list */
.shop-table {
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
}
.shop-cat-row {
    padding: var(--space-sm) var(--space-md);
    background: var(--bg-card-alt);
    border-top: 1px solid var(--border);
    font-family: var(--font-ui);
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-dim);
}
.shop-cat-row:first-child { border-top: none; }
.shop-item-row {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    flex-wrap: wrap;
    padding: var(--space-md);
    border-top: 1px solid var(--border);
    background: var(--bg-card);
}
.shop-item-row.is-out { opacity: 0.55; }
.shop-item-main {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex: 1;
    min-width: 220px;
    color: inherit;
    text-decoration: none;
}
.shop-item-main:hover .shop-item-name { color: var(--gold-bright); }
.shop-item-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.shop-item-name {
    font-weight: 600;
    color: var(--parchment, var(--text));
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
}
.shop-item-desc { font-size: 0.82rem; color: var(--text-dim); }
.shop-item-side {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    flex-shrink: 0;
}
.price-override-note .icon { font-size: 0.9rem; color: var(--gold-dim); }

/* Stock chip */
.stock-chip {
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    font-family: var(--font-ui);
    font-size: 0.7rem;
    font-weight: 600;
    white-space: nowrap;
    border: 1px solid transparent;
}
.stock-chip.in  { background: rgba(30,74,53,0.22);  color: var(--green-text); border-color: rgba(30,74,53,0.45); }
.stock-chip.out { background: var(--bg-card-alt);   color: var(--text-muted); border-color: var(--border-mid); }

/* GM inventory controls on each row */
.shop-item-gm {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
    width: 100%;
    padding-top: var(--space-sm);
    border-top: 1px dashed var(--border-mid);
}
.rotate-flag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-family: var(--font-ui);
    font-size: 0.72rem;
    color: var(--text-dim);
    margin-right: auto;
}
.rotate-flag.fixed { color: var(--text-muted); }
.rotate-flag .icon { font-size: 0.9rem; color: var(--gold-dim); }

/* "from <pool>" tag on pool-generated inventory rows */
.pool-tag {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-family: var(--font-ui);
    font-size: 0.68rem;
    color: var(--campaign-accent, var(--gold-dim));
    border: 1px solid var(--border-mid);
    border-radius: 999px;
    padding: 1px 7px;
    margin-left: 6px;
    white-space: nowrap;
}

/* Inline checkbox + label row (e.g. the auto-restock toggle on the shop form) */
.check-inline {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    cursor: pointer;
    font-weight: 400;
    text-transform: none;
}
.check-inline input { margin-top: 3px; flex: none; }

/* Auto-stocking pools manager */
.pool-list { display: flex; flex-direction: column; gap: var(--space-sm); margin-bottom: var(--space-lg); }
.pool-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    flex-wrap: wrap;
    padding: var(--space-sm) var(--space-md);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg-card);
}
.pool-row.is-inactive { opacity: 0.55; }
.pool-row-summary { font-family: var(--font-ui); font-size: 0.8rem; color: var(--text-dim); }
.pool-row-summary strong { color: var(--text); font-weight: 600; }
.pool-edit-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--space-md);
}

/* Inline inventory edit form */
.shop-inv-edit { width: 100%; margin-top: var(--space-sm); }
.shop-inv-edit-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--space-md);
}
.shop-inv-edit-grid .form-group { margin: 0; }

/* ----- List toolbar: category browser + layout toggle --- */
.list-toolbar {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-md);
    flex-wrap: wrap;
    margin-bottom: var(--space-lg);
}
.cat-filter {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs, 0.4rem);
    flex: 1;
    min-width: 0;
}
.cat-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.3rem 0.7rem;
    border-radius: 999px;
    background: var(--bg-card);
    border: 1px solid var(--border-mid);
    color: var(--text-dim);
    font-family: var(--font-ui);
    font-size: 0.82rem;
    text-decoration: none;
    white-space: nowrap;
    transition: border-color 0.12s, color 0.12s, background 0.12s;
}
.cat-pill:hover { color: var(--parchment); border-color: var(--gold-border); }
.cat-pill.active {
    background: var(--gold-faint);
    border-color: var(--gold-border);
    color: var(--gold-bright);
    font-weight: 600;
}
.cat-count {
    font-size: 0.7rem;
    color: var(--text-muted);
    background: var(--bg-input);
    border-radius: 999px;
    padding: 0.05rem 0.4rem;
}
.cat-pill.active .cat-count { color: var(--gold-bright); background: var(--gold-faint); }

/* ----- Tab bar (AI studio & friends) --------------------- */
.tab-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 0.15rem;
    border-bottom: 1px solid var(--border-mid);
    margin-bottom: var(--space-lg);
}
.tab-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.55rem 1rem;
    margin-bottom: -1px;
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    color: var(--text-dim);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}
.tab-btn:hover { color: var(--text); }
.tab-btn.active { color: var(--gold-bright); border-bottom-color: var(--gold); }
.tab-count {
    font-size: 0.78rem;
    color: var(--text-dim);
    background: var(--bg-input);
    border-radius: 999px;
    padding: 0.05rem 0.5rem;
}
.tab-btn.active .tab-count { color: var(--gold-bright); background: var(--gold-faint); }
.tab-panel { display: none; }
.tab-panel.active { display: block; }

/* Segmented layout toggle (table / grid) */
.view-toggle {
    display: inline-flex;
    flex-shrink: 0;
    border: 1px solid var(--border-mid);
    border-radius: var(--radius);
    overflow: hidden;
}
.view-toggle-right { margin-left: auto; margin-bottom: var(--space-md); }
.view-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.35rem 0.6rem;
    color: var(--text-dim);
    background: var(--bg-card);
    text-decoration: none;
    border: none;
}
.view-btn + .view-btn { border-left: 1px solid var(--border-mid); }
.view-btn:hover { color: var(--parchment); }
.view-btn.active { background: var(--gold-faint); color: var(--gold-bright); }
.view-btn .icon { font-size: 1.05rem; }

/* ----- Tight data tables (catalog + storefront) --------- */
.data-table td, .data-table th { padding: 0.55rem 0.85rem; }
.data-table .num { text-align: right; white-space: nowrap; }
.data-table th.num { text-align: right; }
.data-table tr.row-link { cursor: pointer; }
.data-table .cell-item {
    display: inline-flex;
    align-items: center;
    gap: var(--space-sm);
    color: inherit;
    text-decoration: none;
    min-width: 0;
}
.data-table tr.row-link:hover .cell-item-name { color: var(--gold-bright); }
.data-table .cell-item-name { font-weight: 600; }
.data-table tr.is-out { opacity: 0.55; }
.data-table .actions {
    display: flex;
    gap: var(--space-xs, 0.4rem);
    align-items: center;
    justify-content: flex-end;
    white-space: nowrap;
}
.data-table .actions .inline-form { display: inline; }
/* Category group header row inside a data table */
.data-table tr.cat-row td {
    background: var(--bg-card-alt);
    font-family: var(--font-ui);
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-dim);
    padding: 0.4rem 0.85rem;
}
.data-table tr.cat-row:hover td { background: var(--bg-card-alt); }
.data-table tr.inv-edit-row:hover td { background: transparent; }
.data-table tr.inv-edit-row td { padding: 0; background: transparent; }
.data-table tr.inv-edit-row .shop-inv-edit { margin: 0; border-radius: 0; }

/* Extra-small thumbnail for dense table rows */
.catalog-thumb.xs { width: 28px; height: 28px; border-radius: var(--radius-sm, 4px); }
.catalog-thumb.xs .icon { font-size: 0.95rem; }

/* ----- Rumors ------------------------------------------------ */
/* Rarity badges — siblings of .status-badge */
.rarity-common    { background: var(--bg-card-alt);    color: var(--text-dim); border-color: var(--border-mid); }
.rarity-uncommon  { background: rgba(45,106,79,0.18);  color: #6dbf8c; border-color: rgba(45,106,79,0.4); }
.rarity-rare      { background: rgba(26,46,74,0.30);   color: #7ab4e8; border-color: rgba(26,46,74,0.6); }
.rarity-legendary { background: rgba(122,90,16,0.25);  color: #d4aa6d; border-color: rgba(122,90,16,0.5); }
.rarity-mythic    { background: rgba(99,46,122,0.28);  color: #c79be0; border-color: rgba(99,46,122,0.55); }

/* Quest kind chips — siblings of .status-badge */
.qkind-main     { background: rgba(122,90,16,0.25);  color: #d4aa6d; border-color: rgba(122,90,16,0.5); }
.qkind-side     { background: rgba(26,46,74,0.30);   color: #7ab4e8; border-color: rgba(26,46,74,0.6); }
.qkind-personal { background: rgba(58,125,90,0.20);  color: #7fd6a0; border-color: rgba(58,125,90,0.45); }
.qkind-faction  { background: rgba(99,46,122,0.28);  color: #c79be0; border-color: rgba(99,46,122,0.55); }
.qkind-mystery  { background: rgba(72,52,102,0.30);  color: #b7a6e6; border-color: rgba(72,52,102,0.6); }

/* Quest status badges — siblings of .status-badge */
.qstatus-active    { background: rgba(45,106,79,0.20);  color: #7fd6a0; border-color: rgba(45,106,79,0.45); }
.qstatus-rumored   { background: rgba(26,46,74,0.30);   color: #7ab4e8; border-color: rgba(26,46,74,0.6); }
.qstatus-stalled   { background: rgba(122,90,16,0.25);  color: #d4aa6d; border-color: rgba(122,90,16,0.5); }
.qstatus-completed { background: rgba(45,106,79,0.30);  color: #8fe0ac; border-color: rgba(45,106,79,0.6); }
.qstatus-failed    { background: rgba(122,31,46,0.22);  color: #e57373; border-color: rgba(122,31,46,0.45); }
.qstatus-abandoned { background: rgba(40,40,44,0.55);   color: #9a9a9a; border-color: rgba(90,90,90,0.5); }

/* Quest meta definition list (giver / location / sessions / reward) */
.quest-meta { display: grid; gap: var(--space-sm); margin: 0; }
.quest-meta > div { display: flex; gap: var(--space-md); align-items: baseline; }
.quest-meta dt {
    flex: 0 0 8rem;
    color: var(--text-dim);
    font-family: var(--font-ui, inherit);
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
.quest-meta dd { margin: 0; }

/* Quest beats timeline — a vertical thread of dated developments */
.quest-beats { list-style: none; margin: 0; padding: 0; position: relative; }
.quest-beats::before {
    content: "";
    position: absolute;
    left: 0.4rem;
    top: 0.3rem;
    bottom: 0.3rem;
    width: 2px;
    background: var(--border);
}
.quest-beats .beat {
    position: relative;
    padding: 0 0 var(--space-lg) 1.6rem;
}
.quest-beats .beat::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.35rem;
    width: 0.85rem;
    height: 0.85rem;
    border-radius: 50%;
    background: var(--bg-card);
    border: 2px solid var(--gold, var(--campaign-accent, #d4aa6d));
}
.quest-beats .beat-head { margin-bottom: 0.35rem; }
.quest-beats .beat-body { margin: 0; }

/* Full-viewport overlay host — never blocks interaction */
#rumor-stage {
    position: fixed;
    inset: 0;
    z-index: 80;
    pointer-events: none;
    overflow: hidden;
}

.rumor-blurb {
    /* Per-blurb knobs, randomised in rumors.js (safe fallbacks here). */
    --glow: rgba(201,162,39,0.45);
    --blur: 0px;
    --peak: 1;
    --rot-start: 0deg;
    --rot-end: 0deg;
    --dx: 0vw;
    --dy: -60px;

    position: absolute;
    max-width: min(360px, 70vw);
    padding: 0.6rem 0.9rem;
    font-family: var(--font-display, Georgia, serif);
    font-size: 1.05rem;
    font-style: italic;
    line-height: 1.45;
    color: var(--gold-bright);
    text-shadow: 0 0 8px var(--glow), 0 2px 10px rgba(0,0,0,0.8);
    opacity: 0;
    will-change: transform, opacity, filter;
    filter: blur(var(--blur)) drop-shadow(0 0 7px var(--glow));
}

/* Gradient-filled variant: paint the text with the shimmering background. */
.rumor-blurb.rumor-grad {
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    text-shadow: none;
}

/* Drift variants — all fade in, travel slowly, then fade out. The transform
   endpoints come from the --dx/--dy/--rot-* custom properties set per blurb. */
@keyframes drift-up {
    0%   { opacity: 0; transform: translate(0, 18px) rotate(var(--rot-start)); }
    12%  { opacity: var(--peak); }
    85%  { opacity: var(--peak); }
    100% { opacity: 0; transform: translate(var(--dx), var(--dy)) rotate(var(--rot-end)); }
}
@keyframes drift-rise-left {
    0%   { opacity: 0; transform: translate(24px, 16px) rotate(var(--rot-start)); }
    14%  { opacity: var(--peak); }
    82%  { opacity: var(--peak); }
    100% { opacity: 0; transform: translate(calc(var(--dx) - 8vw), var(--dy)) rotate(var(--rot-end)); }
}
@keyframes drift-rise-right {
    0%   { opacity: 0; transform: translate(-24px, 16px) rotate(var(--rot-start)); }
    14%  { opacity: var(--peak); }
    82%  { opacity: var(--peak); }
    100% { opacity: 0; transform: translate(calc(var(--dx) + 8vw), var(--dy)) rotate(var(--rot-end)); }
}
@keyframes drift-sway {
    0%   { opacity: 0; transform: translate(0, 14px) rotate(var(--rot-start)); }
    15%  { opacity: var(--peak); }
    45%  { transform: translate(calc(var(--dx) * 0.6 + 3vw), calc(var(--dy) * 0.45)) rotate(var(--rot-end)); }
    80%  { opacity: var(--peak); transform: translate(calc(var(--dx) - 3vw), calc(var(--dy) * 0.8)) rotate(var(--rot-start)); }
    100% { opacity: 0; transform: translate(var(--dx), var(--dy)) rotate(var(--rot-end)); }
}

/* Slow breathing pulse layered on top of the drift — modulates glow + softness
   without fighting the drift's opacity envelope (this rides on filter only). */
@keyframes rumor-pulse {
    0%, 100% { filter: blur(var(--blur)) drop-shadow(0 0 6px var(--glow)) brightness(0.92); }
    50%      { filter: blur(calc(var(--blur) + 1.6px)) drop-shadow(0 0 16px var(--glow)) brightness(1.3); }
}

@media (prefers-reduced-motion: reduce) {
    .rumor-blurb { animation: none !important; opacity: var(--peak); filter: drop-shadow(0 0 7px var(--glow)); }
}

/* ----- Environmental overlay (per-location animated SVG ambience) ----- */
/* Sits above page content but muted + click-through so it never gets in the
   way of reading. Effects are built by environment.js; the wrapper handles the
   travel motion, the inner <svg> handles sway/spin. */
#env-stage {
    position: fixed;
    inset: 0;
    z-index: 70;
    pointer-events: none;
    overflow: hidden;
}
.env-p {
    position: absolute;
    top: 0;
    left: 0;
    will-change: transform;
    animation-name: env-fall;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
}
.env-p > svg { display: block; }

/* Travel paths (wrapper) */
@keyframes env-fall  { from { transform: translateY(-115vh); } to { transform: translateY(115vh); } }
@keyframes env-drift { from { transform: translateX(-25vw); }  to { transform: translateX(125vw); } }
@keyframes env-rise  {
    0%   { transform: translateY(115vh);  opacity: 0; }
    12%  { opacity: 0.6; }
    80%  { opacity: 0.6; }
    100% { transform: translateY(-115vh); opacity: 0; }
}

/* Inner motion (sway / flutter) */
@keyframes env-sway { from { transform: translateX(calc(var(--sway, 0px) * -0.5)); }
                      to   { transform: translateX(var(--sway, 0px)); } }
@keyframes env-leaf { from { transform: translateX(calc(var(--sway, 0px) * -0.5)) rotate(0deg); }
                      to   { transform: translateX(var(--sway, 0px)) rotate(var(--rot, 360deg)); } }

.env-snow > svg, .env-ash > svg, .env-motes > svg, .env-embers > svg,
.env-music > svg, .env-water > svg, .env-inferno > svg {
    animation: env-sway var(--swayDur, 4s) ease-in-out infinite alternate;
}
.env-leaves > svg { animation: env-leaf var(--swayDur, 5s) ease-in-out infinite alternate; }
.env-eldritch > svg { animation: env-spin360 var(--swayDur, 12s) linear infinite; transform-origin: center; }
.env-birds > svg { animation: env-flap var(--swayDur, 0.6s) ease-in-out infinite alternate; transform-origin: center bottom; }

/* Size variance for effects whose inner svg isn't otherwise animated */
.env-rain > svg, .env-wind > svg, .env-clouds > svg, .env-fog > svg, .env-dripping > svg {
    transform: scale(var(--scale, 1));
    transform-origin: center;
}

/* Per-effect palette + travel + muting */
.env-rain     { color: #bcd6f5; opacity: 0.22; }
.env-snow     { color: #ffffff; opacity: 0.55; }
.env-ash      { color: #8a8a8a; opacity: 0.35; }
.env-leaves   { color: #c8762e; opacity: 0.42; }
.env-motes    { color: #d8c9a0; opacity: 0.28; }
.env-dripping { color: #9ec9e8; opacity: 0.30; }
.env-embers   { color: #ff7a30; animation-name: env-rise; }
.env-embers > svg { filter: drop-shadow(0 0 3px #ff8a3d); }
.env-wind     { color: #d6dde6; opacity: 0.16; animation-name: env-drift; }
.env-clouds   { color: #cdd6e0; opacity: 0.14; animation-name: env-drift; filter: blur(2px); }
.env-fog      { color: #aab2bd; opacity: 0.16; animation-name: env-drift; filter: blur(4px); }

/* Sunshine — a warm corner glow with slowly rotating rays */
.env-sun-wrap {
    position: absolute;
    top: -60px;
    right: -40px;
    width: 320px;
    height: 320px;
    opacity: 0.5;
}
.env-sun { width: 100%; height: 100%; }
.env-sun-rays { transform-origin: 100px 100px; animation: env-sun-spin 70s linear infinite; }
.env-sun-glow { transform-origin: 100px 100px; animation: env-sun-pulse 6s ease-in-out infinite alternate; }
@keyframes env-sun-spin  { to { transform: rotate(360deg); } }
@keyframes env-sun-pulse { from { opacity: 0.75; transform: scale(0.97); } to { opacity: 1; transform: scale(1.03); } }

/* ----- Extra themes ----- */

/* Glowing eyes — pairs blink open in the dark, then fade away */
.env-eyes { color: #ffc24a; animation-name: env-eyes-blink; }
.env-eyes > svg { filter: drop-shadow(0 0 5px currentColor); }
@keyframes env-eyes-blink {
    0%   { opacity: 0;    transform: scale(0.9); }
    8%   { opacity: 0.78; transform: scale(1); }
    46%  { opacity: 0.78; }
    50%  { opacity: 0.05; }   /* blink */
    54%  { opacity: 0.78; }
    90%  { opacity: 0.78; }
    100% { opacity: 0;    transform: scale(0.95); }
}

/* Eldritch symbols — arcane glyphs fade in, slowly rotating */
.env-eldritch { color: #9d7bff; animation-name: env-glyph; }
.env-eldritch > svg { filter: drop-shadow(0 0 4px currentColor); }
@keyframes env-glyph {
    0%   { opacity: 0; }
    15%  { opacity: 0.5; }
    85%  { opacity: 0.5; }
    100% { opacity: 0; }
}
@keyframes env-spin360 { to { transform: rotate(360deg); } }

/* Lightning storm — rain (reuses .env-rain) plus flashes and bolts */
.env-flash {
    position: absolute; inset: 0;
    background: #dfe8ff;
    opacity: 0;
    animation: env-flash 6s linear infinite;
}
@keyframes env-flash {
    0%  { opacity: 0; }
    3%  { opacity: 0.5; }
    6%  { opacity: 0; }
    9%  { opacity: 0.32; }
    12% { opacity: 0; }
    100%{ opacity: 0; }
}
.env-bolt {
    position: absolute;
    color: #eef4ff;
    opacity: 0;
    filter: drop-shadow(0 0 6px #bcd2ff);
    animation: env-bolt 7s linear infinite;
}
@keyframes env-bolt {
    0%,100% { opacity: 0; }
    3%      { opacity: 0.85; }
    6%      { opacity: 0; }
}

/* Inferno — dense rising embers over a flickering base glow */
.env-inferno { color: #ff6a2a; animation-name: env-rise; }
.env-inferno > svg { filter: drop-shadow(0 0 4px #ff7a2a); }
.env-flame-base {
    position: absolute; left: 0; right: 0; bottom: 0;
    height: 30vh;
    background: linear-gradient(to top, rgba(255,90,20,0.42), rgba(255,140,30,0.12) 45%, transparent);
    animation: env-flame 2.4s ease-in-out infinite alternate;
}
@keyframes env-flame {
    from { opacity: 0.55; transform: scaleY(1); }
    to   { opacity: 0.85; transform: scaleY(1.12); }
}

/* Rainbow — a soft arc near the top that gently shimmers */
.env-rainbow {
    position: absolute;
    left: 50%; top: 6%;
    transform: translateX(-50%);
    width: min(92vw, 1100px);
    opacity: 0.22;
    filter: blur(0.5px);
    animation: env-shimmer 5s ease-in-out infinite alternate;
}
.env-rainbow-svg { width: 100%; height: auto; display: block; }
@keyframes env-shimmer { from { opacity: 0.16; } to { opacity: 0.30; } }

/* Sea birds — gull silhouettes glide across, wings flapping */
.env-birds { color: #aab4c2; opacity: 0.32; animation-name: env-drift; }
@keyframes env-flap {
    from { transform: translateY(0) scaleY(1); }
    to   { transform: translateY(-3px) scaleY(0.5); }
}

/* Deep water — rising bubbles over a cool blue tint */
.env-water { color: #bfe6ff; opacity: 0.42; animation-name: env-rise; }
.env-water-tint {
    position: absolute; inset: 0;
    background: linear-gradient(to bottom, rgba(12,46,86,0.16), rgba(5,22,52,0.30));
}

/* Music notes — notes drift upward, swaying */
.env-music { color: #d9b3ff; opacity: 0.42; animation-name: env-rise; }
.env-music > svg { filter: drop-shadow(0 0 3px rgba(217,179,255,0.6)); }

/* ----- Marker classes for composite "scene" themes ----- */
/* Travel (wrapper) */
.env-t-fall    { animation-name: env-fall; }
.env-t-rise    { animation-name: env-rise; }
.env-t-drift   { animation-name: env-drift; }
.env-t-twinkle { animation-name: env-twinkle; }
@keyframes env-twinkle {
    0%, 100% { opacity: 0; transform: scale(0.6); }
    50%      { opacity: 0.8; transform: scale(1); }
}
/* Inner motion (the <svg>) */
.env-i-sway > svg  { animation: env-sway var(--swayDur, 4s) ease-in-out infinite alternate; }
.env-i-leaf > svg  { animation: env-leaf var(--swayDur, 5s) ease-in-out infinite alternate; }
.env-i-flap > svg  { animation: env-flap var(--swayDur, 0.6s) ease-in-out infinite alternate; transform-origin: center bottom; }
.env-i-wing > svg  { animation: env-wing var(--swayDur, 0.5s) ease-in-out infinite alternate; transform-origin: center; }
.env-i-scale > svg { transform: scale(var(--scale, 1)); transform-origin: center; }
@keyframes env-wing { from { transform: scaleX(1); } to { transform: scaleX(0.45); } }

/* =========================================================
   Campaign theme skins
   ---------------------------------------------------------
   One block per key in campaign_themes() (functions.php). header.php stamps
   `camp-theme-<key>` on <body> and loads the theme's faces, so these blocks
   only redefine tokens — no component is restyled by hand except each theme's
   one signature detail at the end of its block.

   Declared on <body>, deliberately:
     · beaten by `.site-main.loc-pal-*` below, so a location's mood still wins
       inside the content area;
     · beaten by the `body.has-accent` rule header.php inlines, so a GM's
       chosen accent colour outranks the theme's own.
   `--logo` is never touched here: the wordmark stays gold in every campaign.

   To add a theme, copy a block, rename the key, and register it in PHP.
   ========================================================= */

/* ----- Grimdark — ash, cold iron, old blood -------------- */
body.camp-theme-grimdark {
    --bg:#0a0b0c; --bg-raised:#0f1113; --bg-card:#15181b; --bg-card-alt:#1a1e22; --bg-input:#0f1214;
    --parchment:#e2ded6; --parchment-dim:#b0aba2;
    --text:#c5c1ba; --text-dim:#8d8981; --text-muted:#605d57;
    --border:#22262a; --border-mid:#333940;
    --gold:#a63a45; --gold-bright:#c8535e; --gold-dim:#6d2028;
    --gold-faint:rgba(166,58,69,0.13); --gold-border:rgba(166,58,69,0.32);
    --campaign-accent:#a63a45; --campaign-accent-faint:rgba(166,58,69,0.13);
    --campaign-accent-border:rgba(166,58,69,0.32); --campaign-accent-dim:#6d2028;
    --header-bg:rgba(8,9,10,0.97);
    --font-title:'Pirata One', 'Cinzel', serif;
    --font-heading:'Spectral', 'Palatino Linotype', Georgia, serif;
    --font-body:'Spectral', 'Palatino Linotype', Georgia, serif;
    --radius:0; --radius-lg:0;
    --wash:
        radial-gradient(ellipse at 50% 0%, rgba(166,58,69,0.05) 0%, transparent 55%),
        radial-gradient(ellipse at 50% 100%, rgba(0,0,0,0.5) 0%, transparent 60%);
}
/* Signature: the card's rule is a broken iron band, not a soft gradient. */
body.camp-theme-grimdark .card::before {
    height: 3px;
    background: linear-gradient(90deg, var(--gold-dim) 0 34%, transparent 34%);
}

/* ----- Futuristic — cold boot, hull lights, thin data ---- */
body.camp-theme-futuristic {
    --bg:#05080d; --bg-raised:#080d15; --bg-card:#0c141e; --bg-card-alt:#101a26; --bg-input:#0a121b;
    --parchment:#dbe9f4; --parchment-dim:#a9bfd2;
    --text:#c0d2e0; --text-dim:#7e93a6; --text-muted:#57697a;
    --border:#16232f; --border-mid:#203548;
    --gold:#35d2dc; --gold-bright:#6ceaf2; --gold-dim:#1c8189;
    --gold-faint:rgba(53,210,220,0.10); --gold-border:rgba(53,210,220,0.30);
    --campaign-accent:#35d2dc; --campaign-accent-faint:rgba(53,210,220,0.10);
    --campaign-accent-border:rgba(53,210,220,0.30); --campaign-accent-dim:#1c8189;
    --header-bg:rgba(4,7,12,0.97);
    --font-title:'Chakra Petch', system-ui, sans-serif;
    --font-heading:'Chakra Petch', system-ui, sans-serif;
    --font-body:'IBM Plex Sans', system-ui, sans-serif;
    --radius:0; --radius-lg:0;
    --wash:
        repeating-linear-gradient(to bottom, rgba(53,210,220,0.022) 0 1px, transparent 1px 3px),
        radial-gradient(ellipse at 50% 0%, rgba(53,210,220,0.05) 0%, transparent 60%);
}
body.camp-theme-futuristic .page-header h1 { text-transform: uppercase; letter-spacing: 0.07em; }
/* Signature: cards read as instrument panels — a lit segment on a dim rail. */
body.camp-theme-futuristic .card::before {
    height: 1px;
    background: linear-gradient(90deg, var(--gold) 0 52px, var(--gold-border) 52px);
}

/* ----- Modern — graphite, evidence tape, no ornament ----- */
body.camp-theme-modern {
    --bg:#0e1113; --bg-raised:#12161a; --bg-card:#181d22; --bg-card-alt:#1e242a; --bg-input:#14191e;
    --parchment:#eef1f4; --parchment-dim:#c3cbd2;
    --text:#dee3e8; --text-dim:#9aa5ae; --text-muted:#6a747d;
    --border:#212830; --border-mid:#2e3740;
    --gold:#e08a3c; --gold-bright:#f0a862; --gold-dim:#9a5a22;
    --gold-faint:rgba(224,138,60,0.11); --gold-border:rgba(224,138,60,0.28);
    --campaign-accent:#e08a3c; --campaign-accent-faint:rgba(224,138,60,0.11);
    --campaign-accent-border:rgba(224,138,60,0.28); --campaign-accent-dim:#9a5a22;
    --header-bg:rgba(10,13,15,0.97);
    --font-title:'Archivo', system-ui, sans-serif;
    --font-heading:'Archivo', system-ui, sans-serif;
    --font-body:'Source Sans 3', system-ui, sans-serif;
    --radius:4px; --radius-lg:8px;
    --wash:none;
}
body.camp-theme-modern h1, body.camp-theme-modern h2 { letter-spacing: -0.012em; }
/* Signature: the theme that takes things off. No card rule, no gradient
   ornament — structure carries the page instead of decoration. */
body.camp-theme-modern .card::before { display: none; }
body.camp-theme-modern .ornament::before,
body.camp-theme-modern .ornament::after { background: var(--border-mid); }

/* ----- Horror — pallid light, damp paper ----------------- */
body.camp-theme-horror {
    --bg:#07090a; --bg-raised:#0a0e0f; --bg-card:#0f1514; --bg-card-alt:#141b19; --bg-input:#0c1211;
    --parchment:#dfe6dd; --parchment-dim:#aeb8ab;
    --text:#c8cfc8; --text-dim:#879088; --text-muted:#5b645c;
    --border:#1a2321; --border-mid:#26312d;
    --gold:#9bb547; --gold-bright:#b7d165; --gold-dim:#62782b;
    --gold-faint:rgba(155,181,71,0.11); --gold-border:rgba(155,181,71,0.28);
    --campaign-accent:#9bb547; --campaign-accent-faint:rgba(155,181,71,0.11);
    --campaign-accent-border:rgba(155,181,71,0.28); --campaign-accent-dim:#62782b;
    --header-bg:rgba(5,7,8,0.97);
    --font-title:'IM Fell English SC', Georgia, serif;
    --font-heading:'IM Fell English', Georgia, serif;
    --font-body:'EB Garamond', Georgia, serif;
    --radius:2px; --radius-lg:3px;
    --wash:
        radial-gradient(ellipse 70% 55% at 50% 8%, rgba(155,181,71,0.05) 0%, transparent 60%),
        radial-gradient(ellipse 90% 80% at 50% 50%, transparent 30%, rgba(0,0,0,0.55) 100%);
}
body.camp-theme-horror h1, body.camp-theme-horror h2 { text-shadow: 0 0 14px rgba(155,181,71,0.13); }
/* Signature: the page rule doesn't end, it dissolves. */
body.camp-theme-horror .page-header { border-bottom-color: transparent; position: relative; }
body.camp-theme-horror .page-header::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: -1px;
    height: 1px;
    background: linear-gradient(90deg, var(--gold-border), transparent 65%);
}

/* ----- Western — sun-bleached paper, rust, dust ---------- */
body.camp-theme-western {
    --bg:#12100c; --bg-raised:#171410; --bg-card:#1f1a13; --bg-card-alt:#251f17; --bg-input:#191510;
    --parchment:#f2e4c8; --parchment-dim:#cbb894;
    --text:#e5d5b8; --text-dim:#b19b79; --text-muted:#7f6e55;
    --border:#2b2418; --border-mid:#3b3121;
    --gold:#c1703c; --gold-bright:#dc8e57; --gold-dim:#874a24;
    --gold-faint:rgba(193,112,60,0.12); --gold-border:rgba(193,112,60,0.32);
    --campaign-accent:#c1703c; --campaign-accent-faint:rgba(193,112,60,0.12);
    --campaign-accent-border:rgba(193,112,60,0.32); --campaign-accent-dim:#874a24;
    --header-bg:rgba(15,13,9,0.97);
    --font-title:'Rye', Georgia, serif;
    --font-heading:'Bitter', Georgia, serif;
    --font-body:'Bitter', Georgia, serif;
    --radius:2px; --radius-lg:3px;
    --wash:
        radial-gradient(ellipse at 50% -10%, rgba(230,180,110,0.07) 0%, transparent 55%),
        repeating-linear-gradient(to bottom, rgba(193,112,60,0.014) 0 2px, transparent 2px 5px);
}
/* Signature: page titles sit under a printer's double rule, like a notice
   nailed to a post. */
body.camp-theme-western .page-header { border-bottom: 4px double var(--gold-border); }

/* ----- Other — quiet slate, lets your own art lead ------- */
body.camp-theme-other {
    --bg:#0b0d0f; --bg-raised:#0e1113; --bg-card:#14181c; --bg-card-alt:#191e22; --bg-input:#11151a;
    --parchment:#e6ecf1; --parchment-dim:#b8c2ca;
    --text:#d3d9df; --text-dim:#939da6; --text-muted:#656f78;
    --border:#1d2429; --border-mid:#29323a;
    --gold:#8fa8bd; --gold-bright:#adc2d4; --gold-dim:#5d7182;
    --gold-faint:rgba(143,168,189,0.10); --gold-border:rgba(143,168,189,0.26);
    --campaign-accent:#8fa8bd; --campaign-accent-faint:rgba(143,168,189,0.10);
    --campaign-accent-border:rgba(143,168,189,0.26); --campaign-accent-dim:#5d7182;
    --header-bg:rgba(8,10,12,0.97);
    --wash: radial-gradient(ellipse at 50% 0%, rgba(143,168,189,0.045) 0%, transparent 55%);
}

/* ----- Theme picker (campaign create / settings) ---------
   Every card is painted and set in the theme it offers, so the choice is made
   by looking at the thing rather than reading its name. Colours and the title
   face arrive as inline --t-* vars straight from campaign_themes(). */
.theme-picker {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
    gap: var(--space-sm);
    margin-top: var(--space-sm);
}
.theme-option {
    position: relative;
    display: block;
    cursor: pointer;
    /* The card is a <label>, so the uppercase form-label styling would other-
       wise shout through every theme name and blurb. */
    text-transform: none;
    letter-spacing: normal;
    font-weight: 400;
    margin-bottom: 0;
    background: var(--bg-input);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-lg);
    overflow: hidden;
    transition: transform var(--transition), border-color var(--transition), box-shadow var(--transition);
}
.theme-option:hover { transform: translateY(-2px); border-color: var(--t-accent); }
.theme-option input { position: absolute; opacity: 0; pointer-events: none; }
.theme-option:focus-within { outline: 2px solid var(--parchment); outline-offset: 2px; }

/* A campaign page in miniature: title rule over a content panel. */
.theme-preview {
    display: block;
    height: 62px;
    padding: 11px 12px;
    background: var(--t-paper);
    border-bottom: 1px solid var(--border);
}
.tp-bar  { display: block; width: 46%; height: 6px; border-radius: 1px; background: var(--t-accent); }
.tp-body { display: block; margin-top: 9px; padding: 6px 7px; border-radius: 2px; background: var(--t-panel); }
.tp-line { display: block; height: 3px; border-radius: 1px; background: var(--t-accent); opacity: 0.42; }
.tp-line + .tp-line { margin-top: 4px; width: 62%; opacity: 0.2; }

.theme-name {
    display: block;
    padding: 9px 12px 0;
    font-family: var(--t-font);
    font-size: 1rem;
    line-height: 1.2;
    color: var(--parchment);
}
.theme-blurb {
    display: block;
    padding: 3px 12px 11px;
    font-family: var(--font-ui);
    font-size: 0.7rem;
    line-height: 1.45;
    color: var(--text-muted);
}
.theme-option input:checked ~ .theme-name { color: var(--t-accent); }
.theme-option:has(input:checked) {
    border-color: var(--t-accent);
    box-shadow: 0 0 0 1px var(--t-accent), var(--shadow);
}
@media (prefers-reduced-motion: reduce) {
    .theme-option, .theme-option:hover { transform: none; transition: none; }
}

/* ===== Per-location palettes (scoped to content area only) ===== */
.site-main[class*="loc-pal-"] { background: var(--bg); color: var(--text); }

.site-main.loc-pal-haven {
    --bg:#1a120b; --bg-raised:#1f1610; --bg-card:#2a1f15; --bg-card-alt:#31261a; --bg-input:#241a12;
    --text:#f1e4cd; --text-dim:#c4ad8a; --text-muted:#937c5e; --border:#3a2c1c; --border-mid:#48381f;
    --campaign-accent:#e8964a; --campaign-accent-faint:rgba(232,150,74,.14);
    --campaign-accent-border:rgba(232,150,74,.34); --campaign-accent-dim:#a5612b;
    --gold:#e8964a; --gold-bright:#f3ad68; --gold-dim:#a5612b;
    --gold-faint:rgba(232,150,74,.14); --gold-border:rgba(232,150,74,.34);
}
.site-main.loc-pal-voidship {
    --bg:#090d13; --bg-raised:#0c1119; --bg-card:#121a24; --bg-card-alt:#16202c; --bg-input:#0f161e;
    --text:#cfdae6; --text-dim:#8ba0b4; --text-muted:#5d7186; --border:#1d2c3a; --border-mid:#274055;
    --campaign-accent:#46c8d6; --campaign-accent-faint:rgba(70,200,214,.12);
    --campaign-accent-border:rgba(70,200,214,.32); --campaign-accent-dim:#2c8f9a;
    --gold:#46c8d6; --gold-bright:#6fdce8; --gold-dim:#2c8f9a;
    --gold-faint:rgba(70,200,214,.12); --gold-border:rgba(70,200,214,.32);
}
.site-main.loc-pal-wilds {
    --bg:#0a0f0a; --bg-raised:#0d130d; --bg-card:#141d14; --bg-card-alt:#19241a; --bg-input:#101810;
    --text:#d6e0c9; --text-dim:#9bab86; --text-muted:#6c7c58; --border:#22301f; --border-mid:#2f4129;
    --campaign-accent:#73ab4c; --campaign-accent-faint:rgba(115,171,76,.12);
    --campaign-accent-border:rgba(115,171,76,.30); --campaign-accent-dim:#4f7a32;
    --gold:#73ab4c; --gold-bright:#8fc766; --gold-dim:#4f7a32;
    --gold-faint:rgba(115,171,76,.12); --gold-border:rgba(115,171,76,.30);
}
.site-main.loc-pal-arcane {
    --bg:#0e0a14; --bg-raised:#120d1a; --bg-card:#1a1327; --bg-card-alt:#1f1730; --bg-input:#150f1f;
    --text:#ded2ee; --text-dim:#a896c4; --text-muted:#766289; --border:#2a1f3c; --border-mid:#392a52;
    --campaign-accent:#a97ce8; --campaign-accent-faint:rgba(169,124,232,.14);
    --campaign-accent-border:rgba(169,124,232,.34); --campaign-accent-dim:#7d54b8;
    --gold:#a97ce8; --gold-bright:#c29ff2; --gold-dim:#7d54b8;
    --gold-faint:rgba(169,124,232,.14); --gold-border:rgba(169,124,232,.34);
}

/* ----- Scene themes ----- */
/* Shared full-screen tints */
.env-jungle-tint  { position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(10,40,18,0.28), rgba(6,24,12,0.36)); }
.env-mossy-tint   { position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(20,45,30,0.30), rgba(8,22,14,0.42)); }
.env-crypt-tint   { position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(25,45,38,0.34), rgba(6,16,14,0.46)); }
.env-voyage-tint  { position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(120,180,220,0.12), rgba(40,90,140,0.18)); }
.env-desert-tint  { position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(200,170,110,0.14), rgba(150,110,60,0.20)); }
.env-icecave-tint { position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(150,200,230,0.14), rgba(60,110,150,0.22)); }

/* Drifting spores / green leaves (jungle, canopy, mossy) */
.env-spore      { color: #9bd17a; opacity: 0.30; }
.env-leaf-green { color: #6bbf59; opacity: 0.40; }

/* Tree-top canopy: green top band + soft light dapples */
.env-canopy-top { position: absolute; left: 0; right: 0; top: 0; height: 38vh;
                  background: linear-gradient(to bottom, rgba(20,60,28,0.42), transparent); }
.env-dapple     { position: absolute; border-radius: 50%;
                  background: radial-gradient(circle, rgba(190,225,130,0.18), transparent 70%);
                  animation: env-shimmer 6s ease-in-out infinite alternate; }

/* Colorful butterflies (colour set inline per particle) */
.env-butterfly  { opacity: 0.72; }

/* Sea voyage: wave swell at the bottom */
.env-voyage-wave { position: absolute; left: 0; right: 0; bottom: 0; height: 22vh;
                   background: linear-gradient(to top, rgba(70,140,190,0.28), transparent);
                   animation: env-flame 4s ease-in-out infinite alternate; }

/* Desert sands: warm grains streaming sideways */
.env-sand       { color: #e6cf9a; opacity: 0.30; }

/* Ice cave: hanging icicles + twinkling frost */
.env-icicle     { position: absolute; top: 0; color: #cfeeff; transform-origin: top; }
.env-frost      { color: #dbf0ff; }
.env-frost > svg { filter: drop-shadow(0 0 3px #bfe6ff); }

/* Sunken crypt: murky bubbles + drifting motes */
.env-crypt-bubble { color: #7fae93; opacity: 0.34; }
.env-crypt-mote   { color: #88ad94; opacity: 0.26; }

/* Creeping shadows: dark tint + breathing vignette + drifting blurred blobs */
.env-shadow-tint     { position: absolute; inset: 0;
                       background: linear-gradient(to bottom, rgba(4,4,8,0.30), rgba(2,2,4,0.46)); }
.env-shadow-vignette { position: absolute; inset: 0;
                       background: radial-gradient(ellipse 80% 70% at 50% 50%, transparent 34%, rgba(0,0,0,0.52) 100%);
                       animation: env-shadow-breathe 7.5s ease-in-out infinite; }
@keyframes env-shadow-breathe { 0%, 100% { opacity: 0.6; } 50% { opacity: 1; } }
.env-shadow          { color: #05050a; opacity: 0.5; }
.env-shadow > svg    { filter: blur(7px); transform: scale(var(--scale, 1)); transform-origin: center; }

/* Cobwebs: pale corner webs, a spider bobbing on a thread, drifting silk motes */
.env-web-tint        { position: absolute; inset: 0;
                       background: radial-gradient(ellipse at center, transparent 55%, rgba(10,12,16,0.34) 100%); }
.env-web-corner      { position: absolute; color: rgba(222,228,236,0.5); }
.env-web-corner > svg { filter: drop-shadow(0 0 2px rgba(255,255,255,0.22)); }
.env-web-tl          { top: -10px; left: -10px; }
.env-web-tr          { top: -10px; right: -10px; transform: scaleX(-1); }
.env-web-bl          { bottom: -10px; left: -10px; transform: scaleY(-1); }
.env-web-br          { bottom: -10px; right: -10px; transform: scale(-1, -1); }
.env-silk            { color: #e8edf4; opacity: 0.26; }
.env-spider          { position: absolute; top: 0; left: 50%; margin-left: -11px;
                       display: flex; flex-direction: column; align-items: center;
                       color: rgba(226,231,239,0.72); transform-origin: top center;
                       animation: env-spider-bob 6s ease-in-out infinite; }
.env-spider-thread   { width: 1px; height: 15vh; background: rgba(220,226,235,0.42); }
@keyframes env-spider-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(5vh); } }

/* Sunny beach: warm tint, sun glow, sea swell + foam, gulls, water glints */
.env-beach-tint      { position: absolute; inset: 0;
                       background: linear-gradient(to bottom, rgba(150,205,235,0.16) 0%, rgba(190,220,235,0.10) 45%, rgba(225,205,150,0.20) 100%); }
.env-beach-sun       { position: absolute; top: 6vh; right: 12vw; width: 220px; height: 220px; border-radius: 50%;
                       background: radial-gradient(circle, rgba(255,240,200,0.55), rgba(255,225,150,0.18) 45%, transparent 70%);
                       animation: env-sun-pulse 5s ease-in-out infinite alternate; }
.env-beach-water     { position: absolute; left: 0; right: 0; bottom: 0; height: 30vh;
                       background: linear-gradient(to top, rgba(60,150,200,0.30), rgba(90,180,210,0.10) 70%, transparent); }
.env-beach-foam      { position: absolute; left: 0; right: 0; bottom: 26vh; height: 5vh;
                       background: linear-gradient(to top, rgba(245,250,255,0.32), transparent);
                       animation: env-flame 4.5s ease-in-out infinite alternate; }
.env-glint           { color: #fff7da; opacity: 0.5; }
.env-glint > svg     { filter: drop-shadow(0 0 3px rgba(255,240,180,0.8)); }

/* Matrix code: cascading columns of glowing green glyphs over a dark tint */
.env-matrix-tint { position: absolute; inset: 0;
                   background: linear-gradient(to bottom, rgba(0,10,4,0.20), rgba(0,6,3,0.30)); }
.env-matrix-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 1;
    font-family: "Courier New", Consolas, monospace;
    font-weight: 700;
    color: #29ff74;
    text-shadow: 0 0 6px rgba(0,255,90,0.55);
    text-transform: none;
    white-space: pre;
}
.env-matrix-ch { display: block; }
.env-matrix-head {
    color: #d9ffe4;
    text-shadow: 0 0 8px #7dffa6, 0 0 14px rgba(120,255,160,0.75);
}

/* Windshield wipers / low visibility: inside a vehicle peering through fogged,
   rain-blurred glass that two blades periodically sweep clear */
.env-wiper-tint {
    position: absolute; inset: 0;
    background: linear-gradient(to bottom, rgba(120,135,150,0.30), rgba(60,72,86,0.42));
    backdrop-filter: blur(1.6px);
    -webkit-backdrop-filter: blur(1.6px);
    animation: env-wiper-haze 4.6s ease-in-out infinite;
}
.env-wiper-vignette {
    position: absolute; inset: 0;
    background: radial-gradient(ellipse 82% 72% at 50% 46%, transparent 42%, rgba(8,12,18,0.55) 100%);
}
.env-glassrain  { color: #cfe0f2; opacity: 0.22; }
.env-glassdrop  { color: #b8d2ec; opacity: 0.30; }
.env-glassrain > svg, .env-glassdrop > svg { transform: scale(var(--scale, 1)); transform-origin: center; }

.env-wiper-arm {
    position: absolute;
    bottom: -8vh;
    left: 18vw;
    width: 7px;
    height: 145vh;
    border-radius: 6px;
    transform-origin: bottom center;
    background: linear-gradient(to top,
        rgba(16,20,26,0.78) 0%,
        rgba(30,36,44,0.55) 55%,
        rgba(45,54,64,0.24) 86%,
        transparent 100%);
    box-shadow: 2px 0 6px rgba(180,210,240,0.32);   /* wet leading edge */
    animation: env-wipe 4.6s ease-in-out infinite;
}
.env-wiper-arm-2 { left: 56vw; animation-delay: 0.12s; opacity: 0.85; }

/* Two quick strokes (out + back) then a long pause — intermittent wiper */
@keyframes env-wipe {
    0%   { transform: rotate(-6deg); }
    9%   { transform: rotate(78deg);  }
    19%  { transform: rotate(-6deg); }
    100% { transform: rotate(-6deg); }
}
/* Haze lifts the instant the blade passes, then the rain re-obscures the glass */
@keyframes env-wiper-haze {
    0%   { opacity: 0.92; }
    11%  { opacity: 0.44; }
    36%  { opacity: 0.92; }
    100% { opacity: 0.92; }
}

/* ----- Place & scene themes (batch 2) ----- */

/* Shared helpers */
@keyframes env-flicker  { 0%,100% { opacity: 0.55; transform: scale(1); }
                          25% { opacity: 0.85; transform: scale(1.03); }
                          50% { opacity: 0.6;  transform: scale(0.99); }
                          75% { opacity: 0.9;  transform: scale(1.02); } }

/* Cozy inn — warm amber room with a flickering hearth, sparks and firelit dust */
.env-cozy-tint   { position: absolute; inset: 0;
                   background: linear-gradient(to bottom, rgba(60,34,14,0.24), rgba(38,20,8,0.34)); }
.env-cozy-hearth { position: absolute; left: -6vw; bottom: -8vh; width: 46vw; height: 46vh; border-radius: 50%;
                   background: radial-gradient(circle, rgba(255,168,74,0.34), rgba(255,120,40,0.12) 45%, transparent 70%);
                   animation: env-flicker 3.2s ease-in-out infinite; }
.env-cozy-spark  { color: #ff9a44; opacity: 0.5; }
.env-cozy-spark > svg { filter: drop-shadow(0 0 3px #ffb056); }
.env-cozy-mote   { color: #f0c887; opacity: 0.26; }

/* Busy marketplace — sunny warmth, swaying bunting, kicked-up dust and straw */
.env-market-tint { position: absolute; inset: 0;
                   background: linear-gradient(to bottom, rgba(255,225,160,0.14), rgba(210,170,110,0.18)); }
.env-market-bunting { position: absolute; top: 0; left: 0; right: 0; height: 42px;
                      display: flex; justify-content: space-around; align-items: flex-start;
                      padding: 0 8px; opacity: 0.6; }
.env-market-flag { width: 17px; height: 23px; clip-path: polygon(0 0, 100% 0, 50% 100%);
                   transform-origin: top center; animation: env-bunting-sway 3s ease-in-out infinite alternate; }
@keyframes env-bunting-sway { from { transform: rotate(-6deg); } to { transform: rotate(6deg); } }
.env-market-dust { color: #e8cf9a; opacity: 0.26; }
.env-market-straw{ color: #d8b467; opacity: 0.4; }

/* Library — dim scholarly warmth, slanted light shafts, motes and loose pages */
.env-library-tint  { position: absolute; inset: 0;
                     background: linear-gradient(to bottom, rgba(46,34,18,0.26), rgba(28,20,10,0.34)); }
.env-library-shaft { position: absolute; top: -25vh; left: 12vw; width: 26vw; height: 165vh;
                     background: linear-gradient(to right, transparent, rgba(255,236,190,0.11), transparent);
                     transform: rotate(17deg); filter: blur(7px); }
.env-library-shaft-2 { left: 56vw; transform: rotate(13deg); opacity: 0.7; }
.env-library-mote  { color: #e6d2a4; opacity: 0.28; }
.env-library-page  { color: #e9dcc0; opacity: 0.4; }

/* Candlelit room — dark space, soft flickering central glow, embers and motes */
.env-candle-tint  { position: absolute; inset: 0;
                    background: linear-gradient(to bottom, rgba(24,16,8,0.36), rgba(14,9,5,0.5)); }
.env-candle-glow  { position: absolute; left: 50%; top: 46%; width: 60vw; height: 60vh;
                    transform: translate(-50%,-50%); border-radius: 50%;
                    background: radial-gradient(circle, rgba(255,190,110,0.30), rgba(255,150,70,0.10) 45%, transparent 70%);
                    animation: env-flicker 2.6s ease-in-out infinite; }
.env-candle-spark { color: #ffb058; opacity: 0.5; }
.env-candle-spark > svg { filter: drop-shadow(0 0 3px #ffc070); }
.env-candle-mote  { color: #f0cf9a; opacity: 0.24; }

/* Throne room — regal gloom, grand golden shafts and slowly falling gold motes */
.env-throne-tint  { position: absolute; inset: 0;
                    background: linear-gradient(to bottom, rgba(30,20,44,0.30), rgba(14,10,24,0.42)); }
.env-throne-shaft { position: absolute; top: -20vh; left: 18vw; width: 22vw; height: 160vh;
                    background: linear-gradient(to right, transparent, rgba(255,224,150,0.13), transparent);
                    transform: rotate(15deg); filter: blur(8px); }
.env-throne-shaft-2 { left: 58vw; transform: rotate(-15deg); opacity: 0.8; }
.env-throne-vignette { position: absolute; inset: 0;
                       background: radial-gradient(ellipse 85% 75% at 50% 44%, transparent 46%, rgba(8,6,16,0.5) 100%); }
.env-throne-mote  { color: #f2d488; opacity: 0.34; }
.env-throne-mote > svg { filter: drop-shadow(0 0 3px rgba(255,214,120,0.6)); }

/* Narrow tunnel — pressing cool darkness, drifting grit and ceiling drips */
.env-tunnel-tint     { position: absolute; inset: 0;
                       background: linear-gradient(to bottom, rgba(14,18,22,0.34), rgba(6,9,12,0.46)); }
.env-tunnel-vignette { position: absolute; inset: 0;
                       background: radial-gradient(ellipse 62% 90% at 50% 50%, transparent 20%, rgba(0,0,0,0.7) 100%); }
.env-tunnel-grit     { color: #9aa0a6; opacity: 0.24; }
.env-tunnel-drip     { color: #9ec2d6; opacity: 0.32; }

/* Pine forest — deep green gloom, dark canopy band, needles and spore-dust */
.env-pine-tint   { position: absolute; inset: 0;
                   background: linear-gradient(to bottom, rgba(12,36,22,0.30), rgba(6,20,12,0.40)); }
.env-pine-top    { position: absolute; left: 0; right: 0; top: 0; height: 34vh;
                   background: linear-gradient(to bottom, rgba(10,40,22,0.5), transparent); }
.env-pine-needle { color: #4f7d3a; opacity: 0.5; }
.env-pine-spore  { color: #9bc47e; opacity: 0.26; }

/* Spaceship cockpit — warp starfield with streaks, pin-stars and a console glow */
.env-cockpit-tint    { position: absolute; inset: 0;
                       background: linear-gradient(to bottom, rgba(4,6,18,0.42), rgba(2,3,10,0.56)); }
.env-cockpit-console { position: absolute; left: 0; right: 0; bottom: 0; height: 14vh;
                       background: linear-gradient(to top, rgba(60,180,220,0.22), rgba(40,120,180,0.06) 60%, transparent); }
.env-cockpit-streak  { color: #bfe6ff; opacity: 0.42; }
.env-cockpit-streak > svg { transform: scaleY(2.4) scale(var(--scale,1)); transform-origin: center;
                            filter: drop-shadow(0 0 3px rgba(150,210,255,0.7)); }
.env-cockpit-star    { color: #ffffff; opacity: 0.6; }
.env-cockpit-star > svg { filter: drop-shadow(0 0 3px rgba(200,225,255,0.8)); }

/* Torchlight — off-centre guttering orange glow over darkness, embers and motes */
.env-torch-tint  { position: absolute; inset: 0;
                   background: linear-gradient(to bottom, rgba(22,14,8,0.36), rgba(12,7,4,0.5)); }
.env-torch-glow  { position: absolute; left: 24%; top: 30%; width: 54vw; height: 60vh;
                   transform: translate(-50%,-50%); border-radius: 50%;
                   background: radial-gradient(circle, rgba(255,150,60,0.34), rgba(255,110,40,0.10) 46%, transparent 70%);
                   animation: env-flicker 1.9s ease-in-out infinite; }
.env-torch-ember { color: #ff8636; opacity: 0.55; }
.env-torch-ember > svg { filter: drop-shadow(0 0 4px #ff9642); }
.env-torch-mote  { color: #f0c081; opacity: 0.24; }

/* Hidden waterfall — cool cascade, heavy droplets, rising mist and sunlit glints */
.env-waterfall-tint { position: absolute; inset: 0;
                      background: linear-gradient(to bottom, rgba(60,130,140,0.16), rgba(30,80,110,0.26)); }
.env-waterfall-mist { position: absolute; left: 0; right: 0; bottom: 0; height: 26vh;
                      background: linear-gradient(to top, rgba(220,240,245,0.34), rgba(200,230,240,0.10) 60%, transparent);
                      filter: blur(3px); animation: env-flame 4s ease-in-out infinite alternate; }
.env-waterfall-fall { color: #d2ecff; opacity: 0.3; }
.env-waterfall-fall > svg { transform: scaleY(1.6) scale(var(--scale,1)); transform-origin: center; }
.env-waterfall-drop { color: #cbe6f4; opacity: 0.4; }
.env-waterfall-glint{ color: #ffffff; opacity: 0.5; }
.env-waterfall-glint > svg { filter: drop-shadow(0 0 3px rgba(200,240,255,0.8)); }

/* Machine shop — cool metallic gloom, drifting steam and sputtering sparks */
.env-machine-tint  { position: absolute; inset: 0;
                     background: linear-gradient(to bottom, rgba(30,36,44,0.30), rgba(14,18,24,0.42)); }
.env-machine-steam { color: #c3ccd4; opacity: 0.12; filter: blur(3px); }
.env-machine-spark { color: #ffc23a; opacity: 0.72; }
.env-machine-spark > svg { filter: drop-shadow(0 0 4px #ff9a2a); }

/* Barnyard — warm afternoon, corner sun, floating straw, dust and feathers */
.env-barn-tint    { position: absolute; inset: 0;
                    background: linear-gradient(to bottom, rgba(240,205,140,0.16), rgba(190,150,90,0.20)); }
.env-barn-sun     { position: absolute; top: -8vh; right: -6vw; width: 44vw; height: 44vh; border-radius: 50%;
                    background: radial-gradient(circle, rgba(255,238,180,0.4), rgba(255,220,140,0.14) 45%, transparent 70%);
                    animation: env-sun-pulse 6s ease-in-out infinite alternate; }
.env-barn-straw   { color: #d6ac5a; opacity: 0.42; }
.env-barn-dust    { color: #e6cf9a; opacity: 0.24; }
.env-barn-feather { color: #f0ece0; opacity: 0.5; }

/* Sun-dappled forest path — warm green canopy, shifting light pools, motes+leaves */
.env-dappled-tint { position: absolute; inset: 0;
                    background: linear-gradient(to bottom, rgba(30,60,26,0.22), rgba(16,38,16,0.30)); }
.env-dappled-top  { position: absolute; left: 0; right: 0; top: 0; height: 34vh;
                    background: linear-gradient(to bottom, rgba(24,66,30,0.4), transparent); }
.env-dappled-pool { position: absolute; border-radius: 50%;
                    background: radial-gradient(circle, rgba(220,240,160,0.2), transparent 70%);
                    animation: env-shimmer 6s ease-in-out infinite alternate; }
.env-dappled-mote { color: #d7e7a0; opacity: 0.28; }

/* Starlight — deep night, twinkling star field and occasional shooting stars */
.env-star-tint { position: absolute; inset: 0;
                 background: linear-gradient(to bottom, rgba(8,12,34,0.44), rgba(4,6,20,0.56)); }
.env-star      { color: #ffffff; opacity: 0.7; }
.env-star > svg     { filter: drop-shadow(0 0 3px rgba(200,220,255,0.8)); }
.env-star-dim  { color: #cfd8ff; opacity: 0.5; }
.env-shootingstar {
    position: absolute; width: 120px; height: 2px; border-radius: 2px;
    background: linear-gradient(to left, rgba(255,255,255,0.9), transparent);
    transform-origin: right center; transform: rotate(28deg);
    opacity: 0; animation: env-shooting linear infinite;
}
@keyframes env-shooting {
    0%, 88%, 100% { opacity: 0; transform: rotate(28deg) translateX(0); }
    90%  { opacity: 0.9; }
    99%  { opacity: 0; transform: rotate(28deg) translateX(-52vw); }
}

/* Full moon — cool moonlit night, a glowing moon, thin clouds and faint stars */
.env-moon-tint  { position: absolute; inset: 0;
                  background: linear-gradient(to bottom, rgba(16,24,50,0.36), rgba(8,12,28,0.48)); }
.env-moon       { position: absolute; top: 7vh; right: 10vw; width: 150px; height: 150px; border-radius: 50%;
                  background: radial-gradient(circle at 42% 40%, #f2f4ff 0%, #d8def0 55%, #b9c2dc 100%);
                  box-shadow: 0 0 40px 20px rgba(200,215,255,0.35), 0 0 120px 60px rgba(160,185,255,0.14);
                  animation: env-sun-pulse 8s ease-in-out infinite alternate; }
.env-moon-cloud { color: #9aa6c6; opacity: 0.2; filter: blur(2px); }
.env-moon-star  { color: #dfe6ff; opacity: 0.5; }
.env-moon-star > svg { filter: drop-shadow(0 0 2px rgba(200,215,255,0.7)); }

/* Oncoming storm — angry clouds massing low, the sky slowly darkening as the
   light is crushed out. Near-still: menace from the creeping dark, not motion. */
.env-storm-tint  { position: absolute; inset: 0;
                   background: linear-gradient(to bottom, rgba(18,20,26,0.62), rgba(28,32,40,0.28) 55%, rgba(20,24,30,0.5));
                   animation: env-storm-gather 30s ease-in-out infinite alternate; }
@keyframes env-storm-gather {
    0%   { opacity: 0.7; }
    100% { opacity: 1; }
}
/* Vignette that slowly closes inward — the light being crushed from the edges */
.env-storm-crush { position: absolute; inset: 0; pointer-events: none;
                   background: radial-gradient(120% 100% at 50% 42%, transparent 30%, rgba(10,12,16,0.75) 100%);
                   animation: env-storm-crush-kf 24s ease-in-out infinite alternate; }
@keyframes env-storm-crush-kf {
    0%   { background: radial-gradient(120% 100% at 50% 42%, transparent 42%, rgba(10,12,16,0.66) 100%); }
    100% { background: radial-gradient(120% 100% at 50% 42%, transparent 18%, rgba(8,10,14,0.86) 100%); }
}
.env-storm-flash { position: absolute; inset: 0;
                   background: radial-gradient(140% 60% at 50% 96%, rgba(150,164,190,0.5), transparent 60%);
                   opacity: 0; animation: env-storm-flash-kf 17s ease-out infinite; }
@keyframes env-storm-flash-kf {
    0%, 100% { opacity: 0; }
    3%  { opacity: 0.16; }
    6%  { opacity: 0; }
    9%  { opacity: 0.09; }
    12% { opacity: 0; }
}
.env-storm-cloud { color: #2a2f38; opacity: 0.6; filter: blur(4px); }

@media (prefers-reduced-motion: reduce) {
    #env-stage { display: none; }
}

/* ============================================================================
   Interactive maps
   ========================================================================== */
.map-card-thumb {
    width: 100%;
    aspect-ratio: 16 / 9;
    background-size: cover;
    background-position: center;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    margin-bottom: 0.6rem;
}

.map-stage {
    position: relative;
    border: 1px solid var(--gold-border);
    border-radius: var(--radius-lg);
    background: var(--bg-card);
}
/* The viewport clips the zoomed/panned canvas. */
.map-viewport {
    position: relative;
    overflow: hidden;
    border-radius: var(--radius-lg);
    cursor: grab;
    touch-action: none;          /* pan/zoom are handled in JS */
}
.map-viewport.panning { cursor: grabbing; }
.map-stage.is-editing .map-viewport { cursor: crosshair; }
.map-stage.is-editing .map-viewport.panning { cursor: grabbing; }
.map-canvas {
    position: relative;
    display: block;
    width: 100%;
    line-height: 0;
    transform-origin: 0 0;
    will-change: transform;
}
.map-image {
    display: block;
    width: 100%;
    height: auto;
    user-select: none;
    -webkit-user-drag: none;
}
.map-markers { position: absolute; inset: 0; }
.map-edit-hint { margin-bottom: 0.75rem; }

/* Zoom controls (top-right overlay). */
.map-zoom-controls {
    position: absolute;
    top: 8px;
    right: 8px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    z-index: 20;
}
.map-zoom-btn {
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.15rem;
    line-height: 1;
    background: rgba(20, 17, 11, 0.85);
    color: var(--gold);
    border: 1px solid var(--gold-border);
    border-radius: var(--radius);
    cursor: pointer;
}
.map-zoom-btn:hover { background: var(--gold-faint); color: var(--gold-bright); }

/* A marker is anchored by its bottom-centre tip at (x%, y%). */
.map-marker {
    position: absolute;
    transform: translate(-50%, -100%);
    width: 30px;
    height: 30px;
    color: var(--mk-color, var(--gold));
    cursor: pointer;
    z-index: 1;
}
/* Pin sizes (medium is the 30px baseline above). */
.map-marker.mk-sz-small { width: 20px; height: 20px; }
.map-marker.mk-sz-large { width: 44px; height: 44px; }
.map-marker:hover,
.map-marker:focus-visible { z-index: 5; outline: none; }
.map-stage.is-editing .map-marker { cursor: grab; }
.map-stage.is-editing .map-marker:active { cursor: grabbing; }

/* Party token: a pulsing ring marks it as the movable party piece, and it
   shows a grab cursor for everyone (players can drag it, not just the GM). */
.map-marker.mk-token { cursor: grab; z-index: 6; }
.map-marker.mk-token:active { cursor: grabbing; }
.map-marker.mk-token .map-pin { position: relative; z-index: 1; }
.map-marker.mk-token::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 168%;
    aspect-ratio: 1;
    transform: translate(-50%, -52%);
    border-radius: 50%;
    border: 2px solid var(--mk-color, var(--gold));
    box-shadow: 0 0 8px var(--mk-color, var(--gold));
    opacity: 0.55;
    pointer-events: none;
    animation: mk-token-ring 2.4s ease-in-out infinite;
}
@keyframes mk-token-ring {
    0%, 100% { transform: translate(-50%, -52%) scale(1);    opacity: 0.45; }
    50%      { transform: translate(-50%, -52%) scale(1.12); opacity: 0.75; }
}

.map-pin { display: block; width: 100%; height: 100%; }
.map-pin-svg {
    width: 100%;
    height: 100%;
    filter: drop-shadow(0 1px 2px rgba(0,0,0,0.7));
    transition: transform var(--transition);
}
.map-marker:hover .map-pin-svg { transform: scale(1.18); }

/* GM-only secret markers: dashed ring so the GM can tell them apart. */
.mk-secret .map-pin-svg {
    outline: 1px dashed rgba(255,255,255,0.55);
    outline-offset: 2px;
    border-radius: 50%;
    opacity: 0.92;
}

/* Hover tooltip. */
.map-marker-tip {
    position: absolute;
    bottom: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%);
    min-width: 90px;
    max-width: 240px;
    padding: 0.5rem 0.65rem;
    background: #14110b;
    border: 1px solid var(--gold-border);
    border-radius: var(--radius);
    box-shadow: 0 6px 18px rgba(0,0,0,0.55);
    color: var(--text);
    font-size: 0.82rem;
    line-height: 1.35;
    text-align: left;
    white-space: normal;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity var(--transition);
    z-index: 10;
}
/* Markers near the top edge flip their tooltip to below the pin. */
.map-marker.tip-below .map-marker-tip {
    bottom: auto;
    top: calc(100% + 6px);
}
.map-marker:hover .map-marker-tip,
.map-marker:focus-visible .map-marker-tip { opacity: 1; visibility: visible; }
.mk-tip-title { display: block; font-weight: 600; color: var(--gold-bright); }
.mk-tip-body  { display: block; margin-top: 0.2rem; color: var(--text); }
.mk-tip-link  { display: block; margin-top: 0.3rem; font-size: 0.76rem; color: var(--gold); }

/* Marker editor panel. */
.marker-panel {
    margin-top: 1rem;
    max-width: 560px;
    padding: 1rem 1.25rem;
    background: var(--bg-card);
    border: 1px solid var(--gold-border);
    border-radius: var(--radius-lg);
}
.marker-panel .checkbox-row { display: flex; gap: 0.5rem; align-items: flex-start; margin-top: 0.5rem; }

/* --- Marker effects -------------------------------------------------------- */
/* Glowing: soft pulsing halo. */
.mk-fx-glow .map-pin-svg {
    filter: drop-shadow(0 0 4px var(--mk-color, var(--gold))) drop-shadow(0 0 9px var(--mk-color, var(--gold)));
    animation: mk-glow 2.4s ease-in-out infinite;
}
@keyframes mk-glow {
    0%, 100% { filter: drop-shadow(0 0 3px var(--mk-color, var(--gold))) drop-shadow(0 0 6px var(--mk-color, var(--gold))); }
    50%      { filter: drop-shadow(0 0 6px var(--mk-color, var(--gold))) drop-shadow(0 0 14px var(--mk-color, var(--gold))); }
}

/* Pulsing: scale heartbeat. */
.mk-fx-pulse .map-pin-svg { animation: mk-pulse 1.6s ease-in-out infinite; transform-origin: bottom center; }
@keyframes mk-pulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.22); }
}

/* On fire: warm flicker glow + a flame glyph licking up from the pin. */
.mk-fx-fire .map-pin-svg {
    filter: drop-shadow(0 0 5px #ff8a2a) drop-shadow(0 -2px 8px #ff5a1e);
    animation: mk-fire 0.45s ease-in-out infinite alternate;
}
.mk-fx-fire::before {
    content: "";
    position: absolute;
    left: 50%; top: -8px;
    width: 14px; height: 18px;
    transform: translateX(-50%);
    background: radial-gradient(ellipse at 50% 80%, rgba(255,180,60,0.9), rgba(255,90,20,0.55) 55%, transparent 75%);
    border-radius: 50% 50% 50% 50% / 70% 70% 40% 40%;
    filter: blur(1px);
    animation: mk-flame 0.5s ease-in-out infinite alternate;
    pointer-events: none;
}
@keyframes mk-fire  { from { filter: drop-shadow(0 0 4px #ff8a2a) drop-shadow(0 -2px 6px #ff5a1e); }
                      to   { filter: drop-shadow(0 0 7px #ffb43c) drop-shadow(0 -3px 11px #ff5a1e); } }
@keyframes mk-flame { from { transform: translateX(-50%) scaleY(0.9) translateY(1px); opacity: 0.8; }
                      to   { transform: translateX(-50%) scaleY(1.15) translateY(-2px); opacity: 1; } }

/* Frosted: cool steady glow with a frozen blue cast. */
.mk-fx-frost .map-pin-svg {
    filter: drop-shadow(0 0 4px #9fd9ff) drop-shadow(0 0 8px #6fb8e8);
    animation: mk-frost 3s ease-in-out infinite;
}
@keyframes mk-frost {
    0%, 100% { filter: drop-shadow(0 0 3px #9fd9ff) drop-shadow(0 0 6px #6fb8e8); }
    50%      { filter: drop-shadow(0 0 6px #cfeeff) drop-shadow(0 0 12px #6fb8e8); }
}

/* Hallowed: gentle golden-white radiance. */
.mk-fx-holy .map-pin-svg {
    filter: drop-shadow(0 0 5px #fff4c2) drop-shadow(0 0 11px #f5d97a);
    animation: mk-holy 3.4s ease-in-out infinite;
}
@keyframes mk-holy {
    0%, 100% { filter: drop-shadow(0 0 4px #fff4c2) drop-shadow(0 0 8px #f5d97a); }
    50%      { filter: drop-shadow(0 0 8px #fffbe8) drop-shadow(0 0 16px #f5d97a); }
}

@media (prefers-reduced-motion: reduce) {
    .mk-fx-glow .map-pin-svg, .mk-fx-pulse .map-pin-svg, .mk-fx-fire .map-pin-svg,
    .mk-fx-frost .map-pin-svg, .mk-fx-holy .map-pin-svg { animation: none; }
    .mk-fx-fire::before { animation: none; }
    .map-marker.mk-token::after { animation: none; }
}

/* ─── Shop Stock Log ────────────────────────────────────────────────────────── */

/* Shop filter chips */
.filter-chip {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border-radius: 12px;
    border: 1px solid var(--border-mid);
    background: var(--bg-card);
    color: var(--text-dim);
    font-size: 0.82rem;
    text-decoration: none;
    white-space: nowrap;
    transition: border-color 0.15s, color 0.15s;
}
.filter-chip:hover { border-color: var(--gold-dim); color: var(--text); }
.filter-chip.active { border-color: var(--gold); color: var(--gold); background: rgba(212,163,70,0.10); }

/* Date-group label */
.log-date-group { margin-bottom: var(--space-lg); }
.log-date-label {
    padding: var(--space-xs) 0 var(--space-xs);
    border-bottom: 1px solid var(--border-mid);
    margin-bottom: var(--space-sm);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-size: 0.78rem;
}

/* Individual run card (uses <details> for native expand/collapse) */
.restock-run-card {
    background: var(--bg-card);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-lg);
    margin-bottom: var(--space-xs);
    overflow: hidden;
}
.restock-run-card[open] { border-color: var(--gold-dim); }
.restock-run-summary {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-sm) var(--space-md);
    cursor: pointer;
    list-style: none;
    flex-wrap: wrap;
    user-select: none;
}
.restock-run-summary::-webkit-details-marker { display: none; }
.restock-run-summary::before {
    content: '▸';
    color: var(--text-dim);
    font-size: 0.75rem;
    flex-shrink: 0;
    transition: transform 0.15s;
}
.restock-run-card[open] .restock-run-summary::before { transform: rotate(90deg); }
.restock-run-shop { font-weight: 600; color: var(--text); }
.restock-run-meta { display: flex; align-items: center; gap: 4px; }
.restock-run-counts { display: flex; align-items: center; gap: var(--space-xs); flex-wrap: wrap; margin-left: auto; }

/* Summary count chips */
.stock-count-chip {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 0.78rem;
    border: 1px solid transparent;
    white-space: nowrap;
}
.stock-count-chip.restocked { background: rgba(30,74,53,0.22);  color: var(--green-text); border-color: rgba(30,74,53,0.45); }
.stock-count-chip.sold      { background: rgba(122,31,46,0.22); color: var(--red-text);   border-color: rgba(122,31,46,0.40); }
.stock-count-chip.added     { background: rgba(212,163,70,0.15); color: var(--gold);  border-color: rgba(212,163,70,0.35); }
.stock-count-chip.retired   { background: var(--bg-card-alt);   color: var(--text-muted); border-color: var(--border-mid); }

/* Per-item list inside an expanded run */
.restock-item-list {
    list-style: none;
    margin: 0;
    padding: 0 var(--space-md) var(--space-sm);
    border-top: 1px solid var(--border-mid);
}
.restock-item {
    display: flex;
    align-items: baseline;
    gap: var(--space-xs);
    padding: 5px 0;
    border-bottom: 1px solid var(--border-mid);
    font-size: 0.88rem;
    flex-wrap: wrap;
}
.restock-item:last-child { border-bottom: none; }
.restock-item-name { font-weight: 500; color: var(--text); flex: 0 0 auto; }
.restock-item-qty  { color: var(--text-dim); font-size: 0.82rem; }
.restock-item-type { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.04em; margin-left: 2px; }
.restock-item-pool { font-size: 0.78rem; }

/* Colour the change-type label by category */
.stock-change-restocked .restock-item-type { color: var(--green-text); }
.stock-change-sold      .restock-item-type { color: var(--red-text); }
.stock-change-added     .restock-item-type { color: var(--gold); }
.stock-change-retired   .restock-item-type { color: var(--text-muted); }

.restock-no-items { padding: var(--space-sm) var(--space-md); }

/* AI Studio result cards — collapsed by default, expand to the merge form.
   Mirrors the .restock-run-card <details> pattern above. */
.ai-result {
    margin-bottom: var(--space-sm);
    padding: 0;
    overflow: hidden;
}
.ai-result[open] { border-color: var(--gold-dim); }
.ai-result-summary {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-sm) var(--space-md);
    cursor: pointer;
    list-style: none;
    flex-wrap: wrap;
    user-select: none;
}
.ai-result-summary::-webkit-details-marker { display: none; }
.ai-result-summary::before {
    content: '▸';
    color: var(--text-dim);
    font-size: 0.75rem;
    flex-shrink: 0;
    transition: transform 0.15s;
}
.ai-result[open] .ai-result-summary::before { transform: rotate(90deg); }
.ai-result-summary strong { color: var(--text); font-weight: 600; }
.ai-result-meta { color: var(--text-dim); font-size: 0.82rem; }
.ai-result-counts {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    flex-wrap: wrap;
    margin-left: auto;
}
.ai-result-body {
    padding: 0 var(--space-md) var(--space-md);
    border-top: 1px solid var(--border-mid);
}

/* Summary count chips (sibling of .stock-count-chip) */
.ai-count-chip {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 0.78rem;
    border: 1px solid transparent;
    white-space: nowrap;
}
.ai-count-chip.pending   { background: rgba(212,163,70,0.18); color: var(--gold-bright); border-color: rgba(212,163,70,0.45); }
.ai-count-chip.added     { background: rgba(58,125,90,0.20);  color: #7fd6a0; border-color: rgba(58,125,90,0.45); }
.ai-count-chip.dismissed { background: var(--bg-card-alt);    color: var(--text-muted); border-color: var(--border-mid); }
.ai-count-chip.cleared   { background: rgba(26,46,74,0.30);   color: #7ab4e8; border-color: rgba(26,46,74,0.6); }

/* ── Session scheduling ─────────────────────────────────────────────────── */

/* "Next session" banner on the campaign overview */
.next-session-banner {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    padding: var(--space-md) var(--space-lg);
    margin-bottom: var(--space-xl);
    background: linear-gradient(90deg, var(--campaign-accent-faint), transparent);
    border: 1px solid var(--campaign-accent-border);
    border-left: 3px solid var(--campaign-accent);
    border-radius: var(--radius-lg);
    text-decoration: none;
    color: inherit;
    transition: background 0.15s;
}
.next-session-banner:hover { background: linear-gradient(90deg, var(--campaign-accent-faint), var(--campaign-accent-faint)); }
.next-session-icon { color: var(--campaign-accent); display: flex; }
.next-session-icon .icon { width: 22px; height: 22px; }
.next-session-text { display: flex; flex-direction: column; line-height: 1.25; }
.next-session-label {
    font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.08em;
    color: var(--campaign-accent); font-weight: 700;
}
.next-session-when { font-size: 1.05rem; font-weight: 600; color: var(--text); }
.next-session-tally {
    margin-left: auto; font-size: 0.85rem; color: var(--text-dim);
    white-space: nowrap; font-variant-numeric: tabular-nums;
}

/* Compact chip on dashboard campaign cards */
.next-session-chip {
    display: flex; align-items: center; gap: var(--space-xs);
    margin: var(--space-sm) 0;
    padding: 4px 8px;
    background: var(--gold-faint);
    border: 1px solid var(--gold-border);
    border-radius: 10px;
    font-size: 0.78rem; color: var(--text-dim);
}
.next-session-chip .icon { width: 14px; height: 14px; color: var(--gold); flex-shrink: 0; }
.next-session-chip strong { color: var(--gold-bright); font-weight: 600; }

/* Create-poll candidate-time grid */
.poll-time-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--space-sm);
}

/* Tally grid: players × candidate times */
.poll-grid { width: 100%; border-collapse: collapse; }
.poll-grid th, .poll-grid td {
    border: 1px solid var(--border-mid);
    padding: var(--space-sm);
    text-align: center;
    vertical-align: middle;
}
.poll-grid-corner, .poll-player {
    text-align: left; font-weight: 600;
    background: var(--bg-card-alt); white-space: nowrap;
}
.poll-player { color: var(--text); font-weight: 500; }
.poll-opt { min-width: 130px; background: var(--bg-card-alt); }
.poll-opt-when { font-size: 0.85rem; font-weight: 600; color: var(--text); margin-bottom: 4px; }
.poll-opt-won { background: var(--gold-faint); border-color: var(--gold-border) !important; }
.poll-opt-badge {
    margin-top: 4px; font-size: 0.72rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.05em; color: var(--gold-bright);
}
.poll-lock-btn { margin-top: 6px; }

.poll-you > .poll-player { background: var(--gold-faint); color: var(--gold-bright); }
.poll-you-tag {
    display: inline-block; margin-left: 6px; padding: 1px 6px;
    font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.05em;
    background: var(--gold); color: #1a1408; border-radius: 8px; font-weight: 700;
    vertical-align: middle;
}

/* Live tally chip under an option header */
.opt-tally {
    display: inline-flex; gap: 6px; justify-content: center;
    font-size: 0.72rem; font-variant-numeric: tabular-nums;
}
.opt-tally span { display: inline-flex; align-items: center; gap: 2px; }
.opt-tally b { font-weight: 700; }
.tally-yes   { color: var(--green-text); }
.tally-maybe { color: var(--gold-bright); }
.tally-no    { color: var(--red-text); }

/* Read-only vote marks (other players) */
.poll-mark { font-size: 1rem; font-weight: 700; }
.poll-mark-yes   { color: var(--green-text); background: rgba(30,74,53,0.25); }
.poll-mark-maybe { color: var(--gold-bright); background: var(--gold-faint); }
.poll-mark-no    { color: var(--red-text); background: rgba(122,31,46,0.20); }
.poll-mark-none  { color: var(--text-muted); }

/* Interactive vote buttons (current player's row) */
.poll-vote-cell { padding: 4px !important; }
.vote-group { display: inline-flex; gap: 3px; }
.vote-btn {
    width: 30px; height: 30px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--border-mid); background: var(--bg-input);
    color: var(--text-muted); border-radius: var(--radius);
    font-size: 0.9rem; font-weight: 700; cursor: pointer;
    transition: all 0.12s;
}
.vote-btn:hover:not(:disabled) { color: var(--text); border-color: var(--text-dim); }
.vote-btn:disabled { opacity: 0.5; cursor: default; }
.vote-yes.active   { background: var(--green); color: #eafaf0; border-color: var(--green-text); }
.vote-maybe.active { background: var(--gold-dim); color: #1a1408; border-color: var(--gold-bright); }
.vote-no.active    { background: var(--red); color: #fbeaec; border-color: var(--red-text); }

/* ============================================================================
   Search + @-mentions
   ========================================================================== */

/* Campaign sub-nav search box */
.cnav-search {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-left: auto;
    background: var(--bg-input);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius);
    padding: 2px 8px;
    max-width: 220px;
    transition: border-color 0.15s;
}
.cnav-search:focus-within { border-color: var(--campaign-accent-border); }
.cnav-search-icon { display: inline-flex; color: var(--text-muted); }
.cnav-search-icon .icon { width: 14px; height: 14px; }
.cnav-search input {
    border: none; background: none; outline: none;
    color: var(--text); font-family: var(--font-ui);
    font-size: 0.78rem; width: 100%; padding: 3px 0;
}
.cnav-search input::placeholder { color: var(--text-muted); }
@media (max-width: 640px) { .cnav-search { max-width: 150px; } }

/* Search results page */
.search-page-form {
    display: flex; align-items: center; gap: var(--space-sm);
    background: var(--bg-card); border: 1px solid var(--border-mid);
    border-radius: var(--radius-lg); padding: 6px 8px 6px 12px;
    margin-bottom: var(--space-xl);
}
.search-page-icon { display: inline-flex; color: var(--text-dim); }
.search-page-form input[type="search"] {
    flex: 1; border: none; background: none; outline: none;
    color: var(--text); font-family: var(--font-body); font-size: 1rem; padding: 6px 0;
}
.search-page-form input[type="search"]::placeholder { color: var(--text-muted); }

.search-summary { margin-bottom: var(--space-lg); font-size: 0.9rem; }
.search-group { margin-bottom: var(--space-xl); }
.search-group-count {
    font-size: 0.72rem; font-weight: 600; color: var(--text-muted);
    background: var(--bg-card-alt); border-radius: 999px; padding: 1px 8px; margin-left: 4px;
}
.search-results { display: flex; flex-direction: column; gap: 6px; }
.search-result {
    display: block; text-decoration: none;
    background: var(--bg-card); border: 1px solid var(--border);
    border-left: 3px solid var(--campaign-accent-border);
    border-radius: var(--radius); padding: 10px 14px;
    transition: border-color 0.12s, background 0.12s;
}
.search-result:hover { background: var(--bg-card-alt); border-left-color: var(--campaign-accent); }
.search-result-title { font-family: var(--font-heading); font-size: 0.95rem; color: var(--gold); margin-bottom: 3px; }
.search-result-snippet { font-size: 0.86rem; color: var(--text-dim); line-height: 1.5; }
.search-result-meta { font-size: 0.75rem; color: var(--text-muted); margin-top: 4px; }
.search-result mark, .search-result-snippet mark {
    background: var(--gold-faint); color: var(--gold-bright);
    border-radius: 2px; padding: 0 2px;
}
.search-page-form kbd, .empty-desc kbd {
    font-family: var(--font-ui); font-size: 0.78em;
    background: var(--bg-input); border: 1px solid var(--border-mid);
    border-radius: 3px; padding: 1px 5px; color: var(--text-dim);
}

/* Rendered @-mention links inside rich content */
.mention {
    color: var(--gold-bright); text-decoration: none;
    font-weight: 600; border-radius: 2px; padding: 0 1px;
    background: var(--gold-faint);
}
.mention:hover { text-decoration: underline; }

/* @-mention autocomplete menu (Quill editor) */
.mention-menu {
    position: absolute; z-index: 300; display: none;
    min-width: 200px; max-width: 300px; max-height: 260px; overflow-y: auto;
    background: var(--bg-card); border: 1px solid var(--border-mid);
    border-radius: var(--radius-lg); box-shadow: 0 8px 24px rgba(0,0,0,0.45);
    padding: 4px;
}
.mention-menu.open { display: block; }
.mention-opt {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 8px; border-radius: var(--radius); cursor: pointer;
    font-size: 0.88rem; color: var(--text);
}
.mention-opt.active, .mention-opt:hover { background: var(--gold-faint); }
.mention-opt-type {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; flex: 0 0 auto;
    font-size: 0.7rem; font-weight: 700; border-radius: 50%;
    background: var(--bg-input); color: var(--text-dim);
}
.mention-opt-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ══════════════════════════════════════════════════════════════════════
   Entity images — carousel, GM controls, lightbox
   Ported from the dicelords carousel/lightbox and re-tokenised. The
   carousel lives in the portrait column on entity pages, so it must never
   exceed its container's width.
   ══════════════════════════════════════════════════════════════════════ */
.entity-images { margin: 0; }
/* Standalone block (sessions have no portrait column) — keep it from spanning
   the whole content width on a wide screen. */
.entity-images-block { max-width: 640px; margin: 0 0 var(--space-lg); }

.carousel { position: relative; max-width: 100%; margin: 0 auto var(--space-md); }
.carousel-viewport {
    overflow: hidden;
    border: 1px solid var(--border-mid);
    border-radius: var(--radius);
    background: var(--bg-input);
}
.carousel-track { display: flex; transition: transform 320ms ease; }
.carousel-slide {
    flex: 0 0 100%;
    min-width: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
}
.carousel-slide a { display: block; max-width: 100%; line-height: 0; }
.carousel-slide img {
    display: block;
    max-width: 100%;
    max-height: 68vh;
    width: auto;             /* keep aspect ratio; never upscale past intrinsic size */
    height: auto;
    cursor: zoom-in;
}

/* Prev/next arrows + counter overlay the viewport (rendered only when >1 image). */
.carousel-btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 36px; height: 36px;
    display: flex; align-items: center; justify-content: center;
    font-size: 1.5rem; line-height: 1;
    color: var(--text);
    background: rgba(8, 6, 4, 0.62);
    border: 1px solid var(--gold-border);
    border-radius: 50%;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
.carousel-btn:hover { background: rgba(8, 6, 4, 0.9); color: var(--gold-bright); }
.carousel-btn.prev { left: 8px; }
.carousel-btn.next { right: 8px; }
.carousel-counter {
    position: absolute;
    bottom: 8px; right: 10px;
    font-family: var(--font-ui);
    font-size: 0.66rem; font-weight: 600; letter-spacing: 0.1em;
    color: var(--text);
    background: rgba(8, 6, 4, 0.7);
    padding: 3px 8px;
    border-radius: var(--radius);
}

/* GM-only per-image controls, in the slide's figcaption. */
.ei-controls {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    flex-wrap: wrap;
    width: 100%;
    padding: var(--space-xs) 2px var(--space-sm);
    font-family: var(--font-ui);
    font-size: 0.75rem;
}
.ei-controls .inline-form { display: inline; margin: 0; }
.ei-controls .ei-del { margin-left: auto; }
.ei-btn {
    background: none;
    border: 1px solid var(--border-mid);
    color: var(--text-dim);
    border-radius: var(--radius);
    font-family: var(--font-ui);
    font-size: 0.72rem;
    line-height: 1;
    padding: 3px 7px;
    cursor: pointer;
    transition: color var(--transition), border-color var(--transition);
}
.ei-btn:hover { color: var(--gold-bright); border-color: var(--gold-border); }
.ei-btn-danger:hover { color: var(--red-text); border-color: var(--red); }
.ei-tag {
    display: inline-flex; align-items: center;
    padding: 2px 7px;
    border-radius: var(--radius);
    font-size: 0.68rem; font-weight: 600;
    letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--gold); background: var(--gold-faint);
    border: 1px solid var(--gold-border);
}
.ei-tag-ai { color: var(--blue-text); background: var(--blue); border-color: transparent; cursor: help; }

/* Generation panel below the carousel (GM only, AI images enabled). */
.ei-panel { font-family: var(--font-ui); font-size: 0.82rem; }
.ei-chip {
    display: flex; align-items: center; gap: var(--space-xs);
    margin: 0 0 var(--space-sm);
    padding: var(--space-sm);
    border: 1px solid var(--gold-border);
    border-radius: var(--radius);
    background: var(--gold-faint);
    color: var(--text-dim);
}
.ei-error {
    display: flex; align-items: flex-start; gap: var(--space-sm);
    flex-wrap: wrap;
    margin-bottom: var(--space-sm);
    padding: var(--space-sm);
    border: 1px solid var(--red);
    border-radius: var(--radius);
    background: rgba(122, 31, 46, 0.15);
    color: var(--red-text);
}
.ei-gen { margin-bottom: var(--space-sm); }
.ei-gen > summary {
    cursor: pointer;
    display: flex; align-items: center; gap: var(--space-xs);
    padding: var(--space-xs) 0;
    color: var(--text-dim);
}
.ei-gen > summary:hover { color: var(--gold-bright); }
.ei-gen textarea { width: 100%; font-size: 0.82rem; }
.ei-label {
    display: block;
    margin-top: var(--space-xs);
    font-size: 0.72rem; font-weight: 600;
    letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--text-dim);
}
.ei-note { margin: var(--space-xs) 0; color: var(--text-muted); font-size: 0.76rem; }
.ei-actions {
    display: flex; align-items: center; gap: var(--space-sm);
    flex-wrap: wrap;
    margin-top: var(--space-sm);
}
.ei-cap { color: var(--text-muted); font-size: 0.75rem; }

/* Lightbox popout — clicking a carousel image opens it here instead of leaving. */
body.lb-lock { overflow: hidden; }
.lightbox {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: none;
    align-items: center;
    justify-content: center;
    background: rgba(6, 5, 3, 0.93);
}
.lightbox.open { display: flex; }
.lb-figure {
    margin: 0;
    max-width: 92vw; max-height: 92vh;
    display: flex; flex-direction: column; align-items: center;
}
.lb-figure img {
    max-width: 92vw; max-height: 90vh;
    width: auto; height: auto;
    border: 1px solid var(--gold-border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
}
.lb-close, .lb-nav {
    position: absolute;
    background: rgba(10, 8, 4, 0.55);
    border: 1px solid var(--gold-border);
    color: var(--gold);
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: background var(--transition), color var(--transition);
}
.lb-close:hover, .lb-nav:hover { background: rgba(10, 8, 4, 0.9); color: var(--gold-bright); }
.lb-close { top: 16px; right: 20px; width: 42px; height: 42px; font-size: 1rem; border-radius: 50%; }
.lb-nav {
    top: 50%; transform: translateY(-50%);
    width: 52px; height: 52px;
    font-size: 2rem; line-height: 1;
    border-radius: 50%;
}
.lb-prev { left: 16px; }
.lb-next { right: 16px; }

@media (max-width: 720px) {
    .lb-close { top: 10px; right: 10px; width: 38px; height: 38px; }
    .lb-nav { width: 42px; height: 42px; font-size: 1.6rem; }
    .lb-prev { left: 6px; }
    .lb-next { right: 6px; }
}
