/* ── Character panel (protagonist + every character — one template) ── */
.character-section {
    flex: 1; overflow: hidden;
    display: flex; gap: 1.25rem;
    padding: 1.1rem 1.5rem 1rem;
}

.character-bio {
    flex: 1; display: flex; flex-direction: column; gap: 0.55rem; overflow: hidden; min-width: 0;
}

.portrait-panel {
    width: 170px; flex-shrink: 0;
    display: flex; flex-direction: column; gap: 0.6rem;
}

.portrait-frame {
    width: 100%; aspect-ratio: 2 / 3;
    border: 1px solid var(--border); border-radius: 8px;
    background: var(--panel2);
    display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 0.5rem;
    overflow: hidden; position: relative;
}

.portrait-frame img {
    position: absolute; inset: 0;
    width: 100%; height: 100%; object-fit: cover; border-radius: 7px; display: block;
}

/* Spinner overlay while a portrait is generating — reuses the modal-spin
   keyframes; works whether or not there's already a portrait underneath. */
.portrait-frame.generating::after {
    content: ''; position: absolute; inset: 0;
    background: rgba(6,11,20,0.72); z-index: 2;
}
.portrait-frame.generating::before {
    content: ''; position: absolute; top: 50%; left: 50%;
    width: 28px; height: 28px; margin: -14px 0 0 -14px;
    border: 3px solid var(--border); border-top-color: var(--accent);
    border-radius: 50%; animation: modal-spin 0.8s linear infinite;
    z-index: 3;
}

.portrait-edit-btn {
    position: absolute; bottom: 0.3rem; right: 0.4rem; z-index: 4;
    padding: 0; background: none; border: none;
    color: var(--muted); cursor: pointer; font-size: 0.95rem; line-height: 1;
    text-shadow: 0 1px 3px rgba(0,0,0,0.7);
    opacity: 0; transition: opacity 0.18s, color 0.18s;
}
.portrait-frame:hover .portrait-edit-btn,
.portrait-edit-btn:focus-visible { opacity: 1; }
.portrait-edit-btn:hover { color: var(--gold); }

/* Shell and rows are .floating-menu / .menu-item (static/css/components.css) —
   this menu adds nothing of its own. */

.portrait-age-carousel {
    display: flex; align-items: center; gap: 0.15rem; margin-top: 0.45rem;
    background: var(--wash); border-radius: 6px;
    padding: 0.15rem 0.2rem;
}
.portrait-age-track {
    flex: 1; min-width: 0;
    display: flex; gap: 0.15rem;
    overflow-x: auto; scrollbar-width: none;
    cursor: grab; touch-action: pan-y;
}
.portrait-age-track::-webkit-scrollbar { display: none; }
.portrait-age-track.dragging { cursor: grabbing; }
.portrait-age-track.dragging .portrait-age-chip { pointer-events: none; }

/* Arrows are hidden (visibility, so the track doesn't reflow) until the
   chips overflow — see _syncAgeNav(). */
.portrait-age-nav, .portrait-age-add {
    flex-shrink: 0; padding: 0 0.2rem;
    background: none; border: none; cursor: pointer;
    color: var(--muted); transition: color 0.18s;
    font-family: 'Cormorant Garamond', serif; line-height: 1;
}
.portrait-age-nav { font-size: 0.5rem; visibility: hidden; }
.portrait-age-add { font-size: 0.9rem; margin-left: 0.15rem; }
.portrait-age-nav:hover, .portrait-age-add:hover { color: var(--gold); }

/* Gold is the selected state only — unselected chips stay plain, or the whole
   strip reads as highlighted. Active matches .pill-toggle.active. */
.portrait-age-chip {
    flex-shrink: 0; padding: 0.15rem 0.4rem;
    border: 1px solid transparent;
    background: none;
    border-radius: 5px;
    color: var(--muted); cursor: pointer;
    font-family: 'Nunito', sans-serif; font-size: 0.72rem; line-height: 1.3;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
/* The default (any-age) chip leads every strip — set apart from the numbers so
   it reads as a mode rather than as an age. */
.portrait-age-chip.default {
    font-family: 'Cormorant Garamond', serif;
    font-size: 0.78rem; font-style: italic;
}
.portrait-age-chip:hover { background: var(--gold-wash); color: var(--text); }
.portrait-age-chip.active {
    background: var(--gold-wash-2);
    border-color: var(--gold);
    color: var(--gold);
}

.portrait-placeholder {
    display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 0.4rem;
    color: var(--muted); text-align: center; padding: 0.5rem;
}
.portrait-placeholder .p-ornament { font-size: 1.1rem; opacity: 0.3; }
.portrait-placeholder .p-label    { font-size: 0.68rem; letter-spacing: 0.1em; font-style: italic; }

/* ── Story backup ── */
.backup-btn-row { display: flex; gap: 0.6rem; flex-wrap: wrap; }

/* ── Scene header (bg image + portraits, above posts) ── */
.scene-header {
    position: relative;
    height: 25vh;
    flex-shrink: 0;
    overflow: hidden;
}
.scene-regen-btn {
    position: absolute; top: 8px; right: 8px; z-index: 5;
    background: rgba(0,0,0,0.52); border: 1px solid var(--wash-2);
    border-radius: 5px; color: var(--muted); cursor: pointer;
    font-size: 0.7rem; padding: 0.28rem 0.6rem;
    font-family: 'Cormorant Garamond', serif; letter-spacing: 0.07em;
    transition: all 0.15s; opacity: 0;
}
.scene-header:hover .scene-regen-btn { opacity: 1; }
.scene-regen-btn:hover  { background: rgba(0,0,0,0.75); border-color: var(--gold); color: var(--gold); }
.scene-regen-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.scene-bg-full {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover; pointer-events: none;
    transition: opacity 1.2s ease, filter 0.6s ease;
}
/* Last scene stays up, blurred, while the next one generates server-side —
   layers underneath the existing overlay/fade (static/app/features/story/scene.js). */
.scene-bg-full.pending {
    filter: blur(10px) brightness(0.8);
    transform: scale(1.06); /* hides the blur's soft edge past the box */
}
/* The same spread carries much further against a light page — pull it in. */
body.theme-cream .scene-bg-full.pending {
    filter: blur(5px) brightness(0.8);
}
/* Overlay: subtle tint at the top, blending to exactly --bg at the bottom so
   the scene dissolves into the feed. The stops have to be the theme's own page
   colour — left on navy, a cream page ended in a dark band with the portraits
   sitting in it. */
.scene-bg-overlay {
    position: absolute; inset: 0;
    background: var(--scene-fade);
    pointer-events: none;
}
/* Fades the scene bg into the feed below, same technique as .post-input-area::before */
.scene-header::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 48px;
    background: linear-gradient(to bottom, transparent, var(--bg));
    pointer-events: none;
}
/* Portraits sit at the bottom of the header, inside the blend. Explicitly
   above the bg image and its overlay rather than relying on DOM order, so the
   blur the bg picks up while the next scene generates never touches them. */
.scene-portraits-inner {
    position: absolute; bottom: 20px; left: 0; right: 0;
    z-index: 3;
    display: flex; justify-content: space-between; align-items: flex-end;
    padding: 0 14px; pointer-events: none;
}
.scene-portrait-wrap    { position: relative; }
.scene-protagonist-slot { pointer-events: all; }
.scene-char-slots       { display: flex; gap: 20px; align-items: flex-end; pointer-events: all; }
.scene-protagonist-slot .scene-portrait-thumb { height: 19vh; width: calc(19vh * 2 / 3); }
.scene-char-slots .scene-portrait-thumb       { height: 15vh; width: calc(15vh * 2 / 3); }

.scene-portrait-thumb {
    border-radius: 6px; border: 1px solid var(--gold);
    object-fit: cover; display: block;
    box-shadow: 0 0 10px rgba(0,0,0,0.8), inset 0 -40px 40px rgba(0,0,0,0.35);
}
.scene-portrait-label {
    position: absolute; bottom: 0; left: -4px; right: -4px;
    font-size: 0.62rem; letter-spacing: 0.07em; text-align: center;
    background: rgba(0,0,0,0.78); color: var(--gold);
    padding: 4px 5px; border-radius: 0 0 5px 5px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    font-family: 'Cormorant Garamond', serif; font-style: italic;
    opacity: 0; transform: translateY(4px);
    transition: opacity 0.18s, transform 0.18s; pointer-events: none;
}
.scene-portrait-wrap:hover .scene-portrait-label { opacity: 1; transform: translateY(0); }

/* ── Images section ── */
.images-section {
    flex: 1;
    padding: 1.75rem 2rem;
    display: flex; flex-direction: column; gap: 0.6rem;
    overflow-y: auto;
}
.style-presets {
    display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.4rem 0 0.2rem;
}
/* The preset buttons themselves are .pill-toggle (static/css/components.css);
   .style-preset-btn stays on them as the hook config.js queries by. */
/* ── Theme picker (Settings → Theme) ── */
/* Grid rather than wrapping flex: a flex row lets whatever lands alone on the
   last line stretch to fill it, so a third card came out double-width.
   auto-fill keeps the empty tracks, so every card is one column wide. */
.theme-picker {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 0.75rem;
    margin-top: 0.5rem;
}
.theme-card {
    display: flex; flex-direction: column; gap: 0.35rem;
    padding: 0.85rem;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--wash);
    cursor: pointer;
    text-align: start;
    transition: border-color 0.15s, background 0.15s;
}
.theme-card:hover { border-color: var(--gold); background: var(--gold-wash); }
.theme-card.active { border-color: var(--gold); background: var(--gold-wash-2); }
.theme-swatch {
    display: flex; height: 30px; border-radius: 6px; overflow: hidden;
    border: 1px solid var(--border-strong);
    margin-bottom: 0.15rem;
}
.theme-swatch > span { flex: 1; }
.theme-card-name {
    font-family: 'Cormorant Garamond', serif;
    font-size: 1rem; color: var(--cream); letter-spacing: 0.04em;
}
.theme-card.active .theme-card-name { color: var(--gold); }
.theme-card-sub { font-size: 0.75rem; color: var(--muted); line-height: 1.45; }

.style-extra-textarea {
    width: 100%;
    background: var(--wash);
    border: 1px solid var(--wash-2);
    border-radius: 8px;
    color: var(--text);
    padding: 0.6rem 0.8rem;
    font-size: 0.85rem;
    font-family: inherit;
    resize: vertical;
    box-sizing: border-box;
    margin-top: 0.3rem;
}
.style-extra-textarea:focus { outline: none; border-color: var(--gold-line-2); }
#scenePromptTextarea { background: var(--input-dark); border: none; resize: none; }
#scenePromptTextarea:focus { border: none; }

/* ── API Key section ── */
.apikey-section {
    flex: 1;
    padding: 1.75rem 2rem;
    display: flex; flex-direction: column; gap: 1.25rem; max-width: 540px;
    overflow-y: auto;
}
.apikey-heading {
    font-family: 'Cormorant Garamond', serif;
    font-size: 1.05rem; font-weight: 300; color: var(--cream); letter-spacing: 0.05em;
}
.apikey-info { font-size: 0.83rem; color: var(--muted); line-height: 1.65; }
.apikey-info code {
    background: var(--panel2); border: 1px solid var(--border); border-radius: 3px;
    padding: 0.1em 0.4em; font-size: 0.88em; color: var(--cream);
}
.apikey-field { display: flex; gap: 0.5rem; }
.apikey-input {
    flex: 1;
    background: var(--panel2); border: 1px solid var(--border-strong); border-radius: 6px;
    padding: 0.6rem 0.85rem; color: var(--cream);
    font-family: 'Courier New', Courier, monospace; font-size: 0.88rem; outline: none;
    transition: border-color 0.18s; letter-spacing: 0.04em;
}
.apikey-input:focus { border-color: var(--accent); }
.apikey-input.masked { -webkit-text-security: disc; letter-spacing: 0.1em; }
.apikey-toggle {
    background: var(--panel2); border: 1px solid var(--border-strong); border-radius: 6px;
    color: var(--muted); cursor: pointer; padding: 0.6rem 0.75rem; font-size: 0.75rem;
    transition: all 0.15s; flex-shrink: 0;
}
.apikey-toggle:hover { border-color: var(--accent); color: var(--accent); }
.apikey-save-btn {
    align-self: flex-start;
    background: var(--btn-grad);
    border: 1px solid var(--btn-border); border-radius: 6px; color: var(--btn-ink);
    cursor: pointer; padding: 0.5rem 1.25rem;
    font-family: 'Cormorant Garamond', serif; font-size: 0.95rem; letter-spacing: 0.08em;
    transition: all 0.18s;
}
.apikey-save-btn:hover:not(:disabled) {
    background: var(--btn-grad-hi);
    box-shadow: 0 0 12px rgba(100,170,230,0.25);
}
.apikey-save-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.apikey-divider { border: none; border-top: 1px solid var(--seam); margin: 0.25rem 0; }

/* ── Generate Story Bible — wider prompt + inspiration cards ── */
.generate-section {
    max-width: none;
    flex-direction: row;
    gap: 1.75rem;
}
.generate-main {
    flex: 1;
    min-width: 0;
    display: flex; flex-direction: column; gap: 1.1rem;
}
.generate-headline {
    font-family: 'Cormorant Garamond', serif;
    font-weight: 500;
    font-size: 1.9rem;
    letter-spacing: 0.02em;
    color: var(--cream);
    margin-bottom: -0.3rem;
}
.generate-input-wrap {
    position: relative;
    flex: 1;
    display: flex;
    min-height: 146px;
}
.generate-textarea {
    border: none;
    background: var(--input-dark);
    border-radius: 10px;
    padding-right: 7rem;
}
.generate-textarea:focus { border: none; }
.generate-send-btn {
    position: absolute;
    right: 0.65rem; bottom: 0.65rem;
    height: 36px;
    padding: 0 1.1rem;
    display: flex; align-items: center; justify-content: center;
    font-size: 0.78rem; font-weight: 500; letter-spacing: 0.02em;
    background: var(--accent-wash);
    border: 1px solid var(--accent);
    border-radius: 999px;
    color: var(--accent);
    cursor: pointer;
    transition: all 0.2s;
}
.generate-send-btn:hover:not(:disabled) {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--bg);
}
.generate-send-btn:disabled { opacity: 0.28; cursor: not-allowed; }

.generate-inspiration {
    flex-shrink: 0;
    width: 280px;
    align-self: center;
    display: flex; flex-direction: column; gap: 0.65rem;
}
.inspiration-label {
    font-size: 0.6rem; color: var(--muted); letter-spacing: 0.08em;
    text-transform: uppercase; flex-shrink: 0;
}
.inspiration-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1rem;
}
.inspiration-card {
    position: relative;
    background: none; border: none; border-radius: 12px;
    cursor: pointer; padding: 0; overflow: hidden;
    aspect-ratio: 3 / 4;
}
.inspiration-card img {
    width: 100%; height: 100%; object-fit: cover; display: block;
    filter: grayscale(70%) brightness(0.6);
    transition: filter 0.2s ease, transform 0.3s ease;
}
.inspiration-card:hover img {
    filter: grayscale(0%) brightness(0.85);
    transform: scale(1.04);
}
.inspiration-card-label {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    text-align: center; padding: 0.4rem;
    background: rgba(0,0,0,0.35);
    font-size: 0.78rem; color: #faf4ec;
    font-family: 'Nunito', sans-serif; line-height: 1.25;
    opacity: 0;
    transition: opacity 0.2s ease;
}
.inspiration-card:hover .inspiration-card-label { opacity: 1; }
/* Rows, not a column of prose to read — so it does not want the 540px measure
   the other tabs share. At that width the dictionary row's label was squeezed to
   six lines, and the overflow that caused drew .apikey-section's scrollbar
   halfway across the panel, that being both the measure and the scroll box. */
#generalSection { max-width: 760px; }

.general-list {
    display: flex; flex-direction: column;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--wash);
    overflow: hidden;
    /* The clipping above is only for the rounded corners. Left shrinkable, a
       list taller than the section is squeezed and its last rows cut off —
       hidden, with no scrollbar to say so. It keeps its height; the section
       around it scrolls. */
    flex-shrink: 0;
}
.general-row {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem;
    padding: 0.9rem 1.1rem;
    border-bottom: 1px solid var(--seam);
}
.general-row:last-child { border-bottom: none; }
.general-row-text { display: flex; flex-direction: column; gap: 0.2rem; }
.general-row-label {
    font-family: 'Cormorant Garamond', serif; font-size: 1rem; color: var(--cream); letter-spacing: 0.03em;
}
.general-row-sub { font-size: 0.75rem; color: var(--muted); line-height: 1.4; }
.general-row-btn {
    background: var(--panel2); border: 1px solid var(--border-strong); border-radius: 6px;
    color: var(--text); cursor: pointer; padding: 0.45rem 1rem;
    font-family: 'Nunito', sans-serif; font-size: 0.8rem;
    transition: all 0.15s; flex-shrink: 0;
}
.general-row-btn:hover { border-color: var(--accent); color: var(--accent); }
.general-row-btn.danger:hover { border-color: var(--danger); color: var(--danger); }
/* A row whose setting is two things: what it does, and what it does it in. */
.general-row-controls { display: flex; align-items: center; gap: 0.5rem; flex-shrink: 0; }
.general-row-select {
    background: var(--panel2); border: 1px solid var(--border-strong); border-radius: 6px;
    color: var(--text); cursor: pointer; padding: 0.45rem 0.5rem;
    font-family: 'Nunito', sans-serif; font-size: 0.8rem;
    outline: none;
    width: 9rem; text-align: start;
    display: flex; align-items: center; justify-content: space-between; gap: 0.4rem;
}
.general-row-select:hover { border-color: var(--accent); }
.general-row-select:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}
.general-row-select:disabled:hover { border-color: var(--border-strong); }
/* The caret the native control used to draw for itself. */
.general-row-select::after {
    content: '▾'; color: var(--muted); font-size: 0.7rem;
    transition: transform 0.15s;
}
.general-row-select.open::after { transform: rotate(180deg); }
.general-row-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.general-row-btn:disabled:hover { border-color: var(--border-strong); color: var(--text); }
/* The list itself, on the shared .floating-menu shell. Long enough to read as a
   list, short enough to stay inside the settings panel it opens over. */
.lang-menu { max-height: 15rem; overflow-y: auto; min-width: 9rem; }
.lang-menu .menu-item.picked { color: var(--accent); }
/* The padded thumb the themes give the feed and the sidebar, said once here so
   the list is right on the base palette too — --scrollbar is themed already. */
.lang-menu::-webkit-scrollbar { width: 11px; }
.lang-menu::-webkit-scrollbar-thumb {
    background: var(--scrollbar); background-clip: padding-box;
    border: 3px solid transparent; border-radius: 999px;
}
.lang-menu::-webkit-scrollbar-thumb:hover { background: var(--muted); background-clip: padding-box; }
/* ── Content — three things you own, not six operations in a list. A row each
   flattened them to equal weight; grouped by what they act on, the save/load
   pairs read as one thing with two verbs. Clearing is out of the grid entirely,
   below a rule, so nothing destructive sits inside the ordinary choices. ── */
#contentSection { max-width: none; }
.content-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
    gap: 0.9rem;
}
.content-card {
    display: flex; flex-direction: column;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--wash);
    padding: 1.1rem 1.15rem 1rem;
}
.content-card-title {
    font-family: 'Cormorant Garamond', serif;
    font-size: 0.9rem; letter-spacing: 0.15em; text-transform: uppercase;
    color: var(--cream);
}
/* Grows so the buttons sit on one line across all three, whatever the copy. */
.content-card-sub {
    flex: 1;
    margin-top: 0.4rem;
    font-size: 0.78rem; color: var(--muted); line-height: 1.5;
}
.content-card-actions {
    display: flex; flex-wrap: wrap; gap: 0.45rem;
    margin-top: 0.9rem;
}
.content-danger {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem;
    margin-top: 0.35rem;
    padding-top: 1.2rem;
    border-top: 1px solid var(--seam);
}
.content-danger-text { display: flex; flex-direction: column; }
.apikey-status {
    font-size: 0.78rem; padding: 0.5rem 0.75rem; border-radius: 5px; display: none;
}
.apikey-status.ok  { display: block; background: rgba(126,200,138,0.12); border: 1px solid #7ec88a55; color: #7ec88a; }
.apikey-status.err { display: block; background: rgba(212,138,138,0.12); border: 1px solid #d48a8a55; color: var(--danger); }
