/* Writer base styles. Colors/typography come from /theme.css custom properties. */

* { box-sizing: border-box; }

html { color-scheme: light; }
html.dark { color-scheme: dark; }

body {
	margin: 0;
	font-family: var(--font-body);
	background: var(--color-bg);
	color: var(--color-text);
	line-height: 1.6;
	min-height: 100vh;
	display: flex;
	flex-direction: column;
}

a { color: var(--color-primary); }

/* ── Form controls: one consistent look everywhere ───────────────────────────
   Base styling for every text-like input, textarea and select so no control
   ever falls back to the raw browser default ("utilitarian system fields").
   These are element selectors (lowest specificity) so ANY existing class rule
   — .tb-select, .color-field, .note-title-input, etc. — still wins and keeps
   its bespoke look; this only fills in the un-styled controls. Radios,
   checkboxes, file and colour inputs are deliberately excluded. */
input[type="text"], input[type="email"], input[type="password"],
input[type="search"], input[type="number"], input[type="url"],
input[type="date"], input[type="time"], input[type="tel"],
textarea, select {
	font: inherit;
	padding: 0.5rem 0.7rem;
	border: 1px solid var(--color-border);
	border-radius: var(--radius);
	background: var(--color-surface);
	color: var(--color-text);
	max-width: 100%;
}
textarea { line-height: 1.55; }
select { cursor: pointer; }
input[type="text"]:focus, input[type="email"]:focus, input[type="password"]:focus,
input[type="search"]:focus, input[type="number"]:focus, input[type="url"]:focus,
input[type="date"]:focus, input[type="time"]:focus, input[type="tel"]:focus,
textarea:focus, select:focus {
	outline: none;
	border-color: var(--color-primary);
	box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-primary) 30%, transparent);
}

/* A required-field marker that stays on the label's own line. Wrap the label
   text + asterisk in <span class="lbl">…<span class="req">*</span></span> so
   they form one inline unit inside a column-flex <label>. */
.lbl { display: inline-flex; align-items: baseline; gap: 0.3rem; }
.req { color: #d24b3f; }

.site-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: 0.75rem 1.25rem;
	border-bottom: 1px solid var(--color-border);
	background: var(--color-surface);
}

.site-title {
	font-family: var(--font-serif);
	font-size: 1.35rem;
	font-weight: 700;
	text-decoration: none;
	color: var(--color-text);
}

/* The theme toggle is an icon button styled like the nav icon links (it carries
   .nav-icon-link too); this only adds the button reset + pointer. */
.theme-toggle { background: none; border: 0; cursor: pointer; }

.site-main {
	flex: 1;
	width: 100%;
	max-width: var(--content-width);
	margin: 0 auto;
	padding: 2rem 1.25rem;
}

.site-footer {
	padding: 1rem 1.25rem;
	border-top: 1px solid var(--color-border);
	color: var(--color-text-muted);
	font-size: 0.9rem;
	text-align: center;
}

.hero {
	max-width: 42rem;
	margin: 3rem auto;
	text-align: center;
}

.hero h1 {
	font-family: var(--font-serif);
	font-size: 2.6rem;
	margin: 0 0 0.5rem;
}

.hero .tagline {
	color: var(--color-text-muted);
	font-size: 1.15rem;
	margin-top: 0;
}

/* ── Buttons & links ──
   Compact by default (matching the story-overview action buttons) — no big
   chunky buttons anywhere. `.small` is a tighter variant for dense icon rows. */
.button, button[type="submit"] {
	display: inline-block;
	padding: 0.34rem 0.8rem;
	border: 1px solid var(--color-primary);
	border-radius: var(--radius);
	background: var(--color-primary);
	color: var(--color-primary-contrast);
	font: inherit;
	font-size: 0.9rem;
	line-height: 1.35;
	text-decoration: none;
	cursor: pointer;
}
/* `hidden` must actually hide. The rule above sets `display`, which outranks the
   browser's own [hidden] { display: none }, so any button we hide from script —
   the PWA install button, the push on/off toggle — would otherwise sit there as
   a live-looking control that does nothing. */
.button[hidden], button[hidden] { display: none; }
button.danger, .button.danger { background: #b3372f; border-color: #b3372f; color: #fff; }
.button.small, button.small { padding: 0.2rem 0.55rem; font-size: 0.82rem; }
.link-button {
	background: none; border: none; padding: 0; font: inherit;
	color: var(--color-primary); text-decoration: underline; cursor: pointer;
}
.inline-form { display: inline; }
.site-nav { display: flex; align-items: center; gap: 0.9rem; }
.site-nav a { text-decoration: none; }

/* Account menu — avatar dropdown (Settings / Log out). */
.user-menu { position: relative; }
.user-menu-trigger { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 0.5rem; }
.user-menu-trigger::-webkit-details-marker { display: none; }
.user-menu-trigger::marker { content: ''; }
.user-menu-trigger:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; border-radius: 50%; }
.user-menu-name { display: none; }
.user-menu-panel {
	position: absolute; top: calc(100% + 0.45rem); right: 0; z-index: 200;
	min-width: 9rem; padding: 0.35rem;
	background: var(--color-surface); border: 1px solid var(--color-border);
	border-radius: var(--radius); box-shadow: 0 10px 30px rgba(0, 0, 0, 0.28);
	display: flex; flex-direction: column; gap: 0.1rem;
}
/* Invisible bridge across the gap between the avatar and the panel, so the
   pointer never leaves .user-menu on the way down (which would close it). */
.user-menu-panel::before { content: ''; position: absolute; left: 0; right: 0; top: -0.55rem; height: 0.55rem; }
.user-menu:not([open]) .user-menu-panel { display: none; }
.user-menu-panel a, .user-menu-panel .user-menu-item {
	display: block; width: 100%; box-sizing: border-box; text-align: left; white-space: nowrap;
	padding: 0.45rem 0.7rem; border-radius: var(--radius);
	background: none; border: none; font: inherit; font-weight: 500; cursor: pointer;
	color: var(--color-text); text-decoration: none;
}
.user-menu-panel a:hover, .user-menu-panel .user-menu-item:hover { background: color-mix(in srgb, var(--color-primary) 12%, transparent); }

/* ── Hamburger nav (small screens) ───────────────────────────────────────────
   CSS-only disclosure: a hidden checkbox toggled by the burger label reveals the
   nav as a full-width dropdown. On wide screens the burger is hidden and the nav
   is the normal inline row. In the dropdown, icon-only links reveal their
   aria-label as text so the menu is readable. */
.nav-toggle { display: none; }
.nav-burger { display: none; }
@media (max-width: 48rem) {
	.site-header { flex-wrap: wrap; }
	.nav-burger {
		display: inline-flex; align-items: center; justify-content: center;
		width: 2.5rem; height: 2.5rem; margin-left: auto; cursor: pointer;
		font-size: 1.4rem; line-height: 1; border-radius: var(--radius); color: var(--color-text);
	}
	.nav-burger::before { content: "\2630"; } /* ☰ */
	.nav-toggle:checked ~ .nav-burger::before { content: "\2715"; } /* ✕ */
	.nav-burger:hover { background: color-mix(in srgb, var(--color-primary) 12%, transparent); }
	.site-nav {
		display: none; order: 3; width: 100%;
		flex-direction: column; align-items: stretch; gap: 0.1rem;
		padding: 0.4rem 0;
	}
	.nav-toggle:checked ~ .site-nav { display: flex; }
	.site-nav > a, .site-nav > .nav-icon-link, .site-nav > .inline-form > .link-button {
		width: 100%; box-sizing: border-box; padding: 0.6rem 0.75rem; border-radius: var(--radius); text-align: left;
	}
	.site-nav > .inline-form { width: 100%; }
	.site-nav > a:hover, .site-nav > .nav-icon-link:hover { background: color-mix(in srgb, var(--color-primary) 10%, transparent); }
	/* Icon links are icon-only by default; in the menu, show their label too. */
	.site-nav .nav-icon-link { justify-content: flex-start; gap: 0.65rem; }
	.site-nav .nav-icon-link::after { content: attr(aria-label); font-size: 0.95rem; font-weight: 500; }
	.site-nav .nav-notif-pill { position: static; margin-left: auto; }
	/* Account menu expands inline within the drawer (avatar + name, then items). */
	.site-nav > .user-menu { width: 100%; }
	.site-nav .user-menu-trigger { width: 100%; box-sizing: border-box; padding: 0.6rem 0.75rem; border-radius: var(--radius); gap: 0.65rem; }
	.site-nav .user-menu-trigger:hover { background: color-mix(in srgb, var(--color-primary) 10%, transparent); }
	.site-nav .user-menu-name { display: inline; font-size: 0.95rem; font-weight: 500; }
	.site-nav .user-menu-panel { position: static; box-shadow: none; border: none; background: transparent; min-width: 0; padding: 0.1rem 0 0.2rem 2.6rem; }
}

/* ── Flash messages ── */
.flash { padding: 0.6rem 1rem; border-radius: var(--radius); margin-bottom: 1rem; }
.flash-ok { background: color-mix(in srgb, var(--color-accent) 15%, transparent); border: 1px solid var(--color-accent); }
.flash-err { background: color-mix(in srgb, #b3372f 12%, transparent); border: 1px solid #b3372f; }

/* ── Forms ── */
.form-card { max-width: 26rem; margin: 2rem auto; }
.form-card h1 { font-family: var(--font-serif); }
.form-card h2 { font-family: var(--font-serif); margin-top: 2.5rem; font-size: 1.15rem; }
.form-card form { display: flex; flex-direction: column; gap: 0.9rem; align-items: flex-start; }
.form-card label { display: flex; flex-direction: column; gap: 0.25rem; width: 100%; }
.form-card input {
	padding: 0.5rem 0.7rem;
	border: 1px solid var(--color-border);
	border-radius: var(--radius);
	background: var(--color-surface);
	color: var(--color-text);
	font: inherit;
	width: 100%;
}
.form-card small, .muted { color: var(--color-text-muted); }
.form-alt { font-size: 0.9rem; color: var(--color-text-muted); }

/* ── Admin ── */
.admin-badge {
	font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em;
	background: var(--color-primary); color: var(--color-primary-contrast);
	border-radius: 4px; padding: 0.1rem 0.4rem; vertical-align: middle;
}
.admin-layout { display: flex; flex: 1; min-height: 0; }
.admin-sidebar {
	width: 12rem; flex-shrink: 0; padding: 1.25rem 0;
	border-right: 1px solid var(--color-border); background: var(--color-surface);
	display: flex; flex-direction: column;
}
.admin-sidebar a { padding: 0.5rem 1.25rem; text-decoration: none; color: var(--color-text); }
.admin-sidebar a.active { background: color-mix(in srgb, var(--color-primary) 12%, transparent); font-weight: 600; }
.admin-main { flex: 1; padding: 1.5rem; min-width: 0; }
.admin-main h1 { font-family: var(--font-serif); margin-top: 0; }
.admin-body { min-height: 100vh; }
/* The admin section tabs live in the hamburger menu on small screens (see
   below); on wide screens they are the left sidebar and this duplicate hides. */
.nav-admin-section { display: none; }
@media (max-width: 48rem) {
	/* Hamburger active: fold the admin tabs into the menu, drop the sidebar. */
	.admin-layout { flex-direction: column; }
	.admin-layout > .admin-sidebar { display: none; }
	.nav-admin-section { display: flex; flex-direction: column; gap: 0.1rem; width: 100%; border-bottom: 1px solid var(--color-border); margin-bottom: 0.35rem; padding-bottom: 0.35rem; }
	.nav-admin-section a {
		width: 100%; box-sizing: border-box; padding: 0.6rem 0.75rem; border-radius: var(--radius);
		text-decoration: none; color: var(--color-text);
	}
	.nav-admin-section a.active { background: color-mix(in srgb, var(--color-primary) 14%, transparent); font-weight: 600; }
	.nav-admin-section a:hover { background: color-mix(in srgb, var(--color-primary) 10%, transparent); }
}

/* ── Tables & stats ── */
.table-wrap { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; font-size: 0.92rem; }
th, td { text-align: left; padding: 0.45rem 0.7rem; border-bottom: 1px solid var(--color-border); vertical-align: top; }
td.actions { white-space: nowrap; }

/* ── Responsive card tables ──────────────────────────────────────────────────
   A table with class "cards" collapses into one stacked card per row on small
   screens: the header row is hidden and each cell shows its column name (from
   the td's data-label) beside its value. Above the breakpoint it is a normal
   table. Mirrors the dragonslaircms pattern. */
@media (max-width: 48rem) {
	table.cards { border: none; }
	table.cards thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
	table.cards, table.cards tbody, table.cards tr, table.cards td, table.cards th { display: block; width: 100%; }
	table.cards tr {
		background: var(--color-surface); border: 1px solid var(--color-border);
		border-radius: var(--radius); padding: 0.4rem 0.85rem; margin-bottom: 0.75rem;
	}
	table.cards td {
		border: none; padding: 0.3rem 0;
		display: flex; justify-content: space-between; align-items: baseline;
		gap: 0.9rem; text-align: right;
	}
	table.cards td[data-label]::before {
		content: attr(data-label); flex: 0 0 auto; text-align: left;
		font-size: 0.7rem; font-weight: 700; text-transform: uppercase;
		letter-spacing: 0.04em; color: var(--color-text-muted);
	}
	/* A row-scoped <th> (e.g. the quota grid's role) is the card's heading. */
	table.cards td.cell-main, table.cards th[scope="row"] { justify-content: flex-start; text-align: left; font-weight: 700; font-size: 1rem; border: none; padding: 0.3rem 0 0.5rem; }
	table.cards td.cell-main::before { display: none; }
	/* Editable card cells (quota grid): keep the control from overflowing. */
	table.cards td > input, table.cards td > select { flex: 0 1 auto; min-width: 0; max-width: 62%; }
	table.cards td.actions, table.cards td.row-actions { justify-content: flex-end; flex-wrap: wrap; white-space: normal; }
	table.cards td:empty { display: none; }
	/* .sprint-table sets its own td border/nowrap later in the file; re-assert the
	   card treatment over it (equal specificity, later source would otherwise win). */
	table.sprint-table.cards td { border: none; white-space: normal; }
}
td.actions form { margin-right: 0.3rem; }
.stat-row { display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem; }
.stat {
	background: var(--color-surface); border: 1px solid var(--color-border);
	border-radius: var(--radius); padding: 0.8rem 1.2rem; min-width: 8rem;
	display: flex; flex-direction: column;
}
.stat strong { font-size: 1.6rem; }
.stat span { color: var(--color-text-muted); font-size: 0.85rem; }
.chip {
	display: inline-block; padding: 0.15rem 0.7rem; border-radius: 999px;
	border: 1px solid var(--color-border); text-decoration: none; font-size: 0.85rem;
}
.chip.active { background: var(--color-primary); color: var(--color-primary-contrast); border-color: var(--color-primary); }
.role-badge {
	font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em;
	background: var(--color-accent); color: #fff; border-radius: 4px; padding: 0.05rem 0.35rem;
}
.settings-form { display: flex; flex-direction: column; gap: 1.1rem; align-items: flex-start; }
/* Site section: stacked labelled fields, each with a full-width input and a
   note underneath. max-width keeps the long URL/email inputs from stretching
   the whole admin main column. */
.settings-site-form { gap: 1rem; width: 100%; max-width: 40rem; }
.settings-site-field { display: flex; flex-direction: column; gap: 0.3rem; width: 100%; }
.settings-site-field input { width: 100%; box-sizing: border-box; }
.settings-site-field small { line-height: 1.4; }
.settings-test-email { display: flex; flex-direction: column; gap: 0.35rem; align-items: flex-start; margin: 0.4rem 0 1.6rem; max-width: 40rem; }

/* ── Branding (icon uploads) ─────────────────────────────────────────────────
   Each item: preview swatches, a format note, upload + reset. */
.branding-item { max-width: 44rem; padding: 1rem 0; border-bottom: 1px solid var(--color-border); }
.branding-item h3 { margin: 0 0 0.6rem; font-size: 1rem; }
.branding-preview { display: flex; gap: 0.6rem; align-items: center; margin-bottom: 0.6rem; }
.branding-note { margin: 0 0 0.7rem; line-height: 1.45; max-width: 40rem; }
.branding-actions { display: flex; gap: 0.8rem 1rem; flex-wrap: wrap; align-items: center; }
.branding-form { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; margin: 0; }
.branding-reset { margin: 0; }
.branding-default-tag { font-size: 0.85rem; }
/* Preview chips: dark and light so a theme-adaptive (currentColor) SVG can be
   seen both ways; a tinted chip for the badge (which the OS masks). */
.branding-swatch {
	display: inline-flex; align-items: center; justify-content: center;
	width: 56px; height: 56px; border-radius: var(--radius); border: 1px solid var(--color-border);
}
.branding-swatch svg, .branding-swatch img { width: 34px; height: 34px; }
.branding-swatch-dark { background: #1b1e27; color: #fff; }
.branding-swatch-light { background: #eceef2; color: #1b1e27; }
.branding-swatch-tint { background: #6b4fa0; }
.branding-avatar :is(svg) { width: 60%; height: 60%; }
.toggle { display: flex; gap: 0.6rem; align-items: flex-start; }
.toggle input { margin-top: 0.3rem; }

/* ── Honeypot (anti-spam) ── */
/* Off-screen, non-interactive: real users never see or fill it; bots do. */
.hp-trap {
	position: absolute; left: -9999px; top: auto;
	width: 1px; height: 1px; overflow: hidden;
}

/* ── Pagination ── */
.pagination { display: flex; gap: 0.35rem; flex-wrap: wrap; margin-top: 1.25rem; }
.pagination a, .pagination span {
	padding: 0.25rem 0.6rem; border: 1px solid var(--color-border);
	border-radius: var(--radius); text-decoration: none; color: var(--color-text); font-size: 0.9rem;
}
.pagination .current { background: var(--color-primary); color: var(--color-primary-contrast); border-color: var(--color-primary); }

/* ── Confirm / alert modal (public/js/confirm-modal.js) ── */
.cfm-overlay {
	position: fixed; inset: 0; background: rgba(0, 0, 0, 0.45); z-index: 200;
	display: flex; align-items: flex-start; justify-content: center; padding: 18vh 1rem 1rem;
}
.cfm-box {
	background: var(--color-bg); border: 1px solid var(--color-border);
	border-radius: var(--radius); width: 100%; max-width: 430px;
	padding: 1.1rem 1.2rem; box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
}
.cfm-title { font-weight: 700; margin-bottom: 0.4rem; }
.cfm-msg { margin: 0 0 1.1rem; color: var(--color-text); line-height: 1.5; }
.cfm-label { display: block; margin: 0 0 0.4rem; font-size: 0.9rem; color: var(--color-text); }
.cfm-input {
	display: block; width: 100%; box-sizing: border-box; margin: 0 0 1.1rem; font: inherit;
	padding: 0.5rem 0.6rem; border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); color: var(--color-text);
}
.cfm-input:focus { outline: 2px solid var(--color-primary); outline-offset: 1px; border-color: var(--color-primary); }
.cfm-actions { display: flex; gap: 0.6rem; justify-content: flex-end; }
.cfm-btn {
	padding: 0.45rem 0.9rem; border-radius: var(--radius); border: 1px solid var(--color-primary);
	background: var(--color-primary); color: var(--color-primary-contrast); font: inherit; cursor: pointer;
}
.cfm-btn-cancel { background: var(--color-surface); color: var(--color-text); border-color: var(--color-border); }
.cfm-btn-danger { background: #b3372f; border-color: #b3372f; color: #fff; }

/* ── Admin media library (src/routes/admin-media.js) ── */
.media-upload-form { display: flex; gap: 0.6rem; align-items: center; flex-wrap: wrap; margin: 1rem 0 1.5rem; }
.media-upload-form input[type="file"] { width: auto; }
.media-upload-form select, .media-upload-form input[type="text"] {
	width: auto; font: inherit; font-size: 0.9rem; padding: 0.4rem 0.5rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); color: var(--color-text);
}
.media-layout { display: flex; gap: 1.5rem; align-items: flex-start; }
.media-sidebar { flex: 0 0 13rem; }
.media-main { flex: 1; min-width: 0; }
.media-folders { display: flex; flex-direction: column; gap: 0.4rem; margin-bottom: 1rem; }
.media-chip {
	display: flex; justify-content: space-between; gap: 0.5rem; padding: 0.3rem 0.7rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); text-decoration: none; color: var(--color-text); font-size: 0.88rem;
}
.media-chip:hover { border-color: var(--color-primary); }
.media-chip.active { border-color: var(--color-primary); color: var(--color-primary); font-weight: 700; }
.media-chip .count { color: var(--color-text-muted); font-weight: 400; }
.media-manage summary { cursor: pointer; font-size: 0.85rem; color: var(--color-text-muted); }
.media-manage summary:hover { color: var(--color-primary); }
.media-manage-rows { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 0.6rem; }
.media-manage-row { display: flex; flex-direction: column; gap: 0.4rem; }
.media-manage-row form { display: flex; gap: 0.4rem; align-items: center; margin: 0; }
.media-manage-row input[type="text"] {
	flex: 1; min-width: 0; font: inherit; font-size: 0.85rem; padding: 0.3rem 0.5rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); color: var(--color-text);
}
.media-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem; }
.media-tile {
	background: var(--color-surface); border: 1px solid var(--color-border);
	border-radius: var(--radius); padding: 0.7rem; display: flex; flex-direction: column; gap: 0.5rem;
}
.media-thumb {
	aspect-ratio: 4 / 3; border-radius: var(--radius); background: var(--color-bg);
	display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.media-thumb img { width: 100%; height: 100%; object-fit: cover; }
.media-ftype { font-weight: 800; letter-spacing: 0.08em; color: var(--color-text-muted); }
.media-name { font-size: 0.74rem; color: var(--color-text-muted); word-break: break-all; line-height: 1.35; }
.media-move { margin: 0; }
.media-move select {
	width: 100%; font: inherit; font-size: 0.8rem; padding: 0.25rem 0.4rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); color: var(--color-text);
}
.media-copy { display: flex; gap: 0.4rem; }
.media-copy input {
	flex: 1; min-width: 0; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.72rem;
	padding: 0.3rem 0.45rem; border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); color: var(--color-text);
}
.media-foot { display: flex; justify-content: space-between; align-items: center; gap: 0.4rem; margin-top: auto; font-size: 0.82rem; }
.media-actions { display: flex; gap: 0.4rem; }
.media-replace { margin: 0; }
@media (max-width: 40rem) {
	.media-layout { flex-direction: column; }
	.media-sidebar { flex: none; width: 100%; }
	.media-folders { flex-direction: row; flex-wrap: wrap; }
}

/* ── Media picker modal (public/js/media-picker.js) ── */
.mp-field { display: flex; gap: 0.4rem; align-items: center; }
.mp-field input { flex: 1; min-width: 0; }
.mp-browse { flex: 0 0 auto; white-space: nowrap; }
.mp-overlay {
	position: fixed; inset: 0; background: rgba(0, 0, 0, 0.4); z-index: 120;
	display: flex; align-items: flex-start; justify-content: center; padding: 6vh 1rem 1rem;
}
.mp-modal {
	background: var(--color-bg); border: 1px solid var(--color-border);
	border-radius: var(--radius); width: 100%; max-width: 860px; max-height: 80vh;
	display: flex; flex-direction: column; overflow: hidden;
}
.mp-head {
	display: flex; justify-content: space-between; align-items: center;
	padding: 0.9rem 1.1rem; border-bottom: 1px solid var(--color-border);
}
.mp-close { border: none; background: transparent; font-size: 1.5rem; line-height: 1; cursor: pointer; color: var(--color-text-muted); }
.mp-close:hover { color: var(--color-text); }
.mp-bar { display: flex; gap: 0.6rem; align-items: center; padding: 0.8rem 1.1rem; border-bottom: 1px solid var(--color-border); flex-wrap: wrap; }
.mp-bar select, .mp-bar input {
	font: inherit; font-size: 0.85rem; padding: 0.35rem 0.5rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); color: var(--color-text);
}
.mp-bar .mp-folder { width: auto; max-width: 180px; }
.mp-bar .mp-search { flex: 1; min-width: 140px; }
.mp-status { font-size: 0.8rem; color: var(--color-text-muted); }
.mp-body { padding: 1.1rem; overflow-y: auto; }
.mp-empty { color: var(--color-text-muted); margin: 0.4rem 0; }
.mp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 0.8rem; }
.mp-tile {
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); padding: 0.45rem; cursor: pointer;
	display: flex; flex-direction: column; gap: 0.35rem; text-align: left; font: inherit; color: var(--color-text);
}
.mp-tile:hover, .mp-tile:focus-visible { border-color: var(--color-primary); }
.mp-thumb { aspect-ratio: 4 / 3; border-radius: var(--radius); background: var(--color-bg); overflow: hidden; display: flex; align-items: center; justify-content: center; }
.mp-thumb img { width: 100%; height: 100%; object-fit: cover; }
.mp-name { font-size: 0.72rem; color: var(--color-text-muted); word-break: break-all; line-height: 1.3; }
.mp-chips { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem; }
.mp-chip {
	display: inline-flex; align-items: center; gap: 0.45rem; max-width: 100%;
	border: 1px solid var(--color-border); border-radius: 999px;
	background: var(--color-surface); padding: 0.3rem 0.75rem; cursor: pointer;
	font: inherit; font-size: 0.8rem; color: var(--color-text);
}
.mp-chip:hover, .mp-chip:focus-visible { border-color: var(--color-primary); }
.mp-chip-type { font-weight: 800; font-size: 0.68rem; letter-spacing: 0.06em; color: var(--color-text-muted); }
.mp-chip-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mp-tag {
	align-self: flex-start; font-size: 0.66rem; font-weight: 700; color: var(--color-text-muted);
	background: var(--color-bg); border-radius: 999px; padding: 0.1rem 0.5rem;
}

/* ══════════════════════════════════════════════════════════════════════════
   Pages CMS (src/routes/admin-pages.js, src/templates/blocks.js)
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Sidebar count pill (adminPage badges) ── */
.badge-count {
	display: inline-block; min-width: 1.2em; padding: 0 0.35rem; margin-left: 0.35rem;
	font-size: 0.72rem; font-weight: 700; line-height: 1.5; text-align: center;
	background: var(--color-primary); color: var(--color-primary-contrast); border-radius: 999px;
	vertical-align: middle;
}

/* ── Status pills (draft / published / modified) ── */
.status-pill {
	display: inline-block; padding: 0.1rem 0.55rem; border-radius: 999px;
	font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
	border: 1px solid var(--color-border); color: var(--color-text-muted);
}
/* The structure-screen status pill is a <button type="submit">, which the base
   button rule would inflate — re-assert the small pill geometry (matches the
   read-only story-cover pills). Colour rules below still win on their own. */
button.status-pill {
	padding: 0.1rem 0.55rem; border-radius: 999px; border-width: 1px;
	font-size: 0.75rem; line-height: 1.3; font-weight: 700; cursor: pointer;
}
.status-pill.status-published { background: color-mix(in srgb, var(--color-accent) 18%, transparent); border-color: var(--color-accent); color: var(--color-text); }
.status-pill.status-modified { background: color-mix(in srgb, #c98a00 22%, transparent); border-color: #c98a00; color: var(--color-text); }
.status-pill.status-draft { background: var(--color-bg); }

/* ── Public page header nav links ── */
/* Documentation layout: a sidebar of published pages beside the article. The
   header no longer lists pages individually (it carries one info icon → /docs),
   so this is where a reader moves between them. */
.doc-layout { display: grid; grid-template-columns: 14rem minmax(0, 1fr); gap: 2rem; align-items: start; }
.doc-nav { position: sticky; top: 1rem; }
.doc-nav-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.15rem; }
/* Nested lists indent one level per slug segment. */
.doc-nav-list .doc-nav-list { margin-left: 0.75rem; padding-left: 0.5rem; border-left: 1px solid var(--color-border); margin-top: 0.15rem; }
.doc-nav-link {
	display: block; padding: 0.3rem 0.55rem; border-radius: 6px;
	text-decoration: none; color: var(--color-text); font-size: 0.92rem; line-height: 1.35;
}
.doc-nav-link:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); color: var(--color-primary); }
.doc-nav-link.is-current {
	background: color-mix(in srgb, var(--color-primary) 15%, transparent);
	color: var(--color-primary); font-weight: 700;
}
/* Stack the sidebar above the article once there is no room beside it. */
@media (max-width: 52rem) {
	.doc-layout { grid-template-columns: 1fr; gap: 1.2rem; }
	.doc-nav { position: static; padding-bottom: 0.8rem; border-bottom: 1px solid var(--color-border); }
}

/* ══ Public block renderers ══ */
.page-content .block { margin: 2rem 0; }
.page-content .block:first-child { margin-top: 0; }

/* Prose: comfortable measure + line-height for documentation reading. */
.page-content .prose { max-width: 42rem; line-height: 1.7; }
/* The rich-text body block fills the full container width (keeps prose type). */
.page-content .block-richtext.prose { max-width: none; }
.page-content .prose > *:first-child { margin-top: 0; }
.page-content .prose > *:last-child { margin-bottom: 0; }
.page-content .prose h1, .page-content .prose h2, .page-content .prose h3 { font-family: var(--font-serif); line-height: 1.25; }
.page-content .prose h2 { margin-top: 2rem; }
.page-content .prose pre {
	background: var(--color-surface); border: 1px solid var(--color-border);
	border-radius: var(--radius); padding: 0.9rem 1rem; overflow-x: auto;
}
.page-content .prose code { font-size: 0.92em; }
.page-content .prose > p code, .page-content .prose li code {
	background: var(--color-surface); border: 1px solid var(--color-border);
	border-radius: 4px; padding: 0.05rem 0.3rem;
}
.page-content .prose blockquote {
	margin: 1rem 0; padding: 0.2rem 1rem; border-left: 3px solid var(--color-primary);
	color: var(--color-text-muted);
}
.page-content .prose img { max-width: 100%; height: auto; border-radius: var(--radius); }
.page-content .prose table { margin: 1rem 0; }

/* Hero */
.block-hero {
	padding: 3rem 1.5rem; border-radius: var(--radius); text-align: center;
	background: var(--color-surface); border: 1px solid var(--color-border);
}
.block-hero.has-bg { background-size: cover; background-position: center; color: #fff; border: none; position: relative; }
.block-hero.has-bg::before { content: ""; position: absolute; inset: 0; background: rgba(0,0,0,0.45); border-radius: var(--radius); }
.block-hero-inner { position: relative; max-width: 40rem; margin: 0 auto; }
.block-hero h1 { font-family: var(--font-serif); font-size: 2.2rem; margin: 0 0 0.5rem; }
.block-hero-subtitle { font-size: 1.2rem; color: var(--color-text-muted); margin: 0 0 1.2rem; }
.block-hero.has-bg .block-hero-subtitle { color: rgba(255,255,255,0.85); }
.block-hero-cta { margin: 0; }

/* Standalone image */
.block-image { margin-inline: auto; }
.block-image img { display: block; width: 100%; height: auto; border-radius: var(--radius); }
.block-image figcaption { margin-top: 0.4rem; font-size: 0.85rem; color: var(--color-text-muted); text-align: center; }
.block-image.img-normal { max-width: 42rem; }
.block-image.img-wide { max-width: 56rem; }
.block-image.img-full { max-width: 100%; }

/* Gallery */
.block-gallery-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem; }
.block-gallery-item { margin: 0; }
.block-gallery-link { display: block; border-radius: var(--radius); overflow: hidden; cursor: pointer; }
.block-gallery-link img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; transition: transform 0.2s ease, filter 0.2s ease; }
.block-gallery-link:hover img { transform: scale(1.03); filter: brightness(1.05); }
.block-gallery-link:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.block-gallery-item figcaption { margin-top: 0.35rem; font-size: 0.82rem; color: var(--color-text-muted); }

/* Gallery lightbox (appended to <body> by the gallery island). */
.gal-lightbox { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center; }
.gal-lightbox[hidden] { display: none; }
.gal-lb-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.86); }
.gal-lb-stage { position: relative; margin: 0; max-width: 92vw; text-align: center; }
.gal-lb-media { max-width: 92vw; max-height: 82vh; display: block; margin: 0 auto; border-radius: var(--radius); background: #000; }
.gal-lb-cap { color: #fff; margin: 0.9rem auto 0; max-width: 720px; font-size: 0.9rem; }
.gal-lb-cap[hidden] { display: none; }
.gal-lb-close, .gal-lb-nav {
	position: fixed; border: none; cursor: pointer; color: #fff;
	background: rgba(255, 255, 255, 0.15); border-radius: 999px; line-height: 1;
}
.gal-lb-close:hover, .gal-lb-nav:hover { background: rgba(255, 255, 255, 0.28); }
.gal-lb-close { top: 1rem; right: 1.2rem; width: 2.6rem; height: 2.6rem; font-size: 1.7rem; }
.gal-lb-nav { top: 50%; transform: translateY(-50%); width: 3rem; height: 3rem; font-size: 1.9rem; }
.gal-lb-nav[hidden] { display: none; }
.gal-lb-prev { left: 1rem; }
.gal-lb-next { right: 1rem; }
@media (max-width: 600px) { .gal-lb-nav { width: 2.4rem; height: 2.4rem; font-size: 1.5rem; } }

/* Callout */
.block-callout { border: 1px solid var(--color-border); border-left-width: 4px; border-radius: var(--radius); padding: 1rem 1.2rem; }
.block-callout.callout-info { border-left-color: #2f6fb3; background: color-mix(in srgb, #2f6fb3 8%, transparent); }
.block-callout.callout-success { border-left-color: var(--color-accent); background: color-mix(in srgb, var(--color-accent) 10%, transparent); }
.block-callout.callout-warning { border-left-color: #c98a00; background: color-mix(in srgb, #c98a00 12%, transparent); }
.block-callout.callout-error { border-left-color: #b3372f; background: color-mix(in srgb, #b3372f 10%, transparent); }
.block-callout .prose { max-width: none; }

/* Feature grid */
.block-feature-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1.2rem; }
.block-feature {
	background: var(--color-surface); border: 1px solid var(--color-border);
	border-radius: var(--radius); padding: 1.1rem 1.2rem;
}
.block-feature-img { display: block; width: 100%; height: auto; border-radius: var(--radius); margin-bottom: 0.7rem; }
.block-feature h3 { font-family: var(--font-serif); margin: 0 0 0.4rem; }
.block-feature .prose { max-width: none; line-height: 1.55; }

/* FAQ */
.block-faq-item { border-bottom: 1px solid var(--color-border); padding: 0.6rem 0; }
.block-faq-item summary { cursor: pointer; font-weight: 600; }
.block-faq-item .prose { max-width: none; margin-top: 0.5rem; }

/* Embed / code */
.block-embed { margin: 1.5rem 0; }
.block-embed-content { width: 100%; }
.block-embed-content :is(iframe, embed, object, video) { max-width: 100%; }
.block-embed-frame { width: 100%; border: 0; display: block; }
.block-embed-content.embed-small, .block-embed-frame.embed-small { height: 400px; }
.block-embed-content.embed-medium, .block-embed-frame.embed-medium { height: 640px; }
.block-embed-content.embed-large, .block-embed-frame.embed-large { height: 900px; }
.block-embed-frame.embed-page { height: 80vh; }
.block-embed-content.embed-small :is(iframe, embed, object, video),
.block-embed-content.embed-medium :is(iframe, embed, object, video),
.block-embed-content.embed-large :is(iframe, embed, object, video) { width: 100%; height: 100%; }

/* Related links */
.block-related { margin: 1.5rem 0; }
/* The column choice is a MAX: fixed at the chosen count on wide screens, then
   stepping down responsively (never more than the author picked). */
.block-related-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 1rem; grid-template-columns: 1fr; }
@media (min-width: 40rem) {
	.block-related-list.cols-2, .block-related-list.cols-3 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 60rem) {
	.block-related-list.cols-3 { grid-template-columns: repeat(3, 1fr); }
}
/* The whole card is clickable via the title link's stretched ::after overlay
   (accessible: one real <a>, its text is the title). Nested blurb links stay
   clickable by sitting above the overlay. */
.block-related-card { position: relative; border: 1px solid var(--color-border); border-radius: var(--radius); padding: 1rem 1.1rem; background: var(--color-surface); }
.block-related-card:hover { border-color: var(--color-primary); }
.block-related-card h3 { margin: 0 0 0.4rem; }
.block-related-card h3 a { text-decoration: none; }
.block-related-card h3 a::after { content: ''; position: absolute; inset: 0; }
.block-related-card:hover h3 a { color: var(--color-primary); }
.block-related-card .prose a { position: relative; z-index: 1; }
.block-related-blurb { max-width: none; font-size: 0.92rem; }
.block-related-more { display: inline-block; margin-top: 0.5rem; font-size: 0.85rem; color: var(--color-primary); font-weight: 600; }

/* Tabbed content (pure-CSS tabs: hidden radios drive label + panel state) */
.block-tabs { margin: 1.5rem 0; }
.block-tab-radio { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.block-tab-labels { display: flex; flex-wrap: wrap; gap: 0.2rem; border-bottom: 1px solid var(--color-border); margin-bottom: 1rem; }
.block-tab-label {
	cursor: pointer; padding: 0.5rem 0.9rem; border: 1px solid transparent; border-bottom: none;
	border-radius: var(--radius) var(--radius) 0 0; margin-bottom: -1px;
	color: var(--color-text-muted); font-weight: 600; user-select: none;
}
.block-tab-label:hover { color: var(--color-text); }
.block-tab-panel { display: none; }
.block-tab-panel.prose { max-width: none; }
/* Show the panel + light the label whose radio is checked (up to 10 tabs). */
.block-tabs .block-tab-radio:nth-of-type(1):checked ~ .block-tab-panels .block-tab-panel:nth-of-type(1),
.block-tabs .block-tab-radio:nth-of-type(2):checked ~ .block-tab-panels .block-tab-panel:nth-of-type(2),
.block-tabs .block-tab-radio:nth-of-type(3):checked ~ .block-tab-panels .block-tab-panel:nth-of-type(3),
.block-tabs .block-tab-radio:nth-of-type(4):checked ~ .block-tab-panels .block-tab-panel:nth-of-type(4),
.block-tabs .block-tab-radio:nth-of-type(5):checked ~ .block-tab-panels .block-tab-panel:nth-of-type(5),
.block-tabs .block-tab-radio:nth-of-type(6):checked ~ .block-tab-panels .block-tab-panel:nth-of-type(6),
.block-tabs .block-tab-radio:nth-of-type(7):checked ~ .block-tab-panels .block-tab-panel:nth-of-type(7),
.block-tabs .block-tab-radio:nth-of-type(8):checked ~ .block-tab-panels .block-tab-panel:nth-of-type(8),
.block-tabs .block-tab-radio:nth-of-type(9):checked ~ .block-tab-panels .block-tab-panel:nth-of-type(9),
.block-tabs .block-tab-radio:nth-of-type(10):checked ~ .block-tab-panels .block-tab-panel:nth-of-type(10) { display: block; }
.block-tabs .block-tab-radio:nth-of-type(1):checked ~ .block-tab-labels .block-tab-label:nth-of-type(1),
.block-tabs .block-tab-radio:nth-of-type(2):checked ~ .block-tab-labels .block-tab-label:nth-of-type(2),
.block-tabs .block-tab-radio:nth-of-type(3):checked ~ .block-tab-labels .block-tab-label:nth-of-type(3),
.block-tabs .block-tab-radio:nth-of-type(4):checked ~ .block-tab-labels .block-tab-label:nth-of-type(4),
.block-tabs .block-tab-radio:nth-of-type(5):checked ~ .block-tab-labels .block-tab-label:nth-of-type(5),
.block-tabs .block-tab-radio:nth-of-type(6):checked ~ .block-tab-labels .block-tab-label:nth-of-type(6),
.block-tabs .block-tab-radio:nth-of-type(7):checked ~ .block-tab-labels .block-tab-label:nth-of-type(7),
.block-tabs .block-tab-radio:nth-of-type(8):checked ~ .block-tab-labels .block-tab-label:nth-of-type(8),
.block-tabs .block-tab-radio:nth-of-type(9):checked ~ .block-tab-labels .block-tab-label:nth-of-type(9),
.block-tabs .block-tab-radio:nth-of-type(10):checked ~ .block-tab-labels .block-tab-label:nth-of-type(10) {
	color: var(--color-text); border-color: var(--color-border); background: var(--color-bg);
}
/* Keyboard focus (radios are visually hidden) lands a ring on the active label. */
.block-tabs .block-tab-radio:nth-of-type(1):focus-visible ~ .block-tab-labels .block-tab-label:nth-of-type(1),
.block-tabs .block-tab-radio:nth-of-type(2):focus-visible ~ .block-tab-labels .block-tab-label:nth-of-type(2),
.block-tabs .block-tab-radio:nth-of-type(3):focus-visible ~ .block-tab-labels .block-tab-label:nth-of-type(3),
.block-tabs .block-tab-radio:nth-of-type(4):focus-visible ~ .block-tab-labels .block-tab-label:nth-of-type(4),
.block-tabs .block-tab-radio:nth-of-type(5):focus-visible ~ .block-tab-labels .block-tab-label:nth-of-type(5),
.block-tabs .block-tab-radio:nth-of-type(6):focus-visible ~ .block-tab-labels .block-tab-label:nth-of-type(6),
.block-tabs .block-tab-radio:nth-of-type(7):focus-visible ~ .block-tab-labels .block-tab-label:nth-of-type(7),
.block-tabs .block-tab-radio:nth-of-type(8):focus-visible ~ .block-tab-labels .block-tab-label:nth-of-type(8),
.block-tabs .block-tab-radio:nth-of-type(9):focus-visible ~ .block-tab-labels .block-tab-label:nth-of-type(9),
.block-tabs .block-tab-radio:nth-of-type(10):focus-visible ~ .block-tab-labels .block-tab-label:nth-of-type(10) {
	outline: 2px solid var(--color-primary); outline-offset: -2px;
}

/* Divider */
.block-divider { border: none; border-top: 1px solid var(--color-border); }

/* ══ Block editor (public/js/page-editor.js) ══ */
.editor-columns { display: grid; grid-template-columns: 1fr 20rem; gap: 1.5rem; align-items: start; }
.editor-columns > * { min-width: 0; }
@media (max-width: 52rem) { .editor-columns { grid-template-columns: 1fr; } }

.editor-card {
	background: var(--color-surface); border: 1px solid var(--color-border);
	border-radius: var(--radius); padding: 1rem 1.1rem; position: sticky; top: 1rem;
}
.editor-card .field { margin-bottom: 0.9rem; }
.editor-card .field label { display: block; font-size: 0.82rem; font-weight: 600; margin-bottom: 0.3rem; }
.editor-card .field label.checkbox-label { font-weight: normal; }
.editor-card input, .editor-card textarea, .editor-card select {
	width: 100%; max-width: 100%; font: inherit; padding: 0.4rem 0.55rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); color: var(--color-text);
}
.editor-card input[type="checkbox"] { width: auto; }
.editor-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.4rem; }

.blocks-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.4rem; flex-wrap: wrap; gap: 0.4rem; }
.blocks-head-btns { display: flex; gap: 0.4rem; }
.add-block { margin-top: 0.5rem; }
.editor-empty { padding: 0.6rem 0; }

.block-card { border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-surface); margin: 0.2rem 0; min-width: 0; max-width: 100%; }
.block-card .block-head { display: flex; align-items: center; gap: 0.6rem; padding: 0.55rem 0.75rem; flex-wrap: wrap; }
.block-card .blk-caret { border: none; background: transparent; cursor: pointer; font-size: 0.9rem; color: var(--color-text-muted); padding: 0.2rem; }
.block-card .block-headmain { flex: 1; min-width: 0; cursor: pointer; }
.block-card .block-type { font-weight: 700; font-size: 0.95rem; }
.block-card .block-sum { font-size: 0.8rem; color: var(--color-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.block-card .block-ctrls { display: flex; gap: 0.3rem; flex-wrap: wrap; }
.block-card .block-body { padding: 0.9rem; border-top: 1px solid var(--color-border); }
.block-card.collapsed .block-body { display: none; }
.block-card .warn { color: #b3372f; }
.block-card .block-body input, .block-card .block-body textarea, .block-card .block-body select {
	width: 100%; max-width: 100%; font: inherit; padding: 0.4rem 0.55rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); color: var(--color-text);
}
.block-card .block-body textarea { font-family: var(--font-body); line-height: 1.5; }
.block-card .block-body textarea[data-markdown] { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 0.9rem; }

.fld { margin-bottom: 0.9rem; min-width: 0; }
.fld-label { display: block; font-size: 0.82rem; font-weight: 600; margin-bottom: 0.3rem; }

/* Richtext field: the shared TipTap editor mounted inside a block card. The
   toolbar reuses .editor-toolbar/.tb-* styles (createToolbar adds the class);
   the surface gets a bordered box and the same ProseMirror content styling as
   the scene editor, scoped here so it doesn't depend on .scene-surface. */
.rt-field .rt-toolbar {
	display: flex; flex-wrap: wrap; align-items: center; gap: 0.15rem;
	padding: 0.3rem; margin-bottom: 0.4rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); position: sticky; top: 0; z-index: 2;
}
.rt-field .rt-surface {
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); padding: 0.7rem 0.9rem; min-height: 8rem;
}
.rt-field .rt-surface .ProseMirror {
	font-family: var(--font-body); line-height: 1.6; color: var(--color-text);
	caret-color: var(--color-primary); outline: none;
}
.rt-field .rt-surface .ProseMirror:focus { outline: none; }
.rt-field .rt-surface .ProseMirror > * + * { margin-top: 0.8em; }
.rt-field .rt-surface .ProseMirror h1, .rt-field .rt-surface .ProseMirror h2,
.rt-field .rt-surface .ProseMirror h3, .rt-field .rt-surface .ProseMirror h4 {
	font-family: var(--font-serif); font-weight: 700; line-height: 1.25; margin-top: 1.2em;
}
.rt-field .rt-surface .ProseMirror h1 { font-size: 1.6em; }
.rt-field .rt-surface .ProseMirror h2 { font-size: 1.35em; }
.rt-field .rt-surface .ProseMirror h3 { font-size: 1.15em; }
.rt-field .rt-surface .ProseMirror h4 { font-size: 1.05em; }
.rt-field .rt-surface .ProseMirror ul, .rt-field .rt-surface .ProseMirror ol { padding-left: 1.5em; }
.rt-field .rt-surface .ProseMirror li > p { margin: 0; }
.rt-field .rt-surface .ProseMirror blockquote {
	border-left: 3px solid color-mix(in srgb, var(--color-primary) 50%, transparent);
	padding-left: 1rem; margin-left: 0; color: var(--color-text-muted); font-style: italic;
}
.rt-field .rt-surface .ProseMirror hr { border: none; border-top: 1px solid var(--color-border); margin: 1.4em 0; }
.rt-field .rt-surface .ProseMirror img { max-width: 100%; height: auto; }
.rt-field .rt-fallback { width: 100%; min-height: 8rem; font-family: var(--font-body); line-height: 1.5; }
.fld-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(180px, 100%), 1fr)); gap: 0.8rem; margin-bottom: 0.9rem; }
.fld-grid .fld { margin-bottom: 0; }

.listfield { border: 1px dashed var(--color-border); border-radius: var(--radius); padding: 0.8rem; margin-bottom: 0.9rem; }
.item-card { border: 1px solid var(--color-border); border-radius: var(--radius); padding: 0.7rem; margin-bottom: 0.7rem; background: var(--color-bg); }
.item-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem; flex-wrap: wrap; gap: 0.3rem 0.6rem; }
.item-num { font-size: 0.8rem; font-weight: 700; color: var(--color-text-muted); }
.item-ctrls { display: flex; gap: 0.3rem; flex-wrap: wrap; }

.blk-insert { text-align: center; height: 14px; position: relative; }
.blk-insert button {
	position: absolute; left: 50%; top: -4px; transform: translateX(-50%);
	width: 22px; height: 22px; line-height: 1; border-radius: 999px;
	border: 1px solid var(--color-border); background: var(--color-bg); color: var(--color-text-muted);
	cursor: pointer; opacity: 0; transition: opacity 0.12s; z-index: 2; padding: 0;
}
.blk-insert:hover button, .blk-insert button:focus-visible { opacity: 1; }

.blk-modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.4); z-index: 200; display: flex; align-items: flex-start; justify-content: center; padding: 8vh 1rem 1rem; }
.blk-modal { background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius); width: 100%; max-width: 560px; max-height: 75vh; display: flex; flex-direction: column; overflow: hidden; }
.blk-modal-head { display: flex; justify-content: space-between; align-items: center; padding: 0.9rem 1.1rem; border-bottom: 1px solid var(--color-border); }
.blk-modal-close { border: none; background: transparent; font-size: 1.4rem; cursor: pointer; color: var(--color-text-muted); }
.blk-modal-search { padding: 0.8rem 1.1rem 0; }
.blk-modal-search input { width: 100%; font: inherit; padding: 0.4rem 0.55rem; border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-surface); color: var(--color-text); }
.blk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0.6rem; padding: 1.1rem; overflow-y: auto; }
.blk-tile { border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-surface); padding: 0.9rem 0.6rem; cursor: pointer; font: inherit; font-size: 0.9rem; font-weight: 600; color: var(--color-text); }
.blk-tile:hover { border-color: var(--color-primary); color: var(--color-primary); }
.blk-grid-none { color: var(--color-text-muted); padding: 0.5rem; }

.page-revisions { margin-top: 1.6rem; }
.page-revisions summary { cursor: pointer; font-weight: 600; }

/* ══════════════════════════════════════════════════════════════════════════
   Story library (src/routes/library.js, src/covers.js)
   ══════════════════════════════════════════════════════════════════════════ */

.library-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem; }
.library-head h1 { font-family: var(--font-serif); margin: 0; }
.library-head-actions { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.import-form { display: flex; align-items: center; gap: 0.5rem; }
.import-form input[type="file"] { max-width: 12rem; font-size: 0.85rem; }
.back-link { text-decoration: none; font-size: 0.9rem; color: var(--color-text-muted); }
.back-link:hover { color: var(--color-primary); }
.folder-title { font-family: var(--font-serif); margin: 0.3rem 0 0; border-left: 4px solid var(--folder, var(--color-primary)); padding-left: 0.6rem; }
.library-empty { margin: 2rem 0; }

/* ── Filter bar (plain GET form) ── */
.filter-bar {
	background: var(--color-surface); border: 1px solid var(--color-border);
	border-radius: var(--radius); padding: 0.9rem 1rem; margin-bottom: 1.5rem;
}
.filter-row { display: flex; gap: 0.8rem; align-items: flex-end; flex-wrap: wrap; }
.filter-field { display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.82rem; font-weight: 600; color: var(--color-text-muted); }
.filter-field.filter-search { flex: 1; min-width: 12rem; }
.filter-bar input[type="search"], .filter-bar select {
	font: inherit; font-weight: 400; padding: 0.45rem 0.6rem; color: var(--color-text);
	border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-bg);
}
.filter-bar .button { align-self: flex-end; }
.filter-clear { align-self: flex-end; }
.filter-groups { display: flex; gap: 1.5rem; flex-wrap: wrap; margin-top: 0.9rem; }
.filter-group { border: 1px solid var(--color-border); border-radius: var(--radius); padding: 0.5rem 0.9rem 0.7rem; margin: 0; }
.filter-group legend { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-text-muted); padding: 0 0.3rem; }
.filter-check { display: inline-flex; align-items: center; gap: 0.3rem; margin-right: 0.9rem; font-size: 0.9rem; white-space: nowrap; }
.filter-check input { width: auto; }

/* ── Story cover cards (2:3), title/author overlay ── */
.story-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 1.2rem; }
.story-card {
	position: relative; display: block; aspect-ratio: 2 / 3; border-radius: var(--radius);
	overflow: hidden; text-decoration: none; color: #fff;
	border: 1px solid var(--color-border); box-shadow: 0 2px 8px rgba(0,0,0,0.12);
	transition: transform 0.12s, box-shadow 0.12s;
}
.story-card:hover { transform: translateY(-3px); box-shadow: 0 8px 20px rgba(0,0,0,0.25); }
.story-card-cover { position: absolute; inset: 0; background: var(--cover, var(--color-primary)); }
.story-card-overlay {
	position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: flex-end;
	gap: 0.3rem; padding: 0.7rem; background: linear-gradient(to top, rgba(0,0,0,0.72) 0%, rgba(0,0,0,0.22) 55%, rgba(0,0,0,0.05) 100%);
}
.story-card-title { font-family: var(--font-serif); font-weight: 700; font-size: 1.02rem; line-height: 1.2; text-shadow: 0 1px 3px rgba(0,0,0,0.6); }
.story-card-authors { font-size: 0.8rem; opacity: 0.92; text-shadow: 0 1px 3px rgba(0,0,0,0.6); }
.story-card .status-pill { align-self: flex-start; margin-top: 0.1rem; }

/* ── Folder cards ── */
.folder-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 1rem; margin-bottom: 1.5rem; }
.folder-card {
	display: flex; flex-direction: column; gap: 0.15rem; padding: 0.9rem 1rem; text-decoration: none;
	border: 1px solid var(--color-border); border-left: 5px solid var(--folder, var(--color-primary));
	border-radius: var(--radius); background: var(--color-surface); color: var(--color-text);
	transition: border-color 0.12s, transform 0.12s;
}
.folder-card:hover { transform: translateY(-2px); border-color: var(--folder, var(--color-primary)); }
.folder-card-icon { color: var(--folder, var(--color-primary)); line-height: 0; }
.folder-card-icon svg { width: 1.6rem; height: 1.6rem; display: block; }
.folder-card-name { font-weight: 700; }
.folder-card-count { font-size: 0.8rem; color: var(--color-text-muted); }

/* ── Manage-folders panel ── */
.folder-manage { margin-top: 2rem; border-top: 1px solid var(--color-border); padding-top: 1rem; }
.folder-manage > summary { cursor: pointer; font-weight: 600; color: var(--color-text-muted); }
.folder-manage > summary:hover { color: var(--color-primary); }
.folder-manage-rows { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 0.8rem; max-width: 40rem; }
.folder-manage-row { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
.folder-edit-form { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; margin: 0; }
.folder-edit-form input[type="text"] {
	font: inherit; font-size: 0.9rem; padding: 0.35rem 0.5rem; min-width: 10rem;
	border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-surface); color: var(--color-text);
}

/* ── Reusable colour field (src/covers.js colorField + /js/color-picker.js) ── */
.color-field-wrap { display: inline-flex; gap: 0.35rem; align-items: center; }
input.color-field {
	width: 7.5rem; font: inherit; font-size: 0.9rem; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
	text-transform: uppercase;
	padding: 0.35rem 0.5rem; border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); color: var(--color-text);
}

/* Custom colour picker (swatch button + popover), ported from dragonslaircms */
.cp-wrap { position: relative; display: inline-flex; align-items: center; gap: 0.5rem; max-width: 100%; }
.cp-swatch {
	width: 36px; height: 30px; flex: none; padding: 0;
	border: 1px solid var(--color-border); border-radius: var(--radius); cursor: pointer;
	/* Checkerboard shows through for empty/invalid values. */
	background-color: transparent;
	background-image:
		linear-gradient(45deg, rgba(128,128,128,0.25) 25%, transparent 25%, transparent 75%, rgba(128,128,128,0.25) 75%),
		linear-gradient(45deg, rgba(128,128,128,0.25) 25%, transparent 25%, transparent 75%, rgba(128,128,128,0.25) 75%);
	background-size: 12px 12px; background-position: 0 0, 6px 6px;
}
.cp-swatch:not(.cp-swatch-empty) { background-image: none; }
.cp-swatch:hover { border-color: var(--color-primary); }
.cp-pop {
	position: absolute; z-index: 80; top: calc(100% + 6px); left: 0;
	width: 216px; padding: 10px;
	background: var(--color-surface); border: 1px solid var(--color-border);
	border-radius: var(--radius); box-shadow: 0 10px 28px rgba(0, 0, 0, 0.28);
}
.cp-sv { position: relative; width: 100%; height: 140px; border-radius: calc(var(--radius) * 0.6); cursor: crosshair; touch-action: none; }
.cp-thumb {
	position: absolute; width: 14px; height: 14px; border-radius: 50%;
	border: 2px solid #fff; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.55);
	transform: translate(-50%, -50%); pointer-events: none;
}
.cp-hue {
	position: relative; height: 14px; margin-top: 12px; border-radius: 7px; cursor: pointer; touch-action: none;
	background: linear-gradient(to right, #f00 0%, #ff0 16.7%, #0f0 33.3%, #0ff 50%, #00f 66.7%, #f0f 83.3%, #f00 100%);
}
.cp-hue-thumb {
	position: absolute; top: 50%; width: 16px; height: 16px; border-radius: 50%;
	border: 2px solid #fff; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.55);
	transform: translate(-50%, -50%); pointer-events: none; background: transparent;
}
.cp-hex-row { display: flex; align-items: center; gap: 0.5rem; margin-top: 12px; font-size: 0.8rem; color: var(--color-text-muted); }
.cp-hex-row input {
	flex: 1; min-width: 0; font: inherit; font-size: 0.85rem;
	font-family: ui-monospace, SFMono-Regular, Menlo, monospace; text-transform: uppercase;
	padding: 0.25rem 0.4rem; border: 1px solid var(--color-border); border-radius: calc(var(--radius) * 0.6);
	background: var(--color-bg); color: var(--color-text);
}

/* ── Story create / edit form ── */
/* Fills the full site-main width (the shell already caps + centres content). */
.story-form-wrap { max-width: none; }
.story-form-wrap h1 { font-family: var(--font-serif); }
.story-form { display: flex; flex-direction: column; gap: 1rem; align-items: stretch; }
.story-form label, .story-form .field-block { display: flex; flex-direction: column; gap: 0.3rem; font-weight: 600; }
.story-form .field-label { font-weight: 600; }
.story-form input[type="text"], .story-form select {
	font: inherit; font-weight: 400; padding: 0.5rem 0.7rem; width: 100%;
	border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-surface); color: var(--color-text);
}
.story-form .req { color: #b3372f; }
.story-form small { font-weight: 400; }
.story-form-actions { display: flex; gap: 0.8rem; align-items: center; flex-wrap: wrap; margin-top: 0.5rem; }

/* ── Placeholder story page ── */
.story-page-head { display: flex; gap: 1.5rem; align-items: flex-start; flex-wrap: wrap; }
.story-page-cover {
	flex: 0 0 auto; width: 8rem; aspect-ratio: 2 / 3; border-radius: var(--radius);
	background: var(--cover, var(--color-primary)); box-shadow: 0 2px 10px rgba(0,0,0,0.2); border: 1px solid var(--color-border);
}
.story-page-info { flex: 1; min-width: 14rem; }
.story-page-info h1 { font-family: var(--font-serif); margin: 0 0 0.8rem; }
.story-meta { margin: 0 0 1rem; }
.story-meta-row { display: flex; gap: 0.6rem; padding: 0.25rem 0; border-bottom: 1px solid var(--color-border); }
.story-meta-row dt { flex: 0 0 6rem; font-weight: 700; color: var(--color-text-muted); font-size: 0.9rem; }
.story-meta-row dd { margin: 0; }
.story-structure-placeholder {
	margin-top: 2rem; padding: 2rem; text-align: center;
	border: 1px dashed var(--color-border); border-radius: var(--radius); background: var(--color-surface);
}

/* ── Story status pills (PLAN / DRAFT / EDIT / DONE) ── */
.status-pill.status-PLAN { background: color-mix(in srgb, #8b8b8b 22%, transparent); border-color: #8b8b8b; color: #fff; }
.status-pill.status-DRAFT { background: color-mix(in srgb, #c98a00 80%, black 5%); border-color: #c98a00; color: #fff; }
.status-pill.status-EDIT { background: color-mix(in srgb, #2f6fb3 85%, black); border-color: #2f6fb3; color: #fff; }
.status-pill.status-DONE { background: color-mix(in srgb, #2e7d5b 85%, black); border-color: #2e7d5b; color: #fff; }

/* ══ Recycle bin (src/routes/recycle.js) ══ */
.recycle-bin .library-head { align-items: baseline; }
.bin-type {
	display: inline-block; padding: 0.1rem 0.55rem; border-radius: 999px; font-size: 0.72rem;
	font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
	background: var(--color-bg); border: 1px solid var(--color-border); color: var(--color-text-muted);
}
.bin-type-story { border-color: var(--color-primary); color: var(--color-primary); }

/* ══ Cover canvas (procedural covers painted by public/js/cover-pattern.js) ══ */
/* Painted on top of the CSS colour fallback; progressive enhancement. */
.cover-canvas { display: block; width: 100%; height: 100%; }
.story-card .cover-canvas { position: absolute; inset: 0; z-index: 1; }
.story-card-overlay { z-index: 2; }

/* ── Story edit form: two columns (fields + live cover preview) ── */
.story-form-layout { display: flex; gap: 2rem; align-items: flex-start; flex-wrap: wrap; }
.story-form-layout .story-form { flex: 1 1 22rem; min-width: 18rem; }
.story-form-aside { flex: 0 0 auto; display: flex; flex-direction: column; gap: 0.4rem; position: sticky; top: 1rem; }
.story-form-aside .field-label { font-weight: 600; }
.cover-preview-wrap {
	width: 12rem; aspect-ratio: 2 / 3; border-radius: var(--radius); overflow: hidden;
	border: 1px solid var(--color-border); box-shadow: 0 2px 10px rgba(0,0,0,0.2);
}
.cover-preview { width: 100%; height: 100%; }
.cover-image-block { gap: 0.5rem; }
.cover-image-form { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; margin: 0.2rem 0; }
.cover-image-form input[type="file"] { font-size: 0.85rem; }

/* ══ Story structure screen (src/routes/story.js) ══ */
/* Fills the full site-main width (like every other in-container page); the site
   shell already caps + centres content at --content-width. */
.story-structure { max-width: none; }
.structure-head { display: flex; gap: 1.5rem; align-items: flex-start; flex-wrap: wrap; margin-bottom: 1.5rem; }
.structure-cover {
	flex: 0 0 auto; width: 7rem; aspect-ratio: 2 / 3; border-radius: var(--radius);
	box-shadow: 0 2px 10px rgba(0,0,0,0.2); border: 1px solid var(--color-border); background: var(--color-surface);
}
.structure-head-info { flex: 1; min-width: 15rem; }
.structure-head-info h1 { font-family: var(--font-serif); margin: 0 0 0.2rem; }
.structure-authors { margin: 0 0 0.6rem; color: var(--color-text-muted); }
.structure-meta { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; margin-bottom: 0.8rem; }
.structure-total { font-size: 0.95rem; }
.structure-links { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }

/* Export dialog (structure screen) — a zero-JS <details> panel. */
.structure-export { display: inline-block; }
/* Export opens the same centred modal as the row edit/rename dialogs
   (.row-rename → .row-edit-body); see public/js/story-structure.js. */
.export-notes { border: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.3rem; }
.export-notes legend { font-size: 0.8rem; color: var(--color-text-muted); padding: 0; margin-bottom: 0.2rem; }
.export-notes label { display: flex; gap: 0.4rem; align-items: center; font-size: 0.9rem; }
.export-formats { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-top: 1.1rem; }
.export-dwriter { align-self: flex-start; margin-top: 0.2rem; }
.button.disabled, .button.small.disabled {
	opacity: 0.5; cursor: not-allowed; pointer-events: none;
	background: var(--color-surface); color: var(--color-text-muted); border-color: var(--color-border);
}

/* Add-forms (parts / chapters / scenes) */
.structure-add-bar { display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.5rem; }
.tree-add { display: flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; margin: 0; }
.tree-add input[type="text"] {
	font: inherit; font-size: 0.9rem; padding: 0.3rem 0.5rem; min-width: 10rem;
	border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-surface); color: var(--color-text);
}
.tree-add-part { font-size: 0.85rem; color: var(--color-text-muted); display: inline-flex; gap: 0.3rem; align-items: center; }
.tree-add select {
	font: inherit; font-size: 0.85rem; padding: 0.25rem 0.4rem;
	border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-surface); color: var(--color-text);
}

/* Tree lists */
.tree-parts, .tree-chapters, .tree-scenes { list-style: none; margin: 0; padding: 0; }
.tree-section-title { font-family: var(--font-serif); font-size: 1.1rem; margin: 1.5rem 0 0.5rem; }
.tree-root-chapters { margin-top: 0.5rem; }
.tree-chapters { margin-left: 1.2rem; }
.tree-scenes { margin: 0.4rem 0 0.4rem 1.5rem; }

.tree-part { border: 1px solid var(--color-border); border-radius: var(--radius); padding: 0.6rem 0.8rem; margin-bottom: 1rem; background: color-mix(in srgb, var(--color-primary) 5%, var(--color-surface)); }
.tree-part-head, .tree-chapter-head, .tree-scene { display: flex; gap: 0.6rem; align-items: center; flex-wrap: wrap; }
.tree-part-name { font-family: var(--font-serif); font-weight: 700; font-size: 1.15rem; flex: 1; min-width: 8rem; }

.tree-chapter { border: 1px solid var(--color-border); border-radius: var(--radius); padding: 0.6rem 0.8rem; margin-bottom: 0.6rem; background: var(--color-surface); }
.tree-chapter-name { font-family: var(--font-serif); font-weight: 700; font-size: 1.02rem; flex: 1; min-width: 8rem; }

.tree-scene { padding: 0.25rem 0.3rem; border-radius: var(--radius); }
.tree-scene:hover, .tree-part-head:hover, .tree-chapter-head:hover { background: color-mix(in srgb, var(--color-primary) 8%, transparent); }
.tree-scene-name { flex: 1; min-width: 8rem; text-decoration: none; color: var(--color-text); font-weight: 600; }
.tree-scene-name:hover { color: var(--color-primary); }
.tree-wc { font-size: 0.8rem; white-space: nowrap; }
.tree-empty { list-style: none; padding: 0.3rem 0; font-size: 0.9rem; }

.tree-actions { display: inline-flex; gap: 0.35rem; align-items: center; flex-wrap: wrap; }
.order-btns { display: inline-flex; gap: 0.15rem; }
.icon-btn { min-width: 1.9rem; text-align: center; line-height: 1; }
button.icon-btn:disabled { opacity: 0.35; cursor: default; }

/* Compact edit / rename / delete icon buttons (structure screen). Used on both
   <button> (delete) and <summary> (the edit/rename disclosure toggles). */
.row-icon-btn {
	display: inline-flex; align-items: center; justify-content: center;
	width: 1.9rem; height: 1.9rem; padding: 0; line-height: 0; cursor: pointer;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); color: var(--color-text-muted);
	list-style: none; transition: color 0.12s, border-color 0.12s, background 0.12s;
}
.row-icon-btn::-webkit-details-marker { display: none; }
.row-icon-btn svg { width: 1rem; height: 1rem; display: block; }
.row-icon-btn:hover { color: var(--color-primary); border-color: var(--color-primary); }
.row-rename[open] > summary.row-icon-btn { background: var(--color-primary); color: #fff; border-color: var(--color-primary); }
/* Override the filled button.danger look: a bin icon on a neutral surface that
   only fills red on hover. */
.row-icon-btn.danger { color: #b3372f; background: var(--color-surface); border-color: var(--color-border); }
.row-icon-btn.danger:hover { color: #fff; background: #b3372f; border-color: #b3372f; }
/* #b3372f is only ~2.7:1 on the dark surface. The hover rule must be repeated at
   matching specificity: `html.dark .row-icon-btn.danger` is (0,3,1) and would
   otherwise outrank `.row-icon-btn.danger:hover` at (0,3,0). */
html.dark .row-icon-btn.danger { color: #f08a80; }
html.dark .row-icon-btn.danger:hover { color: #fff; background: #b3372f; border-color: #b3372f; }
/* button[type="submit"] (delete) and .row-rename>summary (edit/rename) are both
   (0,1,1) and otherwise force inline-block + padding, knocking the glyph to the
   top-left. This (0,2,0) override re-centres it and zeroes the padding. */
button.row-icon-btn, .row-rename > summary.row-icon-btn { display: inline-flex; align-items: center; justify-content: center; padding: 0; line-height: 0; }
/* A <button type="submit"> otherwise inherits the filled primary button look
   (bg/border/colour); re-assert the neutral icon-button surface. .danger (0,2,0)
   still wins for the red variant. */
button.row-icon-btn { background: var(--color-surface); border: 1px solid var(--color-border); color: var(--color-text-muted); }

/* Drag affordance */
.drag-handle { cursor: grab; color: var(--color-text-muted); user-select: none; font-size: 1rem; }
.tree-row.dragging { opacity: 0.5; }
.tree-row.drop-before { box-shadow: 0 -3px 0 0 var(--color-primary); }

/* Status pill as a submit button */
.status-pill-form { display: inline; margin: 0; }
button.status-pill { border-radius: 999px; cursor: pointer; line-height: 1.2; }

/* Rename / edit toggles (native <details>) */
.row-rename { display: inline-block; position: relative; }
.row-rename > summary { list-style: none; display: inline-block; }
.row-rename > summary::-webkit-details-marker { display: none; }
.row-rename[open] > summary { background: var(--color-primary); }
.rename-form, .reassign-form { display: flex; gap: 0.35rem; align-items: center; margin: 0.4rem 0 0; flex-wrap: wrap; }
.row-edit-body { display: flex; flex-direction: column; gap: 0.3rem; margin-top: 0.4rem; }
.rename-form input[type="text"] {
	font: inherit; font-size: 0.85rem; padding: 0.25rem 0.45rem; min-width: 9rem;
	border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-surface); color: var(--color-text);
}
.reassign-form select {
	font: inherit; font-size: 0.85rem; padding: 0.2rem 0.4rem;
	border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-surface); color: var(--color-text);
}

/* Generic small span-buttons (spans styled as buttons, e.g. disabled links) */
.button.small { padding: 0.2rem 0.6rem; font-size: 0.85rem; }

/* ══ Scene editor (rich TipTap editor — three-pane chrome) ══════════════════ */

/* ── Scene editor shell (editorPage) ──────────────────────────────────────────
   A fixed viewport-height flex column: slim header, then the panes fill the
   rest and scroll INTERNALLY, so growing content never pushes anything off the
   bottom of the screen. No site footer here. */
/* Height is layered: 100vh works everywhere; 100dvh tracks the mobile URL bar
   where supported. WITHOUT the 100vh fallback, a browser that lacks dvh drops
   the declaration entirely, the body falls to height:auto, the whole page grows
   and scrolls, and the header disappears behind the address bar — trapping the
   user with no way back to Home. */
/* position:fixed pins the shell to the viewport (the inline script below refines
   it to the VISUAL viewport so it tracks the on-screen keyboard). Nothing in the
   document can scroll — only the inner .scene-scroll — so the header + toolbar
   can never be scrolled off, no matter how many lines are typed. */
.editor-body { position: fixed; top: 0; left: 0; width: 100%; height: 100vh; height: 100dvh; margin: 0; display: flex; flex-direction: column; overflow: hidden; background: var(--color-bg); }
.editor-header {
	position: sticky; top: 0; z-index: 20;
	flex: 0 0 auto; display: flex; align-items: center; gap: 0.6rem;
	padding: 0.3rem 0.9rem; border-bottom: 1px solid var(--color-border); background: var(--color-surface);
}
.editor-home { flex: 0 0 auto; }
.editor-home svg { height: 1.5rem; width: auto; }
.editor-story {
	flex: 0 1 auto; min-width: 3rem; font-family: var(--font-serif); font-weight: 700; font-size: 1.05rem;
	color: var(--color-text); text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.editor-story:hover { color: var(--color-primary); }
.editor-header .save-status { flex: 0 0 auto; font-size: 0.85rem; }
.editor-header-spacer { flex: 1 1 auto; }
.editor-header .wc { flex: 0 0 auto; white-space: nowrap; font-size: 0.85rem; }
/* Scoped to .editor-body so it doesn't collide with the admin page editor's
   own .editor-main (a grid column in .editor-columns). */
.editor-body > .editor-main { flex: 1 1 0; min-height: 0; display: flex; }
.editor-body > .editor-main > .scene-shell { flex: 1 1 0; min-height: 0; }
@media (max-width: 40rem) {
	/* Split the header into two rows: icon + story + save on row 1; the
	   right-hand group (word counts, S/M/L, theme) drops to row 2. A full-width
	   flex spacer forces the wrap between the two groups. */
	.editor-header { flex-wrap: wrap; row-gap: 0.15rem; }
	.editor-header-spacer { flex-basis: 100%; height: 0; }
}

/* Break the editor out of the centered content column: it owns the viewport. */
.site-main:has(.scene-shell) { max-width: none; padding: 0; display: flex; }

.scene-shell {
	flex: 1;
	min-height: 0;
	display: flex;
	position: relative;
	background: var(--color-bg);
}

/* ── Side panels ─────────────────────────────────────────────────────────── */
.scene-panel {
	flex: 0 0 auto;
	width: 16rem;
	overflow-y: auto;
	overflow-x: hidden;
	background: var(--color-surface);
	transition: width 0.2s ease, padding 0.2s ease;
}
.scene-panel-left { border-right: 1px solid var(--color-border); }
.scene-panel-right { width: 19rem; border-left: 1px solid var(--color-border); padding: 1rem; }
.panel-left-collapsed .scene-panel-left,
.panel-right-collapsed .scene-panel-right { width: 0; border-color: transparent; border-width: 0; }
/* Zero the right panel's own padding when collapsed, or box-sizing keeps it
   2rem wide (the padding floor) even at width: 0. The border width must go
   too, or a 1px strip of the panel remains in the layout. */
.panel-right-collapsed .scene-panel-right { padding-left: 0; padding-right: 0; }

.panel-head { padding: 0.9rem 1rem 0.5rem; border-bottom: 1px solid var(--color-border); position: sticky; top: 0; background: var(--color-surface); }
.panel-story-title {
	font-family: var(--font-serif); font-weight: 700; font-size: 1.05rem;
	text-decoration: none; color: var(--color-text); display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.panel-story-title:hover { color: var(--color-primary); }

.scene-nav { padding: 0.5rem 0.75rem 1.5rem; font-size: 0.9rem; }
.scene-nav ul { list-style: none; margin: 0; padding: 0; }
/* Parts and chapters are collapsible <details class="nav-fold">; the server
   opens only the ancestors of the current scene, so the drawer lands focused. */
.nav-fold { margin: 0; }
.nav-fold > summary {
	list-style: none; cursor: pointer; display: flex; align-items: center; gap: 0.35rem;
	padding: 0.15rem 0.2rem; border-radius: var(--radius); user-select: none;
}
.nav-fold > summary::-webkit-details-marker { display: none; }
.nav-fold > summary::before {
	content: "▸"; flex: none; font-size: 0.7em; line-height: 1; color: var(--color-text-muted);
	transition: transform 0.12s ease;
}
.nav-fold[open] > summary::before { transform: rotate(90deg); }
.nav-fold > summary:hover { background: color-mix(in srgb, var(--color-primary) 10%, transparent); }
.nav-part-name { font-weight: 700; margin: 0.6rem 0 0.2rem; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--color-text-muted); }
.nav-chapter-name { font-weight: 600; margin: 0.5rem 0 0.15rem; color: var(--color-text); }
.nav-chapters { padding-left: 0.4rem; }
.nav-scenes { padding-left: 0.6rem; border-left: 1px solid var(--color-border); margin-left: 0.2rem; }
.nav-scene {
	display: flex; align-items: baseline; gap: 0.5rem;
	padding: 0.25rem 0.5rem; border-radius: var(--radius);
	text-decoration: none; color: var(--color-text);
}
.nav-scene-title { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nav-scene-wc { flex: none; margin-left: auto; font-size: 0.75rem; color: var(--color-text-muted); opacity: 0.8; font-variant-numeric: tabular-nums; }
.nav-scene:hover { background: color-mix(in srgb, var(--color-primary) 10%, transparent); }
.nav-scene.is-current { background: color-mix(in srgb, var(--color-primary) 18%, transparent); font-weight: 600; color: var(--color-primary); }
.nav-empty { padding: 0.25rem 0.5rem; font-size: 0.85rem; }

/* ── Center column ───────────────────────────────────────────────────────── */
.scene-center { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; position: relative; }

.scene-topbar {
	display: flex; align-items: center; gap: 0.4rem;
	padding: 0.35rem 0.6rem; border-bottom: 1px solid var(--color-border);
	background: var(--color-surface); position: sticky; top: 0; z-index: 5;
}

/* Drawer pull-tabs: vertical tabs sitting at each drawer's inner seam, sticking
   out into the editor. The chevrons point the way the tab moves the drawer —
   left tab «open / »closed, right tab »open / «closed — driven purely by the
   shell's collapse classes, so the existing toggle JS needs no change. */
.panel-tab {
	position: absolute; top: 3.4rem; z-index: 12;
	width: 1.4rem; height: 3.75rem; padding: 0; cursor: pointer;
	display: flex; align-items: center; justify-content: center;
	border: 1px solid var(--color-border);
	background: var(--color-surface); color: var(--color-text-muted);
	font-size: 0.9rem; line-height: 1;
	transition: color 0.12s, background 0.12s;
}
.panel-tab:hover { color: var(--color-primary); background: color-mix(in srgb, var(--color-primary) 10%, transparent); }
.panel-tab-left  { left: 0;  border-left: none;  border-radius: 0 var(--radius) var(--radius) 0; }
.panel-tab-right { right: 0; border-right: none; border-radius: var(--radius) 0 0 var(--radius); }
.panel-tab::after { content: "«"; }
.panel-tab-right::after { content: "»"; }
.panel-left-collapsed  .panel-tab-left::after  { content: "»"; }
.panel-right-collapsed .panel-tab-right::after { content: "«"; }

/* ── Toolbar ─────────────────────────────────────────────────────────────── */
.editor-toolbar { flex: 1 1 auto; display: flex; flex-wrap: wrap; align-items: center; gap: 0.15rem; }
.tb-group { display: flex; align-items: center; gap: 0.1rem; padding: 0 0.25rem; }
.tb-group + .tb-group { border-left: 1px solid var(--color-border); }
.tb-btn {
	display: inline-flex; align-items: center; justify-content: center;
	min-width: 1.9rem; height: 1.9rem; padding: 0 0.4rem;
	border: 1px solid transparent; border-radius: var(--radius);
	background: transparent; color: var(--color-text); cursor: pointer;
	font-size: 0.95rem; line-height: 1;
}
.tb-btn:hover { background: color-mix(in srgb, var(--color-primary) 10%, transparent); }
.tb-btn.is-active { background: color-mix(in srgb, var(--color-primary) 20%, transparent); border-color: color-mix(in srgb, var(--color-primary) 35%, transparent); color: var(--color-primary); }
.tb-btn:disabled { opacity: 0.4; cursor: default; background: transparent; }
.tb-btn svg { display: block; }
.tb-bold { font-weight: 700; }
.tb-italic { font-style: italic; }
.tb-underline { text-decoration: underline; }
.tb-strike { text-decoration: line-through; }
.tb-select {
	height: 1.9rem; padding: 0 0.4rem; font: inherit; font-size: 0.85rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); color: var(--color-text); cursor: pointer;
}

/* ── Editing surface ─────────────────────────────────────────────────────── */
.scene-scroll { flex: 1 1 0; min-height: 0; overflow-y: auto; }
.scene-surface { padding: 2.5rem 1.5rem 6rem; }
.scene-surface .ProseMirror {
	max-width: 72ch; margin: 0 auto;
	/* Per-user editor font (M9): the surface sets --editor-font-family inline when
	   a non-default font is chosen; otherwise falls back to the site serif. */
	font-family: var(--editor-font-family, var(--font-serif)); line-height: 1.75; color: var(--color-text);
	caret-color: var(--color-primary); outline: none;
}
.scene-surface .ProseMirror:focus { outline: none; }
.scene-surface.font-s .ProseMirror { font-size: 16px; }
.scene-surface.font-m .ProseMirror { font-size: 20px; }
.scene-surface.font-l .ProseMirror { font-size: 26px; }
.scene-surface .ProseMirror > * + * { margin-top: 0.9em; }
.scene-surface .ProseMirror h1, .scene-surface .ProseMirror h2,
.scene-surface .ProseMirror h3, .scene-surface .ProseMirror h4 { font-family: var(--editor-font-family, var(--font-serif)); font-weight: 700; line-height: 1.25; margin-top: 1.4em; }
.scene-surface .ProseMirror h1 { font-size: 1.9em; }
.scene-surface .ProseMirror h2 { font-size: 1.55em; }
.scene-surface .ProseMirror h3 { font-size: 1.25em; }
.scene-surface .ProseMirror h4 { font-size: 1.1em; }
.scene-surface .ProseMirror ul, .scene-surface .ProseMirror ol { padding-left: 1.6em; }
.scene-surface .ProseMirror li > p { margin: 0; }
.scene-surface .ProseMirror blockquote {
	border-left: 3px solid color-mix(in srgb, var(--color-primary) 50%, transparent);
	padding-left: 1rem; margin-left: 0; color: var(--color-text-muted); font-style: italic;
}
.scene-surface .ProseMirror hr { border: none; border-top: 1px solid var(--color-border); margin: 1.6em 0; }
.scene-surface .ProseMirror img { max-width: 100%; height: auto; }
.scene-surface .ProseMirror p.is-editor-empty:first-child::before { content: attr(data-placeholder); color: var(--color-text-muted); float: left; height: 0; pointer-events: none; }

/* ── Status bar ──────────────────────────────────────────────────────────── */
.scene-statusbar {
	display: flex; align-items: center; gap: 0.9rem;
	padding: 0.4rem 0.9rem; border-top: 1px solid var(--color-border);
	background: var(--color-surface); font-size: 0.85rem; color: var(--color-text-muted);
}
.status-spacer { flex: 1 1 auto; }
.save-status { font-weight: 600; }
.save-status[data-state="saved"] { color: var(--color-accent); }
.save-status[data-state="saving"] { color: var(--color-text-muted); }
.save-status[data-state="unsaved"] { color: var(--color-text-muted); }
.save-status[data-state="error"] { color: #b3372f; }
/* Offline isn't an error — work is safe in the local draft. Muted, not red. */
.save-status[data-state="offline"] { color: var(--color-text-muted); font-weight: 500; }
.scene-statusbar .wc { white-space: nowrap; }

/* Restore-unsaved-changes banner (injected at the top of the editor column when
   a newer local draft is found on open). */
.editor-restore-banner {
	display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
	margin: 0.6rem; padding: 0.7rem 1rem;
	border: 1px solid var(--color-border); border-left: 4px solid var(--color-primary);
	border-radius: var(--radius); background: var(--color-surface); color: var(--color-text);
}
.editor-restore-text { font-size: 0.9rem; flex: 1 1 14rem; }
.editor-restore-actions { display: inline-flex; align-items: center; gap: 0.75rem; flex: 0 0 auto; }
.fontsize-toggle { display: inline-flex; gap: 0.15rem; }
.font-btn {
	width: 1.7rem; height: 1.7rem; padding: 0; font-size: 0.8rem; cursor: pointer;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); color: var(--color-text);
}
.font-btn:hover { background: color-mix(in srgb, var(--color-primary) 10%, transparent); }
.font-btn.is-active { background: color-mix(in srgb, var(--color-primary) 20%, transparent); border-color: var(--color-primary); color: var(--color-primary); font-weight: 700; }

/* ── Notes panel ─────────────────────────────────────────────────────────── */
.notes-block { margin-bottom: 1.2rem; }
.notes-label-row { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 0.3rem; }
.notes-label-row label { font-weight: 600; font-size: 0.9rem; }
.notes-hint { font-size: 0.75rem; color: var(--color-text-muted); }
.notes-hint.is-saved { color: var(--color-accent); }
.notes-hint.is-error { color: #b3372f; }
.notes-textarea {
	width: 100%; min-height: 8rem; resize: vertical; font: inherit; font-size: 0.9rem; line-height: 1.5;
	padding: 0.6rem; border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); color: var(--color-text);
}
.m5-placeholders { margin-top: 1.5rem; padding-top: 1rem; border-top: 1px dashed var(--color-border); }
.m5-item { font-size: 0.8rem; font-style: italic; }

/* ── Overlay scrim (narrow layouts) ──────────────────────────────────────── */
.panel-scrim { display: none; position: absolute; inset: 0; z-index: 10; background: rgba(0, 0, 0, 0.35); }

@media (max-width: 64rem) {
	.scene-panel { position: absolute; top: 0; bottom: 0; z-index: 15; box-shadow: 0 0 1.5rem rgba(0, 0, 0, 0.25); }
	.scene-panel-left { left: 0; }
	.scene-panel-right { right: 0; }
	.scene-shell:not(.panel-left-collapsed) .panel-scrim,
	.scene-shell:not(.panel-right-collapsed) .panel-scrim { display: block; }
	/* When a drawer is open as an overlay, ride its close tab on the drawer's
	   inner edge, above the drawer, so it stays visible and taps shut. Widths
	   match the panel widths for this breakpoint. */
	.scene-shell:not(.panel-left-collapsed) .panel-tab-left { left: 16rem; z-index: 16; }
	.scene-shell:not(.panel-right-collapsed) .panel-tab-right { right: 19rem; z-index: 16; }
}
@media (max-width: 40rem) {
	.scene-panel-left { width: 13rem; }
	.scene-panel-right { width: 15rem; }
	.scene-shell:not(.panel-left-collapsed) .panel-tab-left { left: 13rem; }
	.scene-shell:not(.panel-right-collapsed) .panel-tab-right { right: 15rem; }
	.scene-surface { padding: 1.5rem 1rem 5rem; }
}

/* ══════════════════════════════════════════════════════════════════════════
   M5: inline images, find & replace, highlights, word sprints, toasts
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Inline image bubble ─────────────────────────────────────────────────── */
.writer-img-bubble {
	position: absolute; z-index: 30; display: none; flex-direction: column; gap: 0.35rem;
	min-width: 15rem; padding: 0.5rem; border-radius: var(--radius);
	background: var(--color-surface); border: 1px solid var(--color-border);
	box-shadow: 0 0.4rem 1.2rem rgba(0, 0, 0, 0.22);
}
.writer-img-bubble.is-shown { display: flex; }
.writer-img-bubble .ib-row { display: flex; gap: 0.2rem; align-items: center; flex-wrap: wrap; }
.ib-btn {
	flex: 0 0 auto; padding: 0.2rem 0.5rem; font-size: 0.78rem; cursor: pointer;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); color: var(--color-text);
}
.ib-btn:hover { background: color-mix(in srgb, var(--color-primary) 12%, transparent); }
.ib-btn.is-active { background: color-mix(in srgb, var(--color-primary) 22%, transparent); border-color: var(--color-primary); color: var(--color-primary); font-weight: 600; }
.ib-widths .ib-btn { min-width: 2.6rem; }
.ib-alt-input {
	width: 100%; padding: 0.3rem 0.4rem; font: inherit; font-size: 0.8rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); color: var(--color-text);
}
.ib-remove { color: #b3372f; border-color: color-mix(in srgb, #b3372f 40%, var(--color-border)); }
.ib-remove:hover { background: color-mix(in srgb, #b3372f 12%, transparent); }
.scene-surface .ProseMirror .ProseMirror-selectednode { outline: 2px solid var(--color-primary); outline-offset: 2px; }

/* ── Find & replace bar ──────────────────────────────────────────────────── */
.find-host { position: relative; }
.find-bar {
	display: none; flex-direction: column; gap: 0.4rem;
	padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--color-border);
	background: var(--color-surface);
}
.find-bar.is-open { display: flex; }
.fr-row { display: flex; align-items: flex-end; gap: 0.4rem; flex-wrap: wrap; }
.fr-field { display: flex; flex-direction: column; gap: 0.1rem; flex: 1 1 9rem; min-width: 8rem; }
.fr-field-label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-text-muted); }
.fr-query, .fr-replace {
	width: 100%; padding: 0.3rem 0.45rem; font: inherit; font-size: 0.85rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); color: var(--color-text);
}
.fr-count { font-size: 0.8rem; color: var(--color-text-muted); white-space: nowrap; align-self: center; min-width: 4.5rem; }
.fr-btn {
	flex: 0 0 auto; height: 1.9rem; padding: 0 0.6rem; font-size: 0.82rem; cursor: pointer;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); color: var(--color-text);
}
.fr-btn:hover { background: color-mix(in srgb, var(--color-primary) 12%, transparent); }
.fr-close { min-width: 1.9rem; }
.fr-opts { display: flex; align-items: center; gap: 0.8rem; flex-wrap: wrap; font-size: 0.8rem; }
.fr-check { display: inline-flex; align-items: center; gap: 0.3rem; cursor: pointer; }
.fr-scope {
	height: 1.8rem; padding: 0 0.4rem; font: inherit; font-size: 0.8rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); color: var(--color-text);
}
.fr-progress { font-size: 0.8rem; color: var(--color-primary); font-weight: 600; }
.fr-results { max-height: 40vh; overflow-y: auto; display: flex; flex-direction: column; gap: 0.15rem; }
.fr-results-head, .fr-results-empty { font-size: 0.78rem; color: var(--color-text-muted); padding: 0.2rem 0; }
.fr-chapter { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-text-muted); margin-top: 0.4rem; }
.fr-result {
	text-align: left; width: 100%; padding: 0.4rem 0.5rem; cursor: pointer;
	border: 1px solid transparent; border-radius: var(--radius);
	background: transparent; color: var(--color-text);
}
.fr-result:hover { background: color-mix(in srgb, var(--color-primary) 10%, transparent); border-color: var(--color-border); }
.fr-result-name { font-weight: 600; font-size: 0.85rem; }
.fr-snippet { font-size: 0.78rem; color: var(--color-text-muted); margin-top: 0.15rem; line-height: 1.4; }
.fr-mark, mark.fr-mark { background: color-mix(in srgb, var(--color-primary) 35%, transparent); color: var(--color-text); border-radius: 2px; padding: 0 1px; }

/* ── Find-in-editor match decorations ────────────────────────────────────── */
.writer-find-match { background: color-mix(in srgb, #f5c518 45%, transparent); border-radius: 2px; }
.writer-find-current { background: color-mix(in srgb, #f5891f 70%, transparent); }

/* ── Highlights decoration + panel list ──────────────────────────────────── */
.writer-highlight { background: color-mix(in srgb, #ffbf47 40%, transparent); border-radius: 2px; box-shadow: 0 0 0 1px color-mix(in srgb, #ffbf47 55%, transparent) inset; }

.panel-section { margin-top: 1.4rem; padding-top: 1rem; border-top: 1px solid var(--color-border); }
.panel-section-title { font-size: 0.9rem; font-weight: 700; margin: 0 0 0.6rem; }
.hl-list { display: flex; flex-direction: column; gap: 0.5rem; }
.hl-empty { font-size: 0.8rem; font-style: italic; }
.hl-entry {
	padding: 0.5rem; border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); display: flex; flex-direction: column; gap: 0.25rem;
}
.hl-entry.hl-orphan { border-style: dashed; opacity: 0.85; }
.hl-snippet {
	text-align: left; font-size: 0.82rem; line-height: 1.35; cursor: pointer;
	background: none; border: none; padding: 0; color: var(--color-text); font-family: var(--font-serif);
}
.hl-snippet:hover:not(:disabled) { color: var(--color-primary); }
.hl-snippet:disabled { cursor: default; }
.hl-flag { font-size: 0.72rem; color: #b3372f; font-style: italic; }
.hl-note { font-size: 0.78rem; color: var(--color-text-muted); }
.hl-actions { display: flex; gap: 0.5rem; margin-top: 0.1rem; }
.hl-action {
	font-size: 0.72rem; padding: 0.1rem 0.35rem; cursor: pointer;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); color: var(--color-text);
}
.hl-action:hover { background: color-mix(in srgb, var(--color-primary) 12%, transparent); }
.hl-del { color: #b3372f; }

/* Inline add-note popover. */
.hl-popover {
	position: absolute; z-index: 32; display: flex; gap: 0.25rem; padding: 0.4rem;
	border-radius: var(--radius); background: var(--color-surface);
	border: 1px solid var(--color-border); box-shadow: 0 0.4rem 1.2rem rgba(0, 0, 0, 0.22);
}
.hl-popover-input {
	width: 12rem; padding: 0.25rem 0.4rem; font: inherit; font-size: 0.8rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); color: var(--color-text);
}
.hl-popover-save, .hl-popover-cancel {
	padding: 0.2rem 0.5rem; font-size: 0.78rem; cursor: pointer;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); color: var(--color-text);
}
.hl-popover-save { background: color-mix(in srgb, var(--color-primary) 18%, transparent); border-color: var(--color-primary); }

/* ── Word sprint widget ──────────────────────────────────────────────────── */
.sprint-widget { display: flex; flex-direction: column; gap: 0.6rem; }
.sprint-setup { display: flex; flex-direction: column; gap: 0.5rem; }
.sprint-field { display: flex; flex-direction: column; gap: 0.15rem; font-size: 0.75rem; color: var(--color-text-muted); }
.sprint-num {
	padding: 0.3rem 0.4rem; font: inherit; font-size: 0.85rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); color: var(--color-text);
}
.sprint-btn {
	padding: 0.4rem 0.6rem; font-size: 0.82rem; cursor: pointer;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); color: var(--color-text);
}
.sprint-btn:hover { background: color-mix(in srgb, var(--color-primary) 12%, transparent); }
.sprint-start { background: color-mix(in srgb, var(--color-primary) 18%, transparent); border-color: var(--color-primary); font-weight: 600; }
.sprint-live { display: flex; flex-direction: column; gap: 0.5rem; }
.sprint-stats { display: flex; justify-content: space-between; align-items: baseline; }
.sprint-elapsed { font-size: 1.5rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.sprint-words { font-size: 0.9rem; color: var(--color-text-muted); }
.sprint-bar { position: relative; height: 1.1rem; border-radius: var(--radius); background: color-mix(in srgb, var(--color-border) 60%, transparent); overflow: hidden; }
.sprint-bar-fill { position: absolute; inset: 0 auto 0 0; width: 0; background: color-mix(in srgb, var(--color-primary) 55%, transparent); transition: width 0.3s ease; }
.sprint-bar.is-full .sprint-bar-fill { background: color-mix(in srgb, var(--color-accent) 65%, transparent); }
.sprint-bar-label { position: relative; z-index: 1; display: block; font-size: 0.68rem; line-height: 1.1rem; text-align: center; color: var(--color-text); }
.sprint-controls { display: flex; gap: 0.4rem; }
.sprint-controls .sprint-btn { flex: 1 1 0; }
.sprint-widget.target-hit .sprint-elapsed { color: var(--color-accent); }
.sprint-recent { margin-top: 0.4rem; }
.sprint-recent-title { font-size: 0.78rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; color: var(--color-text-muted); margin: 0 0 0.35rem; }
.sprint-recent-empty { font-size: 0.78rem; font-style: italic; }
.sprint-recent-row { padding: 0.3rem 0; border-bottom: 1px solid var(--color-border); }
.srr-main { font-size: 0.82rem; font-weight: 600; }
.srr-meta { font-size: 0.72rem; }

/* ── Toasts ──────────────────────────────────────────────────────────────── */
.writer-toast-host {
	position: fixed; bottom: 1.2rem; left: 50%; transform: translateX(-50%);
	z-index: 1000; display: flex; flex-direction: column; gap: 0.4rem; align-items: center; pointer-events: none;
}
.writer-toast {
	pointer-events: auto; max-width: 90vw; padding: 0.5rem 0.9rem; border-radius: var(--radius);
	font-size: 0.85rem; color: #fff; background: #333;
	box-shadow: 0 0.3rem 1rem rgba(0, 0, 0, 0.25);
	opacity: 0; transform: translateY(0.5rem); transition: opacity 0.2s ease, transform 0.2s ease;
}
.writer-toast.is-shown { opacity: 1; transform: translateY(0); }
.writer-toast.is-leaving { opacity: 0; }
.writer-toast-error { background: #b3372f; }
.writer-toast-success { background: #1c7a45; }

/* ── Collapsible right-panel sections (scene editor) ── */
.panel-fold { border-bottom: 1px solid var(--color-border); }
.panel-fold-summary {
	cursor: pointer;
	list-style: none;
	display: flex; align-items: center; gap: 0.5rem;
	padding: 0.7rem 0.15rem;
	font-weight: 600; font-size: 0.95rem;
	user-select: none;
}
.panel-fold-summary::-webkit-details-marker { display: none; }
.panel-fold-summary::before {
	content: '▸';
	font-size: 0.8em;
	color: var(--color-text-muted);
	transition: transform 0.15s ease;
}
.panel-fold[open] > .panel-fold-summary::before { transform: rotate(90deg); }
.panel-fold-summary .notes-hint { margin-left: auto; font-weight: 400; }
.panel-fold-body { padding: 0 0.15rem 0.9rem; }

/* Writing goals at the top of the notes drawer — never collapsed, no type
   headings. Each goal carries its own bottom divider (matching the fold rows),
   so the first has no divider above it and none ever double up. */
.drawer-goal { border-bottom: 1px solid var(--color-border); padding: 0.7rem 0.15rem 0.9rem; }
.drawer-goal-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.3rem; }
.drawer-goal-name { font-weight: 600; font-size: 0.9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drawer-goal-pct { flex: none; font-variant-numeric: tabular-nums; color: var(--color-text-muted); font-size: 0.85rem; }
.drawer-goal-count { margin-top: 0.3rem; font-size: 0.8rem; }

/* The hidden attribute must beat the flex display on the sprint live block. */
.sprint-live[hidden] { display: none; }

/* ══════════════════════════════════════════════════════════════════════════
   M6 part 1: notes & frontmatter screens, note editor, reading mode
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Notes / Frontmatter list screen ─────────────────────────────────────── */
/* Fills the full site-main width, consistent with the other in-container pages. */
.notes-screen { max-width: none; }
.notes-blurb { margin: 0.25rem 0 1.5rem; }
.notes-list { list-style: none; margin: 0 0 1.5rem; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.notes-row {
	display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap;
	padding: 0.6rem 0.8rem; border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface);
}
.notes-row-title { font-family: var(--font-serif); font-weight: 700; font-size: 1.05rem; text-decoration: none; color: var(--color-text); }
.notes-row-title:hover { color: var(--color-primary); }
.notes-row-wc { font-size: 0.8rem; white-space: nowrap; }
.notes-row-actions { display: flex; align-items: center; gap: 0.3rem; margin-left: auto; flex-wrap: wrap; }
.notes-empty { padding: 1rem; border: 1px dashed var(--color-border); border-radius: var(--radius); text-align: center; }
.notes-new-form { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
.notes-new-form input[type="text"] {
	flex: 1 1 16rem; min-width: 0; padding: 0.5rem 0.6rem; font: inherit;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); color: var(--color-text);
}

/* ── Note editor page ────────────────────────────────────────────────────── */
/* The note editor shares the scene editor's shell (row layout + left panel);
   .scene-shell/.scene-center provide the layout, so no overrides here. */
/* The note editor reuses the scene shell/centre/topbar/scroll and drawer tab;
   only the document title + surface are note-specific. The title sits at the top
   of the scroll area as an editable heading, aligned with the content column. */
/* Static document title (renaming lives on the notes/frontmatter list screens). */
.note-doc-title { max-width: 72ch; margin: 0 auto; padding: 1.5rem 1.5rem 0; font-family: var(--font-serif); font-weight: 700; font-size: 1.9rem; line-height: 1.2; }
.note-surface { padding: 2.5rem 1.5rem 6rem; }
.note-doc .note-surface { padding-top: 0.6rem; }
.note-surface .ProseMirror {
	max-width: 72ch; margin: 0 auto;
	font-family: var(--editor-font-family, var(--font-serif)); line-height: 1.75; color: var(--color-text);
	caret-color: var(--color-primary); outline: none;
}
.note-surface .ProseMirror:focus { outline: none; }
.note-surface.font-s .ProseMirror { font-size: 16px; }
.note-surface.font-m .ProseMirror { font-size: 20px; }
.note-surface.font-l .ProseMirror { font-size: 26px; }
.note-surface .ProseMirror > * + * { margin-top: 0.9em; }
.note-surface .ProseMirror h1, .note-surface .ProseMirror h2,
.note-surface .ProseMirror h3, .note-surface .ProseMirror h4 { font-family: var(--editor-font-family, var(--font-serif)); font-weight: 700; line-height: 1.25; margin-top: 1.4em; }
.note-surface .ProseMirror h1 { font-size: 1.9em; }
.note-surface .ProseMirror h2 { font-size: 1.55em; }
.note-surface .ProseMirror h3 { font-size: 1.25em; }
.note-surface .ProseMirror h4 { font-size: 1.1em; }
.note-surface .ProseMirror ul, .note-surface .ProseMirror ol { padding-left: 1.6em; }
.note-surface .ProseMirror li > p { margin: 0; }
.note-surface .ProseMirror blockquote {
	border-left: 3px solid color-mix(in srgb, var(--color-primary) 50%, transparent);
	padding-left: 1rem; margin-left: 0; color: var(--color-text-muted); font-style: italic;
}
.note-surface .ProseMirror hr { border: none; border-top: 1px solid var(--color-border); margin: 1.6em 0; }
.note-surface .ProseMirror img { max-width: 100%; height: auto; }
.note-surface .ProseMirror .ProseMirror-selectednode { outline: 2px solid var(--color-primary); outline-offset: 2px; }

@media (max-width: 40rem) {
	.note-surface { padding: 1.5rem 1rem 5rem; }
	.note-doc-title { padding: 1.25rem 1rem 0; font-size: 1.6rem; }
}

/* ── Reading mode ─────────────────────────────────────────────────────────── */
.reading-page { position: relative; }
.reader-bar {
	position: sticky; top: 0; z-index: 20;
	display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
	margin: -0.5rem 0 1.5rem; padding: 0.5rem 0.75rem;
	border-bottom: 1px solid var(--color-border); background: var(--color-surface);
}
.reader-bar-spacer { flex: 1 1 auto; }
.reader-toc-label { display: inline-flex; align-items: center; }
.reader-toc {
	max-width: 16rem; height: 1.9rem; padding: 0 0.4rem; font: inherit; font-size: 0.85rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); color: var(--color-text); cursor: pointer;
}
.reader-nav { min-width: 2rem; }
.reader-font-btn { width: auto; min-width: 1.9rem; padding: 0 0.5rem; }

.reading-view {
	max-width: 40rem; margin: 0 auto; padding: 0 0.5rem 6rem;
	font-family: var(--font-serif); color: var(--color-text);
}
.reading-view.reader-font-s { font-size: 17px; line-height: 1.7; }
.reading-view.reader-font-m { font-size: 19px; line-height: 1.75; }
.reading-view.reader-font-l { font-size: 22px; line-height: 1.8; }

.reading-header { text-align: center; margin: 1rem 0 2.5rem; padding-bottom: 1.5rem; border-bottom: 1px solid var(--color-border); }
.reading-title { font-family: var(--font-serif); font-size: 2.1em; margin: 0 0 0.3em; }
.reading-authors { color: var(--color-text-muted); font-style: italic; margin: 0; }

.reading-part { text-align: center; margin: 3rem 0 2rem; }
.reading-part-title { font-family: var(--font-serif); font-size: 1.7em; letter-spacing: 0.02em; margin: 0; }
.reading-chapter { margin: 2.5rem 0; }
.reading-chapter-title { font-family: var(--font-serif); font-size: 1.4em; text-align: center; margin: 0 0 1.5rem; }
.reading-frontmatter { margin: 2rem 0 2.5rem; padding-bottom: 1.5rem; border-bottom: 1px dashed var(--color-border); }
.reading-front-title { font-family: var(--font-serif); font-size: 1.3em; text-align: center; margin: 0 0 1rem; }

/* Rendered scene / frontmatter content — stored sanitised, emitted as-is. */
.reading-view p { margin: 0 0 1em; }
.reading-view h1, .reading-view h2, .reading-view h3, .reading-view h4 { font-family: var(--font-serif); font-weight: 700; line-height: 1.3; margin: 1.4em 0 0.5em; }
.reading-view ul, .reading-view ol { padding-left: 1.6em; margin: 0 0 1em; }
.reading-view blockquote {
	border-left: 3px solid color-mix(in srgb, var(--color-primary) 50%, transparent);
	padding-left: 1rem; margin: 0 0 1em; color: var(--color-text-muted); font-style: italic;
}
.reading-view hr { border: none; border-top: 1px solid var(--color-border); margin: 1.6em 0; }

.reading-scene-break { text-align: center; color: var(--color-text-muted); letter-spacing: 0.5em; margin: 2rem 0; }
.reading-empty, .reading-empty-state { text-align: center; font-style: italic; }
.reading-empty-state { padding: 3rem 1rem; }

/* Inline images — width applied by reader.js from data-width; alignment here. */
.reading-view img { max-width: 100%; height: auto; }
.reading-view img[data-align="center"] { display: block; margin: 0.5em auto; float: none; }
.reading-view img[data-align="right"] { display: inline; float: right; margin: 0 0 0.5em 1em; }
.reading-view img[data-align="left"] { display: inline; float: left; margin: 0 1em 0.5em 0; }
.reading-chapter::after, .reading-frontmatter::after { content: ""; display: block; clear: both; }

/* Floating "Edit this scene" affordance. */
.reader-edit-fab {
	position: fixed; right: 1.2rem; bottom: 1.2rem; z-index: 25;
	padding: 0.55rem 0.9rem; border-radius: 2rem; text-decoration: none;
	background: var(--color-primary); color: var(--color-primary-contrast);
	font-size: 0.85rem; font-family: var(--font-body); font-weight: 600;
	box-shadow: 0 0.3rem 0.9rem rgba(0, 0, 0, 0.25);
}
.reader-edit-fab[hidden] { display: none; }
.reader-edit-fab:hover { background: color-mix(in srgb, var(--color-primary) 85%, #000); }

.visually-hidden {
	position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
	overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

@media (max-width: 40rem) {
	.reader-toc { max-width: 9rem; }
	.reading-view { padding-left: 0.8rem; padding-right: 0.8rem; }
}

/* ── Writing goals & statistics (M6 part 2) ─────────────────────────────────── */
.goals-screen { max-width: var(--content-width); margin: 0 auto; }
.goals-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.goals-head h1 { margin: 0; }

/* Stat strip */
.stat-strip { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.8rem; margin: 1rem 0 1.5rem; }
.stat-card {
	display: flex; flex-direction: column; align-items: center; text-align: center;
	padding: 0.9rem 0.6rem; border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface);
}
.stat-value { font-size: 1.9rem; font-weight: 700; line-height: 1.1; color: var(--color-primary); font-family: var(--font-serif); }
.stat-label { font-size: 0.85rem; margin-top: 0.25rem; }
.stat-sub { font-size: 0.75rem; }
@media (max-width: 34rem) { .stat-strip { grid-template-columns: repeat(2, 1fr); } }

/* Heatmap */
.heatmap-section {
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); padding: 1rem; margin-bottom: 1.5rem;
}
.heatmap-title { font-size: 1rem; margin: 0 0 0.7rem; }
.heatmap-scroll { overflow-x: auto; padding-bottom: 0.3rem; }
.heatmap-inner { --hm-cell: 13px; --hm-gap: 3px; --hm-gutter: 30px; display: inline-block; min-width: 0; }
.heatmap-months {
	display: grid; grid-template-columns: repeat(var(--hm-weeks), calc(var(--hm-cell) + var(--hm-gap)));
	margin-left: var(--hm-gutter); height: 1rem;
}
.heatmap-month { font-size: 0.65rem; color: var(--color-text-muted); white-space: nowrap; overflow: visible; }
.heatmap-main { display: flex; gap: var(--hm-gap); }
.heatmap-weekdays {
	display: grid; grid-template-rows: repeat(7, var(--hm-cell)); gap: var(--hm-gap);
	width: calc(var(--hm-gutter) - var(--hm-gap)); font-size: 0.6rem; color: var(--color-text-muted);
}
.heatmap-weekdays span { line-height: var(--hm-cell); text-align: right; padding-right: 0.3rem; }
.heatmap-grid {
	display: grid; grid-template-rows: repeat(7, var(--hm-cell)); grid-auto-flow: column;
	grid-auto-columns: var(--hm-cell); gap: var(--hm-gap);
}
.heatmap-cell { width: var(--hm-cell); height: var(--hm-cell); border-radius: 3px; }
.heatmap-future { visibility: hidden; }
/* 5 buckets: empty + 4 intensities scaled off --color-accent (theme-correct in
   light AND dark via the runtime custom property). */
.heat-0 { background: color-mix(in srgb, var(--color-text) 10%, transparent); }
.heat-1 { background: color-mix(in srgb, var(--color-accent) 30%, var(--color-surface)); }
.heat-2 { background: color-mix(in srgb, var(--color-accent) 55%, var(--color-surface)); }
.heat-3 { background: color-mix(in srgb, var(--color-accent) 78%, var(--color-surface)); }
.heat-4 { background: var(--color-accent); }
.heatmap-footer { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-top: 0.6rem; flex-wrap: wrap; }
.heatmap-note { font-size: 0.72rem; }
.heatmap-legend { display: flex; align-items: center; gap: 0.25rem; font-size: 0.72rem; }
.heatmap-legend .heatmap-cell { display: inline-block; }

/* Tabs */
/* flex-wrap matters: with four tabs (Leaderboards being the long one) the strip
   no longer fits a 375px phone, and without it the row pushed the whole document
   wider than the viewport and the page scrolled sideways. Wrapping keeps every
   tab visible — a scrolling strip would hide the last one behind a gesture. */
.goal-tabs { display: flex; flex-wrap: wrap; gap: 0.3rem; border-bottom: 1px solid var(--color-border); margin: 1.1rem 0 1.4rem; }
.goal-tab {
	padding: 0.5rem 1rem; text-decoration: none; color: var(--color-text-muted);
	border-bottom: 3px solid transparent; margin-bottom: -1px; font-weight: 600;
}
@media (max-width: 30rem) { .goal-tab { padding: 0.5rem 0.7rem; } }
.goal-tab:hover { color: var(--color-primary); }
.goal-tab.is-active { color: var(--color-primary); border-bottom-color: var(--color-primary); }

/* Statistics tab: the stat strip and heatmap above, then a grid of panels. */
.stats-tab .stat-strip { margin-top: 0; }
.stats-panels { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }
@media (max-width: 46rem) { .stats-panels { grid-template-columns: 1fr; } }
.stats-panel {
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); padding: 1rem;
	display: flex; flex-direction: column;
}
.stats-panel-title { font-size: 1rem; margin: 0 0 0.85rem; }
.stats-panel-note { font-size: 0.71rem; line-height: 1.45; margin: 0.85rem 0 0; }
.stats-empty { font-size: 0.85rem; margin: 0; }

/* Figure pairs (manuscript totals, added vs removed) */
.stats-figures { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.9rem 1rem; margin: 0; }
.stats-figure { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.stats-figure dt { font-size: 0.76rem; color: var(--color-text-muted); }
.stats-figure dd {
	margin: 0; font-family: var(--font-serif); font-weight: 700; font-size: 1.4rem;
	line-height: 1.15; color: var(--color-primary); font-variant-numeric: tabular-nums;
}
.stats-figure dd.stats-pos { color: var(--color-accent); }
.stats-figure dd.stats-neg { color: #c2392f; }
html.dark .stats-figure dd.stats-neg { color: #f08a80; }

/* Ranked lists (most used words / phrases): a proportional bar behind each row
   so the shape of the distribution reads without comparing the numbers. */
.stats-rank { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.28rem; }
.stats-rank-row {
	position: relative; display: flex; align-items: baseline; gap: 0.6rem;
	padding: 0.32rem 0.55rem; border-radius: 6px; overflow: hidden; font-size: 0.9rem;
}
.stats-rank-bar {
	position: absolute; top: 0; bottom: 0; left: 0; border-radius: 6px;
	background: color-mix(in srgb, var(--color-accent) 18%, transparent);
}
.stats-rank-text {
	position: relative; flex: 1; min-width: 0;
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.stats-rank-count {
	position: relative; font-weight: 700; font-size: 0.8rem;
	color: var(--color-text-muted); font-variant-numeric: tabular-nums;
}

/* Goal cards */
.goals-list { display: flex; flex-direction: column; gap: 1rem; }
.goals-empty { padding: 1.5rem 0; }
.goal-card {
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); padding: 1rem 1.1rem;
}
.goal-card.is-archived { opacity: 0.8; }
.goal-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.goal-name { margin: 0; font-size: 1.15rem; }
.goal-type { margin: 0.15rem 0 0; font-size: 0.82rem; }
.goal-card-progress { text-align: right; white-space: nowrap; }
.goal-count { display: block; font-size: 1rem; }
.goal-pct { display: block; font-size: 0.85rem; color: var(--color-accent); font-weight: 700; }
.goal-card-body { margin: 0.8rem 0; position: relative; }

/* Story goal progress bar */
.goal-bar { position: relative; height: 1.1rem; background: color-mix(in srgb, var(--color-text) 8%, transparent); border-radius: 999px; overflow: hidden; }
.goal-bar-fill { display: block; height: 100%; background: var(--color-accent); border-radius: 999px; min-width: 2px; transition: width 0.3s; }

/* Date-range line graph */
.goal-graph { width: 100%; height: 140px; display: block; }
.goal-graph-empty { margin: 0.5rem 0; font-size: 0.85rem; }
.goal-graph-area { fill: color-mix(in srgb, var(--color-accent) 16%, transparent); stroke: none; }
.goal-graph-line { fill: none; stroke: var(--color-accent); stroke-width: 2; vector-effect: non-scaling-stroke; stroke-linejoin: round; }
.goal-graph-pace { fill: none; stroke: color-mix(in srgb, var(--color-text) 40%, transparent); stroke-width: 1.5; stroke-dasharray: 6 4; vector-effect: non-scaling-stroke; }
.goal-graph-today { stroke: var(--color-primary); stroke-width: 1.5; stroke-dasharray: 3 3; vector-effect: non-scaling-stroke; }

/* Per-point nodes on the date-range graph (added client-side; positioned in the
   graph's own box so they stay round despite the SVG's non-uniform stretch). */
.goal-graph-node {
	position: absolute; width: 6px; height: 6px; margin: -3px 0 0 -3px;
	border-radius: 50%; background: var(--color-accent); pointer-events: none;
	z-index: 2; transition: transform 0.1s ease;
}
.goal-graph-node.is-active { transform: scale(1.9); box-shadow: 0 0 0 2px var(--color-surface); }

/* Shared floating readout for heatmap cells + graph nodes (hover / click / tap). */
.goal-tip {
	position: fixed; z-index: 60; pointer-events: none;
	padding: 0.25rem 0.55rem; border-radius: var(--radius);
	background: var(--color-text); color: var(--color-bg);
	font-size: 0.78rem; font-weight: 600; white-space: nowrap;
	box-shadow: 0 2px 10px rgba(0, 0, 0, 0.28);
}
.goal-tip[hidden] { display: none; }
.heatmap-cell[data-tip] { cursor: pointer; }

.goal-card-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; }

/* Archived fold */
.goals-archived-fold { margin-top: 1.2rem; }
.goals-archived-fold > summary { cursor: pointer; font-weight: 600; padding: 0.4rem 0; color: var(--color-text-muted); }
.goals-archived-fold > summary:hover { color: var(--color-primary); }
.goals-archived-list { display: flex; flex-direction: column; gap: 1rem; margin-top: 0.6rem; }

/* Goal form */
.goal-form-wrap { max-width: 40rem; margin: 0 auto; }
.goal-form { display: flex; flex-direction: column; gap: 0.9rem; margin-top: 1rem; }
.goal-form label { display: flex; flex-direction: column; gap: 0.25rem; font-weight: 600; }
.goal-form input, .goal-form select { font: inherit; padding: 0.45rem 0.6rem; border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-surface); color: var(--color-text); }
/* Goal type: a visual two-card selector (hidden radios drive it). */
.goal-type-toggle { border: 0; padding: 0; margin: 0; min-width: 0; }
.goal-type-toggle > legend { font-weight: 600; padding: 0; margin-bottom: 0.35rem; }
.goal-type-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; }
.goal-type-card {
	position: relative; display: flex; flex-direction: column; gap: 0.2rem;
	padding: 0.8rem 0.9rem; border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); cursor: pointer; font-weight: 400;
}
.goal-type-card input { position: absolute; opacity: 0; width: 0; height: 0; }
.goal-type-card:hover { border-color: var(--color-primary); }
.goal-type-card:has(input:checked) { border-color: var(--color-primary); box-shadow: 0 0 0 2px var(--color-primary); }
.goal-type-card-title { font-weight: 700; }
.goal-type-card-desc { font-size: 0.85rem; color: var(--color-text-muted); }
@media (max-width: 30rem) { .goal-type-cards { grid-template-columns: 1fr; } }
.goal-fields { display: flex; flex-direction: column; gap: 0.9rem; }
.goal-fields[hidden] { display: none; }
.field-hint { display: block; font-size: 0.75rem; line-height: 1.45; margin-top: 0.35rem; font-weight: 400; }
/* Spelled out on a goal card only when it is NOT the default 'net' metric. */
.goal-metric {
	display: inline-block; padding: 0.05rem 0.45rem; border-radius: 999px; font-size: 0.72rem;
	font-weight: 700; color: var(--color-accent);
	background: color-mix(in srgb, var(--color-accent) 15%, transparent);
}
.goal-form-actions { display: flex; gap: 0.6rem; align-items: center; }

/* Sprint history table */
.sprint-totals { margin: 0 0 1rem; }
.sprint-table-wrap { overflow-x: auto; }
.sprint-table { width: 100%; border-collapse: collapse; }
.sprint-table th, .sprint-table td { text-align: left; padding: 0.5rem 0.7rem; border-bottom: 1px solid var(--color-border); white-space: nowrap; }
.sprint-table th { font-size: 0.8rem; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.03em; }
.sprint-table .num { text-align: right; }
.sprint-met { color: var(--color-accent); font-weight: 700; }
.sprint-unmet { color: #c0392b; font-weight: 700; }

/* ── Panel-head quick links (scene editor: Notes / Frontmatter) ── */
.panel-head-links { display: flex; gap: 0.4rem; margin-top: 0.5rem; flex-wrap: wrap; }
.panel-head-link {
	font-size: 0.8rem; padding: 0.15rem 0.6rem; border-radius: 999px;
	border: 1px solid var(--color-border); text-decoration: none; color: var(--color-text);
	background: var(--color-bg);
}
.panel-head-link:hover { border-color: var(--color-primary); color: var(--color-primary); }

/* Note-editor left panel: clickable group headings + empty hint */
a.nav-group-link { text-decoration: none; color: var(--color-text); display: block; }
a.nav-group-link:hover { color: var(--color-primary); }
.nav-empty { font-size: 0.85rem; padding: 0.2rem 0; list-style: none; }

/* Heatmap legend: the swatches live outside .heatmap-inner (no --hm-cell there)
   and inline spans ignore width/height — size them explicitly as inline-blocks. */
.heatmap-legend { display: inline-flex; align-items: center; gap: 3px; }
.heatmap-legend .heatmap-cell { display: inline-block; width: 13px; height: 13px; }
.heatmap-legend .muted { margin: 0 0.35rem; }

/* ── Site icon + nav icon links (owner-provided SVGs, currentColor) ── */
.site-title { display: inline-flex; align-items: center; gap: 0.55rem; }
.site-title > svg { height: 1.6rem; width: auto; flex: none; }
.nav-icon-link {
	display: inline-flex; align-items: center; justify-content: center;
	padding: 0.3rem; border-radius: var(--radius);
	color: var(--color-text); line-height: 0;
	background: none; border: 0; font: inherit; cursor: pointer;
}
.nav-icon-link svg { height: 1.35rem; width: auto; }
.nav-icon-link:hover { color: var(--color-primary); background: color-mix(in srgb, var(--color-primary) 10%, transparent); }

/* ── Content-rating badges (Library / M8) ──────────────────────────────────
   The five fixed ratings (src/ratings.js): Unstated/General/Teens/Mature/
   Explicit → letter badges U/G/T/M/E in grey/green/blue/orange/red. */
.rating-badge {
	display: inline-flex; align-items: center; justify-content: center;
	width: 1.5rem; height: 1.5rem; border-radius: 50%;
	font-size: 0.8rem; font-weight: 700; line-height: 1;
	color: #fff; flex: none; text-decoration: none;
}
.rating-badge--large { width: 2rem; height: 2rem; font-size: 1rem; }
.rating-U { background: #94a3b8; }
.rating-G { background: #059669; }
.rating-T { background: #2563eb; }
.rating-M { background: #ea580c; }
.rating-E { background: #dc2626; }

/* ── Publish panel (structure screen / M8) ─────────────────────────────────── */
.structure-publish { margin: 1.4rem 0; border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-surface, transparent); }
.structure-publish-summary { cursor: pointer; padding: 0.75rem 1rem; font-weight: 700; list-style: none; }
.structure-publish-summary::-webkit-details-marker { display: none; }
.structure-publish-summary::before { content: '▸ '; }
.structure-publish[open] .structure-publish-summary::before { content: '▾ '; }
.structure-publish-body { padding: 0 1rem 1rem; }
.publish-status { margin: 0.4rem 0; }
.publish-takedown { padding: 0.5rem 0.75rem; border-radius: var(--radius); margin: 0.5rem 0; }
.publish-form { display: flex; flex-direction: column; gap: 0.85rem; margin-top: 0.75rem; }
.publish-field { display: flex; flex-direction: column; gap: 0.3rem; font-weight: 600; }
.publish-field textarea, .publish-field input[type="text"], .publish-field select { font-weight: 400; }
.publish-field textarea { resize: vertical; }
.publish-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.85rem; }
.publish-check { display: flex; align-items: flex-start; gap: 0.5rem; }
.publish-mode-notes { margin: -0.4rem 0 0; font-size: 0.85rem; }
.publish-actions { margin-top: 0.3rem; }
.publish-unpublish { margin-top: 0.75rem; }
@media (max-width: 560px) { .publish-grid { grid-template-columns: 1fr; } }

/* Admin library moderation pills */
.pill { display: inline-block; padding: 0.1rem 0.5rem; border-radius: 999px; font-size: 0.75rem; background: color-mix(in srgb, var(--color-primary) 15%, transparent); }
.pill.danger { background: color-mix(in srgb, #dc2626 20%, transparent); color: #dc2626; }
.takedown-form { display: flex; flex-direction: column; gap: 0.4rem; padding: 0.5rem 0; }

/* ══════════════════════════════════════════════════════════════════════════════
   Shared Library — public browse / story page / gate / reader (M8 part 2)
   ══════════════════════════════════════════════════════════════════════════════ */

.library-public { max-width: var(--content-width, 60rem); margin: 0 auto; }
.library-public .library-head { display: flex; align-items: baseline; gap: 0.8rem; margin-bottom: 1rem; }
.library-public .library-head h1 { font-family: var(--font-serif); margin: 0; }
.library-public .library-head-actions { margin-left: auto; }
.library-public .library-head .back-link { margin-left: auto; }
.lib-empty { padding: 2rem 0; text-align: center; }
/* Section headings on the library Recent activity page. */
.activity-heading { font-family: var(--font-serif); font-size: 1.25rem; margin: 1.6rem 0 0.7rem; }
.activity-heading:first-of-type { margin-top: 0.6rem; }

/* ── Filter fold ── */
/* Filter body: hidden until the funnel checkbox in the same form is checked
   (CSS-only disclosure). Sits full-width below the search row. */
.filter-fold-body { display: none; margin-top: 0.9rem; padding-top: 0.9rem; border-top: 1px solid var(--color-border); }
.filter-cb:checked ~ .filter-fold-body { display: block; }
.filter-tags { display: flex; gap: 1.5rem; flex-wrap: wrap; margin-top: 0.9rem; }
.filter-tags .filter-field { flex: 1 1 16rem; }
.filter-field input[list], .filter-tags input { font: inherit; padding: 0.4rem 0.55rem; border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-surface); color: var(--color-text); }

/* ── Browse tiles: cover LEFT, then body ── */
.lib-grid { display: flex; flex-direction: column; gap: 1rem; }
.lib-tile {
	display: flex; gap: 1rem; padding: 0.9rem; align-items: flex-start;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); box-shadow: 0 1px 4px rgba(0,0,0,0.08);
}
.lib-tile-cover {
	position: relative; flex: 0 0 auto; width: 110px; aspect-ratio: 2 / 3;
	border-radius: calc(var(--radius) * 0.7); overflow: hidden; text-decoration: none;
	border: 1px solid var(--color-border); box-shadow: 0 1px 6px rgba(0,0,0,0.18);
}
.lib-tile-cover-fallback { position: absolute; inset: 0; background: var(--cover, var(--color-primary)); }
.lib-tile-canvas { position: absolute; inset: 0; z-index: 1; }
.lib-tile-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.35rem; }
.lib-tile-title { font-family: var(--font-serif); font-size: 1.2rem; margin: 0; line-height: 1.2; }
.lib-tile-title a { color: var(--color-text); text-decoration: none; }
.lib-tile-title a:hover { color: var(--color-primary); }
.lib-tile-authors { margin: 0; color: var(--color-text-muted); font-size: 0.9rem; }
.lib-tile-owner { margin: 0.15rem 0 0; font-size: 0.85rem; color: var(--color-text-muted); }
.lib-tile-owner .avatar { --avatar-size: 22px; }
.lib-tile-owner .owner-name { font-weight: 600; color: var(--color-text); }
.lib-tile-meta { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.lib-tile-blurb {
	margin: 0.15rem 0 0; color: var(--color-text); font-size: 0.92rem; line-height: 1.45;
	display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}

/* ── Tag pills + chips ── */
.lib-tags { display: flex; gap: 0.35rem; flex-wrap: wrap; }
.lib-tag {
	display: inline-block; padding: 0.1rem 0.55rem; border-radius: 999px; font-size: 0.75rem;
	background: color-mix(in srgb, var(--color-primary) 12%, transparent);
	border: 1px solid color-mix(in srgb, var(--color-primary) 30%, transparent); color: var(--color-text);
}
.lib-chip {
	display: inline-block; padding: 0.08rem 0.5rem; border-radius: var(--radius); font-size: 0.72rem;
	font-weight: 600; border: 1px solid var(--color-border); background: var(--color-bg); color: var(--color-text-muted);
}
.lib-chip-status.is-complete { border-color: #2e7d5b; color: #2e7d5b; }
.lib-chip-status.is-wip { border-color: #c98a00; color: #c98a00; }
.lib-chip-length { }
.lib-chip-genre { border-style: dashed; }

/* ── Story page ── */
.library-story .story-page-cover-wrap {
	position: relative; flex: 0 0 auto; width: 9rem; aspect-ratio: 2 / 3;
	border-radius: var(--radius); overflow: hidden; box-shadow: 0 2px 10px rgba(0,0,0,0.2); border: 1px solid var(--color-border);
}
.library-story .story-page-cover { position: absolute; inset: 0; background: var(--cover, var(--color-primary)); }
.library-story .story-page-canvas { position: absolute; inset: 0; z-index: 1; }
.story-page-authors { color: var(--color-text-muted); font-style: italic; margin: 0 0 0.7rem; }
.story-page-owner { margin: 0 0 0.8rem; font-size: 0.92rem; color: var(--color-text-muted); }
.story-page-owner .avatar { --avatar-size: 28px; }
.story-page-owner .owner-name { font-weight: 600; color: var(--color-text); }
.story-page-badges { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.6rem; }
.story-page-wc { margin: 0.5rem 0; font-size: 0.85rem; }
.story-page-actions { display: flex; gap: 0.7rem; align-items: center; flex-wrap: wrap; margin-top: 1rem; }
.story-page-blurb { margin-top: 1.5rem; line-height: 1.6; }

/* Download menu (native <details> dropdown) */
.lib-download { position: relative; display: inline-block; }
.lib-download > summary { list-style: none; cursor: pointer; }
.lib-download > summary::-webkit-details-marker { display: none; }
.lib-download-panel {
	position: absolute; z-index: 30; top: calc(100% + 4px); left: 0; display: flex; gap: 0.4rem;
	padding: 0.5rem; background: var(--color-surface); border: 1px solid var(--color-border);
	border-radius: var(--radius); box-shadow: 0 8px 22px rgba(0,0,0,0.25);
}

/* Part-3 seams collapse to nothing until part 3 fills them. */
.story-engagement:empty, .story-comments:empty { display: none; }

/* ── Staff takedown banner ── */
.takedown-banner {
	margin: 0 0 1.2rem; padding: 0.7rem 1rem; border-radius: var(--radius);
	background: color-mix(in srgb, #dc2626 12%, transparent); border: 1px solid #dc2626; color: var(--color-text);
}
.takedown-banner a { color: inherit; }

/* ── Disclaimer gate ── */
.disclaimer-gate { display: flex; justify-content: center; padding: 2rem 1rem; }
.disclaimer-card {
	max-width: 34rem; width: 100%; text-align: center; padding: 2rem 1.8rem;
	border: 1px solid #c98a00; border-radius: var(--radius);
	background: color-mix(in srgb, #c98a00 8%, var(--color-surface));
	box-shadow: 0 4px 18px rgba(0,0,0,0.15);
}
.disclaimer-card h1 { font-family: var(--font-serif); margin: 0 0 0.8rem; }
.disclaimer-for { color: var(--color-text-muted); margin: 0 0 1rem; }
.disclaimer-text {
	text-align: left; margin: 0 auto 1.5rem; padding: 1rem; max-width: 30rem; line-height: 1.55;
	background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius);
}
.disclaimer-actions { display: flex; gap: 0.8rem; justify-content: center; flex-wrap: wrap; align-items: center; }

/* Reader: author's snapshot note (reuses the M6 reading-view styles otherwise). */
.reading-owner-note {
	max-width: 40rem; margin: 0 auto 1.5rem; padding: 0.5rem 0.9rem; text-align: center; font-size: 0.85rem;
	border: 1px dashed var(--color-border); border-radius: var(--radius);
}

@media (max-width: 34rem) {
	.lib-tile { flex-direction: column; align-items: stretch; }
	.lib-tile-cover { width: 100%; max-width: 150px; align-self: flex-start; }
}

/* ════════════════════════════════════════════════════════════════════════════
   M8 part 3 — comments, engagement, notifications
   ════════════════════════════════════════════════════════════════════════════ */

/* Tile like count (browse + bookmarks). */
.lib-tile-likes { font-size: 0.8rem; white-space: nowrap; }
.library-head-bookmarks { margin-left: auto; }

/* ── Engagement row (story page) ── */
.story-engagement { margin-top: 2rem; padding-top: 1.2rem; border-top: 1px solid var(--color-border); }
.engagement-title, .comments-title { font-family: var(--font-serif); font-size: 1.15rem; margin: 0 0 0.8rem; }
.engagement-row { display: flex; gap: 0.6rem; align-items: center; flex-wrap: wrap; }
.engagement-owner { gap: 1rem; }
.engagement-stat { font-size: 1rem; }
.engagement-btn {
	display: inline-flex; align-items: center; gap: 0.4rem; cursor: pointer;
	padding: 0.4rem 0.8rem; border-radius: var(--radius);
	border: 1px solid var(--color-border); background: var(--color-surface); color: var(--color-text);
	font: inherit; line-height: 1;
}
.engagement-btn:hover { border-color: var(--color-primary); }
/* The active state swaps the solid primary fill for a 14% tint, but the text
   colour was still coming from the generic `button[type="submit"]` (0,1,1),
   which sets --color-primary-contrast: near-black on a dark tint in dark mode,
   white on a pale tint in light mode. Unreadable both ways, so set it here at
   (0,2,0) where it wins. */
.engagement-btn.is-on {
	border-color: var(--color-primary);
	background: color-mix(in srgb, var(--color-primary) 14%, transparent);
	color: var(--color-text);
}
.engagement-heart { color: #dc2626; }
.like-btn.is-on .engagement-heart { color: #dc2626; }
.engagement-count { font-variant-numeric: tabular-nums; }

/* ── Comments ── */
.story-comments { margin-top: 2rem; padding-top: 1.2rem; border-top: 1px solid var(--color-border); }
.comment-list { list-style: none; margin: 0 0 1.5rem; padding: 0; display: flex; flex-direction: column; gap: 1.1rem; }
.comment {
	padding: 0.9rem 1rem; border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface);
}
.comment.is-pending, .comment-reply.is-pending {
	border-style: dashed; background: color-mix(in srgb, #c98a00 7%, var(--color-surface));
}
.comment-head { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.35rem; }
.comment-user { font-weight: 600; }
.comment-date, .comment-edited { font-size: 0.8rem; }
.comment-pending-flag {
	font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em;
	color: #c98a00; border: 1px solid #c98a00; border-radius: 999px; padding: 0.05rem 0.5rem;
}
.comment-author-badge {
	font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em; font-weight: 600;
	color: #fff; background: var(--color-primary); border-radius: 999px; padding: 0.05rem 0.5rem;
}
.comment-body { line-height: 1.55; white-space: normal; overflow-wrap: anywhere; }
.comment-controls { display: flex; gap: 0.8rem; align-items: center; flex-wrap: wrap; margin-top: 0.5rem; }
.comment-controls .link-button { font-size: 0.82rem; }
/* "Reject" sits beside "Approve", so it stays a text control rather than an
   icon. It must undo the generic `button.danger` fill (0,1,1) as well as recolour
   the text — setting the colour alone left red text on a red block. */
.comment-controls .link-button.danger {
	color: #dc2626; background: none; border-color: transparent; padding: 0;
}
html.dark .comment-controls .link-button.danger { color: #f08a80; }

/* Nested replies (one level only). */
.comment-replies {
	list-style: none; margin: 0.9rem 0 0; padding: 0 0 0 1rem;
	border-left: 2px solid var(--color-border); display: flex; flex-direction: column; gap: 0.9rem;
}
.comment-reply.is-author { border-left-color: var(--color-primary); }

/* Inline edit + reply folds (native <details>). */
.comment-edit summary, .comment-reply-fold summary { cursor: pointer; list-style: none; }
.comment-edit summary::-webkit-details-marker, .comment-reply-fold summary::-webkit-details-marker { display: none; }
.comment-reply-fold { margin-top: 0.6rem; }
.comment-form { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 0.6rem; }
.comment-form textarea, .comment-edit-form textarea {
	width: 100%; resize: vertical; padding: 0.6rem; font: inherit; line-height: 1.5;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); color: var(--color-text);
}
.comment-form button, .comment-edit-form button { align-self: flex-start; }
.comment-edit-form { margin-top: 0.5rem; display: flex; flex-direction: column; gap: 0.4rem; }
.comment-mode-note, .comment-closed { margin: 0 0 0.6rem; font-size: 0.88rem; }
.comment-compose { margin-top: 1rem; }

/* ── PWA install banner (injected by pwa.js when installable) ── */
.pwa-install-banner {
	position: fixed; left: 50%; bottom: 1rem; transform: translateX(-50%); z-index: 900;
	width: min(38rem, calc(100vw - 2rem));
	display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
	padding: 0.8rem 1rem; border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); color: var(--color-text);
	box-shadow: 0 8px 30px rgba(0, 0, 0, 0.28);
}
.pwa-install-text { font-size: 0.9rem; flex: 1 1 12rem; }
.pwa-install-actions { display: inline-flex; align-items: center; gap: 0.75rem; flex: 0 0 auto; }
.pwa-install-hint { margin-top: 0.6rem; font-size: 0.82rem; }

/* ── Nav notifications bell + unread pill ── */
.nav-notif { position: relative; }
.nav-notif-pill {
	position: absolute; top: -0.3rem; right: -0.4rem; min-width: 1.05rem; height: 1.05rem;
	padding: 0 0.25rem; border-radius: 999px; background: #dc2626; color: #fff;
	font-size: 0.66rem; line-height: 1.05rem; text-align: center; font-weight: 700;
}

/* Small dot on the Forum icon when there's unread thread activity. */
.nav-forum { position: relative; }
.nav-unread-dot {
	position: absolute; top: 0.1rem; right: 0.15rem; width: 0.5rem; height: 0.5rem;
	border-radius: 999px; background: var(--color-primary);
	box-shadow: 0 0 0 2px var(--color-surface);
}
/* In the mobile drawer the icon links become full-width text rows; float the
   dot to the end of the row rather than over the icon. */
.site-nav .nav-forum .nav-unread-dot { position: static; margin-left: auto; align-self: center; }

/* ── Notifications inbox ── */
/* No max-width here: .site-main already caps and centres content at
   --content-width, so a second, tighter cap only constrained the inbox. */
.notif-list { list-style: none; margin: 1rem 0; padding: 0; display: flex; flex-direction: column; }
.notif-item { border-bottom: 1px solid var(--color-border); }
.notif-link {
	display: flex; gap: 1rem; align-items: baseline;
	padding: 0.8rem 0.4rem; text-decoration: none; color: var(--color-text);
}
/* Push only the date to the right, rather than justify-content: space-between —
   an unread row has a third flex child (the ::before dot), which space-between
   spread out, stranding the body text in the centre. margin-left:auto keeps the
   body left-aligned whether or not the dot is present. */
.notif-date { margin-left: auto; }
.notif-link:hover { background: color-mix(in srgb, var(--color-primary) 8%, transparent); }
.notif-item.is-unread .notif-body { font-weight: 700; }
.notif-item.is-unread .notif-link::before {
	content: ""; flex: 0 0 auto; width: 0.5rem; height: 0.5rem; margin-right: -0.5rem;
	border-radius: 50%; background: var(--color-primary); align-self: center;
}
.notif-date { font-size: 0.8rem; white-space: nowrap; }
.notif-pager { margin-top: 1rem; }

/* ── Admin comments moderation table ── */
.admin-subnav { display: flex; gap: 0.5rem; margin-bottom: 1rem; }
.admin-main tr.row-pending { background: color-mix(in srgb, #c98a00 10%, transparent); }
.admin-main td.comment-cell { max-width: 26rem; white-space: normal; overflow-wrap: anywhere; }

/* ── Structure-screen fixes (edit folds, genre checks, form extras) ── */
/* Required-field marker stays on the label line. */
/* .lbl and .req are defined globally near the top of this file. */

/* Genre multi-select grid (story form + publish panel). */
.genre-checks {
	display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
	gap: 0.25rem 0.9rem; padding: 0.5rem 0.7rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); max-width: 100%;
}

/* Chapter/scene edit folds open as a dropdown card below the row instead of
   inflating the flex row (which contorted the whole header line). */
.tree-actions .row-rename { position: static; }
/* Edit/Rename opens a CENTRED modal so it can never run off the bottom of the
   page (the old absolute popover did). The <details> body becomes a fixed
   full-screen scrim; the card sits centred within it. Closed → hidden by
   <details>. Close via the Cancel button, the backdrop, or Escape (see
   public/js/story-structure.js). */
.row-rename[open] > .row-edit-body {
	position: fixed; inset: 0; z-index: 300;
	display: flex; align-items: center; justify-content: center; padding: 1rem;
	background: rgba(0, 0, 0, 0.5);
}
.row-edit-card {
	width: min(30rem, 92vw); max-height: 85vh; overflow-y: auto;
	display: flex; flex-direction: column; gap: 0.9rem; padding: 1.1rem 1.2rem;
	background: var(--color-surface); border: 1px solid var(--color-border);
	border-radius: var(--radius); box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45);
}
.row-edit-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.row-edit-head strong { font-family: var(--font-serif); font-size: 1.05rem; }
.row-edit-form { display: flex; flex-direction: column; gap: 0.5rem; align-items: flex-start; }
.row-edit-form .row-edit-field { display: flex; flex-direction: column; gap: 0.25rem; width: 100%; font-size: 0.85rem; }
.row-edit-form input[type="text"], .row-edit-form textarea, .row-edit-form select {
	width: 100%; font: inherit; font-size: 0.9rem; padding: 0.4rem 0.55rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-bg); color: var(--color-text); resize: vertical;
}
.row-edit-move { border-top: 1px dashed var(--color-border); padding-top: 0.7rem; }

/* Add-forms: optional notes input shares the row, wraps on narrow screens. */
.tree-add-notes { flex: 1 1 12rem; min-width: 8rem; }

/* Cover image + delete story live OUTSIDE the main form (nested forms are
   invalid HTML and killed the Save button once). */
.story-form-extras {
	margin-top: 1.5rem; padding-top: 1.25rem; border-top: 1px solid var(--color-border);
	display: flex; flex-direction: column; gap: 1.25rem; max-width: 34rem;
}
.danger-zone { border: 1px solid color-mix(in srgb, #b3372f 45%, transparent); border-radius: var(--radius); padding: 0.9rem; }

/* Genre checks inherit the story-form's column-flex labels — restore rows. */
.genre-checks .filter-check {
	display: flex; flex-direction: row; align-items: center; gap: 0.45rem;
	font-size: 0.92rem; font-weight: 400; width: auto;
}

/* ── Settings: appearance / editor font / timezone (M9 part 1) ─────────────── */
/* Settings shares the centred form-card shell, but needs more width than the
   narrow auth cards so the theme grid and font list aren't cramped to one col. */
.form-card:has(.settings-section) { max-width: none; }
.settings-section { margin-bottom: 1rem; }
/* The form-card's column-flex sets align-items:flex-start, which would shrink
   the theme grid and font list to their content (one column). Let them fill. */
.settings-section > .theme-grid, .settings-section > .font-list { align-self: stretch; width: 100%; }
.settings-section > p.muted { margin: 0.2rem 0 0.8rem; }

/* Theme swatch picker — a responsive grid of radio cards. */
.theme-grid {
	display: grid; grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
	gap: 0.6rem; margin: 0 0 1rem;
}
.theme-card {
	display: flex; flex-direction: column; gap: 0.5rem; align-items: flex-start;
	padding: 0.7rem; border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); cursor: pointer; font-weight: 400;
}
.theme-card:hover { border-color: var(--color-primary); }
/* Selected state follows the ACTUAL checked radio (not a server-set class), so
   clicking a card highlights it immediately with no JS. */
.theme-card:has(input:checked) { border-color: var(--color-primary); box-shadow: 0 0 0 2px var(--color-primary); }
.theme-card input { position: absolute; opacity: 0; width: 0; height: 0; }
.theme-swatch { display: flex; gap: 0.3rem; }
.theme-dot {
	width: 1.15rem; height: 1.15rem; border-radius: 50%;
	border: 1px solid rgba(0, 0, 0, 0.15); display: inline-block;
}
.theme-card-label { font-size: 0.9rem; color: var(--color-text); }

/* Editor-font radio list — each option previewed in its own typeface. */
.font-list { display: flex; flex-direction: column; gap: 0.5rem; margin: 0 0 1rem; }
.font-option {
	display: flex; align-items: center; gap: 0.8rem; padding: 0.7rem 0.9rem;
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); cursor: pointer; font-weight: 400;
}
/* .font-option is a <label>; the form-card's `label { flex-direction: column }`
   rule (higher specificity) would stack + centre it, so restore the row here. */
.settings-section .font-option { flex-direction: row; align-items: center; gap: 0.8rem; width: 100%; }
.font-option:hover { border-color: var(--color-primary); }
.font-option:has(input:checked) { border-color: var(--color-primary); box-shadow: 0 0 0 2px var(--color-primary); }
.font-option input { position: absolute; opacity: 0; width: 0; height: 0; }
.font-option-body { display: flex; flex-direction: column; gap: 0.15rem; flex: 1; min-width: 0; }
.font-option-name { font-size: 1.05rem; font-weight: 700; color: var(--color-text); }
.font-option-preview { font-size: 0.95rem; color: var(--color-text); }
.font-option-cat { font-family: var(--font-body); font-size: 0.8rem; flex: none; }

/* Timezone controls. */
.tz-detect-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin: 0.5rem 0; }

/* Highlight "today" on the goals heatmap so the current cell is findable. */
.heatmap-cell.heatmap-today { outline: 2px solid var(--color-primary); outline-offset: -1px; }

/* ── Quotas: admin fields + user-facing usage (M9 part 2) ──────────────────── */
.settings-field { display: flex; flex-direction: column; gap: 0.3rem; align-items: flex-start; max-width: 22rem; }
.settings-field input, .settings-field select { padding: 0.4rem 0.5rem; }
.settings-field small { color: var(--color-text-muted); }

/* A subtle usage line under the library heading. */
.library-usage { margin: 0.15rem 0 0; font-size: 0.85rem; }

/* Read-only usage panel on /settings. */
.usage-section .usage-line { margin: 0 0 0.7rem; }
.usage-bars { display: flex; flex-direction: column; gap: 0.5rem; max-width: 26rem; }
/* .usage-section wins the specificity fight against .form-card label (which
   otherwise forces these into a column, hiding the bars and orphaning the text). */
.usage-section .usage-row { display: flex; flex-direction: row; align-items: center; gap: 0.6rem; width: 100%; font-size: 0.9rem; color: var(--color-text-muted); }
.usage-bar {
	flex: 1; height: 0.5rem; border-radius: 999px; overflow: hidden;
	background: var(--color-border);
}
.usage-bar > span { display: block; height: 100%; background: var(--color-primary); border-radius: inherit; }

/* ── Funnel toggle button (inline, end of the search row) ── */
/* Funnel toggle: a borderless icon button like the top-menu nav icons, with a
   slightly larger glyph. Sits at the end of the search row. */
.filter-toggle {
	align-self: flex-end; cursor: pointer; display: inline-flex; align-items: center; gap: 0.2rem;
	padding: 0.3rem; border: 0; border-radius: var(--radius);
	background: none; color: var(--color-text); user-select: none; line-height: 0;
}
.filter-toggle svg { height: 1.6rem; width: auto; }
.filter-toggle:hover { color: var(--color-primary); background: color-mix(in srgb, var(--color-primary) 10%, transparent); }
/* Lit up while the fold is open. */
.filter-cb:checked ~ .filter-row .filter-toggle {
	color: var(--color-primary); background: color-mix(in srgb, var(--color-primary) 12%, transparent);
}
.filter-fold-body > .filter-field { max-width: 20rem; margin-bottom: 0.6rem; }

/* ══ Forum (src/routes/forum.js) ══════════════════════════════════════════════ */
.forum h1 { font-family: var(--font-serif); }
/* Matches the library head (.library-public .library-head): baseline-aligned so
   the action buttons / back link sit level with the heading's baseline. */
.forum-head { display: flex; gap: 0.8rem; align-items: baseline; justify-content: space-between; flex-wrap: wrap; margin-bottom: 1.2rem; }
.forum-head h1 { margin: 0 0 0.2rem; }
.forum-head-actions { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }

/* Thin preview cards — shared by "My posts" and forum "Recent activity". */
.forum-mine-list { list-style: none; margin: 0 0 1rem; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.forum-mine-card { border: 1px solid var(--color-border); border-radius: var(--radius); padding: 0.7rem 0.9rem; background: var(--color-surface); }
.forum-mine-main { display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap; text-decoration: none; }
.forum-mine-title { font-weight: 700; color: var(--color-text); }
.forum-mine-main:hover .forum-mine-title { color: var(--color-primary); }
.forum-mine-forum { font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; padding: 0.05rem 0.4rem; border-radius: 999px; border: 1px solid var(--color-border); color: var(--color-text-muted); }
.forum-mine-excerpt { margin: 0.3rem 0 0; font-size: 0.9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.forum-mine-date { display: block; margin-top: 0.3rem; font-size: 0.8rem; }

/* Forum index cards */
.forum-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.9rem; grid-template-columns: 1fr; }
@media (min-width: 40rem) { .forum-list { grid-template-columns: 1fr 1fr; } }
.forum-card { border: 1px solid var(--color-border); border-radius: var(--radius); padding: 1rem 1.1rem; background: var(--color-surface); display: flex; flex-direction: column; gap: 0.4rem; }
.forum-card-graveyard { opacity: 0.85; }
.forum-card-link { text-decoration: none; color: var(--color-text); }
.forum-card-link h2 { font-family: var(--font-serif); margin: 0 0 0.2rem; font-size: 1.15rem; }
.forum-card:hover { border-color: var(--color-primary); }
.forum-card-meta { font-size: 0.82rem; }
/* Unread-count badge in a forum card heading. */
.forum-unread-badge {
	display: inline-block; vertical-align: middle; min-width: 1.2rem; padding: 0 0.35rem;
	border-radius: 999px; background: var(--color-primary); color: #fff;
	font-family: var(--font-sans); font-size: 0.72rem; font-weight: 700; line-height: 1.2rem; text-align: center;
}

/* Thread list */
.forum-thread-list { list-style: none; margin: 0 0 1rem; padding: 0; }
.forum-thread-row { padding: 0.7rem 0; border-bottom: 1px solid var(--color-border); display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem; }
.forum-thread-title { font-weight: 700; text-decoration: none; color: var(--color-text); }
.forum-thread-title:hover { color: var(--color-primary); }
.forum-thread-meta { font-size: 0.82rem; flex-basis: 100%; }
/* Unread indicators on a thread row. */
.forum-unread-dot { flex: 0 0 auto; align-self: center; width: 0.5rem; height: 0.5rem; border-radius: 999px; background: var(--color-primary); }
.forum-thread-row.is-unread .forum-thread-title { font-weight: 800; }
.forum-empty { padding: 1rem 0; }

/* In-forum search */
.forum-search { display: flex; gap: 0.5rem; margin: 0 0 1rem; flex-wrap: wrap; }
.forum-search input[type="search"] { flex: 1 1 12rem; min-width: 0; font: inherit; padding: 0.45rem 0.6rem; border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-bg); color: var(--color-text); }
.forum-search-note { font-size: 0.85rem; color: var(--color-text-muted); margin: 0 0 1rem; }
.forum-tag { display: inline-block; font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; padding: 0.05rem 0.4rem; border-radius: 999px; border: 1px solid var(--color-border); color: var(--color-text-muted); vertical-align: middle; }

/* ── Avatars (shared: forum, library, settings) ── */
.avatar {
	--avatar-size: 40px;
	width: var(--avatar-size); height: var(--avatar-size);
	flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
	border-radius: 50%; overflow: hidden; vertical-align: middle;
	background: var(--color-surface);
}
.avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.avatar-default { background: var(--avatar-bg, var(--color-primary)); color: #fff; }
/* The logo (currentColor) sits centred at ~58% of the disc. */
.avatar-default svg { width: 58%; height: 58%; display: block; }
/* Name-with-avatar row helper. */
.byline { display: inline-flex; align-items: center; gap: 0.45rem; }

/* Settings → Profile picture */
.avatar-settings-row { display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap; margin: 0.6rem 0; }
.avatar-preview { --avatar-size: 96px; box-shadow: 0 0 0 1px var(--color-border); }
.avatar-settings-controls { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.avatar-file-label { cursor: pointer; margin: 0; }
.avatar-color-form { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; margin-top: 0.4rem; }
.avatar-color-label { display: inline-flex; align-items: center; gap: 0.5rem; }

/* Posts */
.forum-thread-controls { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.forum-posts { display: flex; flex-direction: column; gap: 0.9rem; margin-bottom: 1rem; }
.forum-post { border: 1px solid var(--color-border); border-radius: var(--radius); padding: 0.9rem 1.1rem; background: var(--color-surface); }
.forum-post-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 0.8rem; flex-wrap: wrap; margin-bottom: 0.5rem; padding-bottom: 0.5rem; border-bottom: 1px solid var(--color-border); }
.forum-post-author { display: inline-flex; align-items: center; gap: 0.6rem; }
.forum-post-author-text { display: flex; flex-direction: column; gap: 0.2rem; line-height: 1.2; }
.forum-post-name { font-weight: 700; }
/* Always reserve the second line (min-height ≈ a pill) so posts without any
   badge keep the same two-line height and the avatar has consistent room. */
.forum-post-badges { display: inline-flex; align-items: center; gap: 0.35rem; flex-wrap: wrap; min-height: 1.1rem; }
/* Role pills: distinct hue per staff role (regular users get no pill). */
.role-pill.role-admin { color: #b3372f; border-color: currentColor; }
.role-pill.role-moderator { color: var(--color-primary); border-color: currentColor; }
.forum-post-date { font-size: 0.8rem; }
.forum-post-tools { display: inline-flex; align-items: center; gap: 0.4rem; }
.forum-post-body { max-width: none; }
.forum-post-deleted { font-size: 0.9rem; }

/* Footer row: page-size + pagination */
.forum-foot { display: flex; gap: 1rem; align-items: center; justify-content: space-between; flex-wrap: wrap; margin: 0.5rem 0 1.5rem; }
.forum-pagesize { font-size: 0.85rem; color: var(--color-text-muted); }
.forum-closed { padding: 0.9rem 1.1rem; border: 1px dashed var(--color-border); border-radius: var(--radius); }

/* Forms (new thread / reply / edit) */
.forum-form { display: flex; flex-direction: column; gap: 1rem; align-items: stretch; max-width: 48rem; }
.forum-field { display: flex; flex-direction: column; gap: 0.35rem; }
.forum-field-label { font-weight: 600; font-size: 0.9rem; }
.forum-form input[type="text"] { font: inherit; padding: 0.5rem 0.6rem; border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-bg); color: var(--color-text); }
.forum-form .button { align-self: flex-start; }
.forum-reply { margin-top: 1.5rem; }
.forum-reply h2 { font-family: var(--font-serif); font-size: 1.2rem; }
.forum-del { display: inline-block; }

/* ── Writing tools (/tools) ── */
.tools-page h1 { font-family: var(--font-serif); margin: 0 0 0.3rem; }
.tools-intro { margin: 0 0 1.4rem; }
.tools-columns { display: grid; grid-template-columns: 1fr; gap: 1.2rem; }
@media (min-width: 52rem) { .tools-columns { grid-template-columns: 1fr 1fr; align-items: start; } }
.tools-col { display: flex; flex-direction: column; gap: 1.2rem; min-width: 0; }
.tool-panel { border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-surface); padding: 1.1rem 1.2rem; }
.tool-panel h2 { font-family: var(--font-serif); margin: 0 0 0.8rem; font-size: 1.25rem; }
.tool-controls { display: flex; align-items: flex-end; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 1rem; }
.tool-field { display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.85rem; color: var(--color-text-muted); }
.tool-field select { font: inherit; padding: 0.4rem 0.5rem; border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-bg); color: var(--color-text); }
.tool-mode { display: inline-flex; gap: 0.3rem; }
.tool-mode .button.small { background: var(--color-surface); color: var(--color-text); border: 1px solid var(--color-border); }
.tool-mode .button.small.is-active { background: var(--color-primary); color: #fff; border-color: var(--color-primary); }

.tool-name-results { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); gap: 0.4rem; }
.tool-name-item { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; padding: 0.4rem 0.6rem; border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-bg); }
.tool-name-text { font-weight: 600; overflow-wrap: anywhere; }
.tool-star { background: none; border: none; cursor: pointer; font-size: 1.15rem; line-height: 1; color: var(--color-text-muted); padding: 0.1rem 0.25rem; }
.tool-star:hover, .tool-star.is-saved { color: var(--color-primary); }

.tool-dice-hint { margin: 0; }

/* 3D dice — both picture and prompt dice are CSS cubes. Size is driven by
   --die-size (translateZ is half of it), so the two sets share all the geometry
   and just set their own size + face content. Tumbled by tools.js on each roll. */
.tool-dice-pics, .tool-dice-prompts { display: grid; justify-content: center; padding: 0.8rem 0 0.5rem; --die-size: 96px; grid-template-columns: repeat(3, var(--die-size)); gap: 1.9rem 1.7rem; }
.die3d { position: relative; width: var(--die-size); height: var(--die-size); perspective: calc(var(--die-size) * 3.6); }
/* Paint each die in front of the one to its right: the right-facing result face
   matters, the left/back face doesn't. 6 dice per set, so descending z-index. */
.tool-dice-pics .die3d:nth-child(1), .tool-dice-prompts .die3d:nth-child(1) { z-index: 6; }
.tool-dice-pics .die3d:nth-child(2), .tool-dice-prompts .die3d:nth-child(2) { z-index: 5; }
.tool-dice-pics .die3d:nth-child(3), .tool-dice-prompts .die3d:nth-child(3) { z-index: 4; }
.tool-dice-pics .die3d:nth-child(4), .tool-dice-prompts .die3d:nth-child(4) { z-index: 3; }
.tool-dice-pics .die3d:nth-child(5), .tool-dice-prompts .die3d:nth-child(5) { z-index: 2; }
.tool-dice-pics .die3d:nth-child(6), .tool-dice-prompts .die3d:nth-child(6) { z-index: 1; }
.die3d-inner { position: relative; width: 100%; height: 100%; transform-style: preserve-3d; transform: rotateX(-16deg) rotateY(22deg); transition: transform 0.95s cubic-bezier(.2, .75, .25, 1); }
.die3d-face {
	position: absolute; width: var(--die-size); height: var(--die-size);
	display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.15rem;
	border-radius: 14%; background: linear-gradient(145deg, color-mix(in srgb, var(--color-surface) 88%, #fff 6%), var(--color-bg));
	border: 1px solid var(--color-border); box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.28); backface-visibility: hidden;
}
.die3d-front { transform: translateZ(calc(var(--die-size) / 2)); }
.die3d-back { transform: rotateY(180deg) translateZ(calc(var(--die-size) / 2)); }
.die3d-right { transform: rotateY(90deg) translateZ(calc(var(--die-size) / 2)); }
.die3d-left { transform: rotateY(-90deg) translateZ(calc(var(--die-size) / 2)); }
.die3d-top { transform: rotateX(90deg) translateZ(calc(var(--die-size) / 2)); }
.die3d-bottom { transform: rotateX(-90deg) translateZ(calc(var(--die-size) / 2)); }
/* Picture faces: one big emoji; help cursor hints the hover tooltip. */
.tool-dice-pics .die3d-face { font-size: calc(var(--die-size) * 0.44); cursor: help; }
.fav-emoji { cursor: help; }
/* Prompt faces: category label + phrase; gentler resting tilt so text reads. */
.tool-dice-prompts .die3d-inner { transform: rotateX(-11deg) rotateY(14deg); }
.tool-dice-prompts .die3d-face { padding: 0.3rem 0.32rem; text-align: center; gap: 0.1rem; }
.pdie-label { font-size: 0.5rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-muted); }
.pdie-text { font-size: 0.66rem; font-weight: 600; line-height: 1.15; overflow-wrap: anywhere; }
@media (max-width: 26rem) { .tool-dice-pics, .tool-dice-prompts { --die-size: 82px; } }
@media (prefers-reduced-motion: reduce) { .die3d-inner { transition: none; } }

.tool-favourites { margin-top: 1.2rem; }
.tool-fav-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.tool-fav { display: flex; align-items: center; gap: 0.6rem; padding: 0.4rem 0.45rem 0.4rem 0.8rem; border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-bg); }
.tool-fav-value { flex: 1 1 auto; min-width: 0; font-weight: 600; overflow-wrap: anywhere; }
.tool-fav-tag { flex: 0 0 auto; font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-text-muted); }
.tool-fav-del { flex: 0 0 auto; }
.tool-fav-empty { padding: 0.5rem 0; }
.tool-fav-prompt .tool-fav-value { font-weight: 500; font-style: italic; }

/* Story prompt */
.tool-prompt-hint { margin: 0; }
.tool-prompt-line { display: flex; align-items: flex-start; gap: 0.6rem; }
.tool-prompt-sentence { flex: 1 1 auto; margin: 0; font-size: 1.15rem; font-weight: 600; line-height: 1.4; }
.tool-prompt-line .tool-star { font-size: 1.3rem; }

/* Magic 8 ball */
.tool-eight-controls { align-items: center; }
.tool-eight-q { flex: 1 1 12rem; min-width: 0; font: inherit; padding: 0.45rem 0.6rem; border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-bg); color: var(--color-text); }
.eightball {
	--ball: 150px; width: var(--ball); height: var(--ball); margin: 1.1rem auto 0.5rem;
	border-radius: 50%; position: relative; display: flex; align-items: center; justify-content: center;
	background: radial-gradient(circle at 33% 28%, #6f6f6f 0%, #2b2b2b 42%, #060606 80%);
	box-shadow: inset -8px -10px 24px rgba(0, 0, 0, 0.7), inset 6px 6px 16px rgba(255, 255, 255, 0.1), 0 12px 26px rgba(0, 0, 0, 0.45);
}
.eightball::after { /* glossy highlight */
	content: ''; position: absolute; top: 11%; left: 19%; width: 36%; height: 26%; border-radius: 50%;
	background: radial-gradient(ellipse at center, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0) 70%);
	filter: blur(2px); pointer-events: none;
}
.eightball-window {
	width: 54%; height: 54%; border-radius: 50%; overflow: hidden; text-align: center;
	display: flex; align-items: center; justify-content: center;
	background: radial-gradient(circle at 50% 38%, #244aa8, #0a1c4a 75%);
	box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.6);
}
.eightball-answer { color: #eaf0ff; font-size: 0.62rem; font-weight: 600; line-height: 1.15; padding: 0.25rem; text-transform: uppercase; letter-spacing: 0.02em; }
.eightball.is-idle .eightball-answer { font-size: 1.8rem; letter-spacing: 0; }
.eightball.is-shaking { animation: eight-shake 0.55s ease; }
.eightball.is-revealing .eightball-answer { animation: eight-reveal 0.5s ease both; }
@keyframes eight-shake {
	0%, 100% { transform: translate(0, 0) rotate(0); }
	15% { transform: translate(-6px, -3px) rotate(-6deg); }
	30% { transform: translate(6px, 3px) rotate(5deg); }
	45% { transform: translate(-5px, 4px) rotate(-4deg); }
	60% { transform: translate(5px, -3px) rotate(4deg); }
	80% { transform: translate(-2px, 2px) rotate(-2deg); }
}
@keyframes eight-reveal {
	from { opacity: 0; transform: scale(0.55) rotate(-25deg); filter: blur(2px); }
	to { opacity: 1; transform: none; filter: none; }
}
@media (prefers-reduced-motion: reduce) {
	.eightball.is-shaking { animation: none; }
	.eightball.is-revealing .eightball-answer { animation: none; }
}

/* ── Member profiles (/users/<username>) ─────────────────────────────────────── */
.profile-page { max-width: var(--content-width); margin: 0 auto; }
.profile-head { display: flex; gap: 1.2rem; align-items: center; flex-wrap: wrap; }
.profile-avatar { flex: 0 0 auto; }
.profile-head-info { min-width: 0; }
.profile-name { margin: 0; overflow-wrap: anywhere; }
.profile-meta { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin: 0.35rem 0 0; font-size: 0.85rem; }
.profile-self-links { margin: 0.6rem 0 0; }
.profile-bio {
	margin: 1.2rem 0 0; padding: 0.9rem 1rem; border: 1px solid var(--color-border);
	border-radius: var(--radius); background: var(--color-surface);
}
.profile-bio p { margin: 0 0 0.6rem; overflow-wrap: anywhere; }
.profile-bio p:last-child { margin-bottom: 0; }
.profile-section-title {
	display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap;
	margin: 1.6rem 0 0.8rem; font-size: 1.1rem;
}
.profile-section-count { font-size: 0.78rem; font-weight: 400; }

/* Achievements: two full ladders, earned tiers lit and the rest dimmed. */
.profile-achievements { display: flex; flex-direction: column; gap: 0.6rem; }
.ach-row { display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap; }
.ach-row-label {
	flex: 0 0 3.4rem; font-size: 0.78rem; font-weight: 700;
	color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.04em;
}
.ach-badges { list-style: none; display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0; padding: 0; }
.ach-badge {
	display: inline-flex; align-items: center; gap: 0.25rem;
	padding: 0.22rem 0.6rem; border-radius: 999px; line-height: 1.4;
	font-size: 0.78rem; font-weight: 700; font-variant-numeric: tabular-nums;
	border: 1px solid var(--color-border); white-space: nowrap;
}
.ach-badge.is-earned {
	border-color: var(--color-accent); color: var(--color-accent);
	background: color-mix(in srgb, var(--color-accent) 15%, var(--color-surface));
}
/* Dimmed, not invisible: a locked tier is the next thing to aim at. */
.ach-badge.is-locked {
	color: var(--color-text-muted); background: transparent; opacity: 0.55;
	border-style: dashed;
}
.ach-badge-tick { font-size: 0.72rem; }
@media (max-width: 34rem) {
	.ach-row { align-items: flex-start; }
	.ach-row-label { flex-basis: 100%; }
}
.profile-empty { margin: 0; }

/* Author links (forum post headers, thread bylines): clickable, but they should
   read as a name, not as body-copy link chrome. */
.profile-link { color: inherit; text-decoration: none; }
.profile-link:hover, .profile-link:focus-visible { text-decoration: underline; }

/* Unpublished tiles pair up two-across — no blurb means they need half the
   room. Drop to one column at 52rem, comfortably BEFORE .lib-tile itself goes
   vertical at 48rem, so a stacked tile never has to live in a half-width
   column. */
.profile-tiles-half { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }
.lib-grid + .profile-tiles-half { margin-top: 1rem; }
@media (max-width: 52rem) { .profile-tiles-half { grid-template-columns: 1fr; } }

/* A shared story that isn't published: same tile, no link, flagged as such. */
.lib-tile-unpublished .lib-tile-cover { cursor: default; }
.lib-chip-unpublished {
	background: color-mix(in srgb, var(--color-text) 12%, transparent);
	color: var(--color-text-muted);
}

/* Story overview: the "Share on profile" toggle beside the status pill.
   Selectors are parent-qualified so they outrank the generic
   `button[type="submit"]` fill (0,1,1) — otherwise the pill inherits the solid
   primary background and a purple-on-purple hover swallows the label. */
.share-toggle-form { display: inline-flex; }
.share-toggle-form .share-pill {
	font: inherit; font-size: 0.78rem; font-weight: 700; cursor: pointer;
	padding: 0.2rem 0.7rem; border-radius: 999px; line-height: 1.5;
	border: 1px solid var(--color-border); background: var(--color-surface);
	color: var(--color-text-muted);
}
.share-toggle-form .share-pill:hover,
.share-toggle-form .share-pill:focus-visible {
	border-color: var(--color-primary); color: var(--color-primary);
	background: color-mix(in srgb, var(--color-primary) 14%, var(--color-surface));
}
.share-toggle-form .share-pill.is-on {
	border-color: var(--color-accent); color: var(--color-accent);
	background: color-mix(in srgb, var(--color-accent) 14%, var(--color-surface));
}
.share-toggle-form .share-pill.is-on:hover,
.share-toggle-form .share-pill.is-on:focus-visible {
	border-color: var(--color-accent); color: var(--color-accent);
	background: color-mix(in srgb, var(--color-accent) 26%, var(--color-surface));
}
.share-toggle-link { font-size: 0.78rem; }

/* Settings: the bio textarea */
.bio-label textarea { width: 100%; min-height: 6rem; resize: vertical; font: inherit; }

/* ── Challenges (/challenges) ─────────────────────────────────────────────────── */
.challenges-screen, .challenge-page { max-width: var(--content-width); margin: 0 auto; }
.ch-group { margin-top: 1.6rem; }
.ch-group-title { font-size: 1rem; margin: 0 0 0.7rem; color: var(--color-text-muted); }
.ch-list { display: flex; flex-direction: column; gap: 0.8rem; }
.ch-card {
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); padding: 0.9rem 1rem;
}
.ch-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.8rem; flex-wrap: wrap; }
.ch-card-title { margin: 0; font-size: 1.05rem; }
.ch-card-title a { text-decoration: none; }
.ch-card-title a:hover { text-decoration: underline; }
.ch-card-meta { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin: 0.4rem 0 0; font-size: 0.82rem; }

.ch-chip {
	display: inline-block; padding: 0.1rem 0.5rem; border-radius: 999px;
	font-size: 0.72rem; font-weight: 700; white-space: nowrap;
	border: 1px solid var(--color-border); color: var(--color-text-muted);
}
.ch-chip-kind { border-color: var(--color-primary); color: var(--color-primary); }
.ch-chip-joined { border-color: var(--color-accent); color: var(--color-accent); }
.ch-chip-rejected { border-color: #c2392f; color: #c2392f; }
html.dark .ch-chip-rejected { border-color: #f08a80; color: #f08a80; }

/* Phase pills: upcoming / open / closed */
.ch-phase { display: inline-block; padding: 0.12rem 0.55rem; border-radius: 999px; font-size: 0.72rem; font-weight: 700; }
.ch-phase-open { background: color-mix(in srgb, var(--color-accent) 18%, transparent); color: var(--color-accent); }
.ch-phase-upcoming { background: color-mix(in srgb, var(--color-primary) 18%, transparent); color: var(--color-primary); }
.ch-phase-closed { background: color-mix(in srgb, var(--color-text) 12%, transparent); color: var(--color-text-muted); }

.ch-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.ch-head h1 { margin: 0; }
.ch-description, .ch-prompt .rich-text {
	margin-top: 1rem; padding: 0.9rem 1rem; border: 1px solid var(--color-border);
	border-radius: var(--radius); background: var(--color-surface);
}
.ch-staff-bar { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 1rem; }
.ch-section { margin-top: 1.8rem; }
.ch-section h2 { font-size: 1.05rem; margin: 0 0 0.6rem; }
.ch-board-note, .ch-hidden-note { font-size: 0.8rem; margin: 0 0 0.7rem; }
.ch-count-inline { font-size: 0.8rem; font-weight: 400; }

/* Leaderboard */
.ch-board { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.35rem; }
.ch-board-row {
	display: grid; grid-template-columns: 1.8rem minmax(6rem, 12rem) 1fr auto;
	align-items: center; gap: 0.7rem; padding: 0.35rem 0.6rem;
	border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-surface);
}
.ch-board-rank { font-weight: 700; color: var(--color-text-muted); font-variant-numeric: tabular-nums; }
.ch-board-bar { height: 0.5rem; border-radius: 999px; background: color-mix(in srgb, var(--color-text) 10%, transparent); overflow: hidden; }
.ch-board-bar > span { display: block; height: 100%; background: var(--color-accent); border-radius: 999px; }
.ch-board-words { font-weight: 700; font-variant-numeric: tabular-nums; font-size: 0.85rem; white-space: nowrap; }
@media (max-width: 40rem) {
	.ch-board-row { grid-template-columns: 1.6rem 1fr auto; }
	.ch-board-bar { display: none; }
}

/* Submissions */
.ch-own { border: 1px solid var(--color-border); border-radius: var(--radius); background: var(--color-surface); padding: 1rem; }
.ch-own h3 { margin: 0 0 0.6rem; font-size: 1rem; }
.ch-form-actions { display: flex; gap: 0.6rem; align-items: center; flex-wrap: wrap; }
.ch-sub {
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); padding: 1rem; margin-bottom: 0.9rem;
}
.ch-sub.is-rejected { border-style: dashed; opacity: 0.85; }
.ch-sub-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.8rem; }
.ch-sub-title { margin: 0; font-size: 1.05rem; }
.ch-sub-author { margin: 0.2rem 0 0; font-size: 0.82rem; display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.ch-sub-reason { margin: 0.6rem 0; font-size: 0.85rem; }
.ch-sub-body { margin-top: 0.7rem; }
.ch-mod-item { margin-bottom: 1.4rem; }
.ch-mod-actions { display: flex; gap: 0.6rem; flex-wrap: wrap; margin-top: -0.3rem; }
.ch-reject-form { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }
.ch-reject-form input { min-width: 16rem; flex: 1 1 16rem; }
.ch-kind-fixed { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.goal-challenge { font-weight: 700; }

/* Profile → challenges taken part in (reuses the .ch-chip / .ch-phase pills). */
.pch-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.pch-row {
	display: flex; align-items: baseline; justify-content: space-between; gap: 0.8rem; flex-wrap: wrap;
	padding: 0.55rem 0.8rem; border: 1px solid var(--color-border);
	border-radius: var(--radius); background: var(--color-surface);
}
.pch-name { font-weight: 700; text-decoration: none; }
.pch-name:hover { text-decoration: underline; }
.pch-meta { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; font-size: 0.78rem; }

/* ── Flag for review ──────────────────────────────────────────────────────────
   Deliberately quiet: an outline flag that only gains colour on hover or once
   you have actually flagged something. */
/* Parent-qualified so it outranks the generic `button[type="submit"]` fill
   (0,1,1) — a bare `.flag-btn` loses and the icon becomes a solid purple block. */
.flag-form { display: inline-flex; }
.flag-form .flag-btn {
	display: inline-flex; align-items: center; justify-content: center;
	width: 1.6rem; height: 1.6rem; padding: 0.25rem; cursor: pointer;
	background: none; border: 1px solid transparent; border-radius: 6px;
	color: var(--color-text-muted); opacity: 0.5; line-height: 1;
}
.flag-form .flag-btn svg { width: 100%; height: 100%; display: block; }
.flag-form .flag-btn:hover, .flag-form .flag-btn:focus-visible {
	opacity: 1; color: var(--color-primary);
	background: none; border-color: var(--color-border);
}
.flag-form .flag-btn.is-flagged { opacity: 1; color: #c2392f; background: none; }
html.dark .flag-form .flag-btn.is-flagged { color: #f08a80; }
.comment-controls .flag-form { margin-left: auto; }

/* Admin → Flagged queue */
.flagq-item {
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); padding: 1rem; margin-bottom: 1rem;
}
.flagq-head { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.flagq-type { font-weight: 700; font-size: 0.85rem; }
.flagq-count {
	padding: 0.1rem 0.5rem; border-radius: 999px; font-size: 0.72rem; font-weight: 700;
	background: color-mix(in srgb, #c2392f 18%, transparent); color: #c2392f;
}
html.dark .flagq-count { color: #f08a80; }
.flagq-meta, .flagq-by { margin: 0.35rem 0 0; font-size: 0.82rem; }
.flagq-body {
	margin: 0.7rem 0; padding: 0.6rem 0.9rem; white-space: pre-wrap; overflow-wrap: anywhere;
	border-left: 3px solid var(--color-border); background: color-mix(in srgb, var(--color-text) 4%, transparent);
}
.flagq-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: flex-start; margin-top: 0.6rem; }
.flagq-actions textarea { width: 100%; font: inherit; }

/* ── Notification settings table ─────────────────────────────────────────────
   `cards` handles the small-screen collapse; these rules only size the
   checkbox columns and keep the per-type description readable. */
.notif-table-wrap { overflow-x: auto; }
.notif-table { width: 100%; border-collapse: collapse; }
.notif-table th, .notif-table td {
	text-align: left; padding: 0.55rem 0.7rem; border-bottom: 1px solid var(--color-border);
	vertical-align: top;
}
.notif-table th { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--color-text-muted); }
.notif-table th.notif-check, .notif-table td.notif-check { text-align: center; width: 6rem; }
.notif-desc { display: block; font-size: 0.78rem; font-weight: 400; margin-top: 0.15rem; line-height: 1.4; }
.notif-box { display: inline-flex; align-items: center; justify-content: center; cursor: pointer; margin: 0; }
.notif-box input { width: 1.1rem; height: 1.1rem; cursor: pointer; }
.notif-freq { display: block; margin: 1.1rem 0 0.9rem; max-width: 34rem; }
.notif-freq select { display: block; margin-top: 0.3rem; }
@media (max-width: 48rem) {
	/* Card mode: the label + description head the card, each switch is its own
	   labelled row. Centring would fight the cards layout's right-aligned value. */
	.notif-table td.notif-check { text-align: right; width: auto; }
	/* cards makes every td a flex ROW, which would stand the description beside
	   the title and squeeze it to two or three words per line. Stack them. */
	.notif-table td.cell-main { flex-direction: column; align-items: flex-start; gap: 0.1rem; }
	.notif-table td.cell-main .notif-desc { font-weight: 400; }
}

/* ── Push devices ────────────────────────────────────────────────────────────
   The per-device half of push notifications, under the preference table. */
.push-devices { margin-top: 1.4rem; padding-top: 1.1rem; border-top: 1px solid var(--color-border); }
.push-devices h3 { margin: 0 0 0.35rem; font-size: 1rem; }
.push-devices .push-status { margin: 0.6rem 0; }
.push-devices [data-push-toggle] { margin-bottom: 0.9rem; }
.push-device-list { list-style: none; margin: 0.6rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.push-device {
	display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap;
	padding: 0.5rem 0.7rem; border: 1px solid var(--color-border); border-radius: var(--radius);
}
.push-device-name { font-weight: 600; }
.push-device-date { font-size: 0.82rem; }
.push-device-remove { margin: 0 0 0 auto; }

/* ── Reminders ───────────────────────────────────────────────────────────────
   Each reminder is its own form, laid out as a wrapping row so it collapses to
   a stack on a phone without a separate small-screen layout.

   EVERY RULE HERE IS QUALIFIED WITH .settings-section, and that is load-bearing.
   The settings page renders inside formPage's `.form-card`, which carries
   `.form-card form { display:flex; flex-direction:column; align-items:flex-start }`
   and `.form-card label { flex-direction:column; width:100% }`. Both are (0,1,1)
   and beat a bare class, so an unqualified `.reminder-form` was silently ignored
   and every control stacked full-width at all widths. Same family of trap as the
   `button[type="submit"]` one further up — a generic descendant rule outranking a
   single class. */
.settings-section .reminder-list { list-style: none; margin: 0.8rem 0 1.1rem; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.settings-section .reminder-row {
	display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
	padding: 0.6rem 0.7rem; border: 1px solid var(--color-border); border-radius: var(--radius);
}
.settings-section .reminder-form {
	display: flex; flex-direction: row; align-items: center; gap: 0.5rem;
	flex-wrap: wrap; flex: 1 1 auto; margin: 0; width: auto;
}
.settings-section .reminder-add { margin-top: 0.4rem; }
.settings-section .rem-field { display: block; width: auto; margin: 0; }
.settings-section .rem-field select, .settings-section .rem-field input { display: block; margin: 0; }
/* `hidden` on a label must win over the display above. */
.settings-section .rem-day[hidden] { display: none; }
/* The message is the one field that should soak up the spare width. Kept as a
   basis rather than a fixed width so it wraps onto its own full line when the
   row runs out of room — which is the whole small-screen story, no media query
   and so no chance of this basis ever being read as a HEIGHT. */
.settings-section .rem-body-field { flex: 1 1 14rem; min-width: 10rem; }
.settings-section .rem-body-field input { width: 100%; }
.settings-section .rem-delete { margin: 0; }
.settings-section .rem-last { flex: 1 0 100%; margin: 0.1rem 0 0; font-size: 0.8rem; }

/* ── Shared leaderboards ─────────────────────────────────────────────────────
   The Leaderboards tab on /goals. The chart reuses .goal-graph's box and pace
   line; only the per-writer lines are new, and they carry their colour inline
   because it is data, not styling. */
/* Full-bleed: this reads as page copy, not a form hint, so it runs the width of
   the container like the headings above it. */
.lb-intro { max-width: none; }
/* Two plain buttons. Creating opens its own page and joining opens a modal, so
   nothing here needs to hold a form open on the page. */
.lb-head-actions { display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; margin-bottom: 1.4rem; }
.lb-head-actions form { margin: 0; }
.lb-join-fallback { display: flex; gap: 0.5rem; align-items: flex-end; flex-wrap: wrap; margin: 0; }
.lb-edit-fold summary { cursor: pointer; font-weight: 600; }
/* The create page. Same wrapping-row form as the inline editor, given a heading
   and its own actions row. */
.lb-form-page { max-width: 52rem; }
.lb-form-actions { display: flex; gap: 0.6rem; align-items: center; flex: 1 0 100%; margin-top: 0.4rem; }
/* A wrapping ROW, not a column: the fields are short and there is a container's
   worth of width to use. */
.lb-edit-form { display: flex; flex-direction: row; flex-wrap: wrap; gap: 0.7rem 1rem; align-items: flex-end; margin-top: 0.7rem; }
.lb-field { display: flex; flex-direction: column; gap: 0.25rem; }
/* Deliberate rows rather than free wrapping, which left the fields ragged: the
   name takes a line of its own, then target/dates/colour share the next one
   evenly. Qualified so it outranks the shared .lb-field rule below it. */
.lb-edit-form .lb-field { flex: 1 1 11rem; }
.lb-edit-form .lb-field-wide { flex: 1 1 100%; }
.lb-field input, .lb-field select { width: 100%; box-sizing: border-box; }
/* Hints and locked-field notes are sentences: give them their own full line
   rather than letting them sit as a squeezed column between two inputs. */
.lb-edit-form .field-hint, .lb-locked { flex: 1 0 100%; margin: 0; font-size: 0.85rem; }

.lb-list { display: flex; flex-direction: column; gap: 1.2rem; }
.lb-card {
	border: 1px solid var(--color-border); border-radius: var(--radius);
	background: var(--color-surface); padding: 1rem;
}
.lb-head { display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap; }
.lb-name { margin: 0; font-size: 1.15rem; }
.lb-meta, .lb-owner { margin: 0.3rem 0 0; font-size: 0.85rem; }

.lb-phase { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; border-radius: 999px; padding: 0.1rem 0.5rem; border: 1px solid var(--color-border); }
.lb-phase.is-upcoming { color: var(--color-text-muted); }
.lb-phase.is-open { background: var(--color-primary); color: var(--color-primary-contrast); border-color: var(--color-primary); }
.lb-phase.is-closed { color: var(--color-text-muted); opacity: 0.85; }

.lb-code { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin: 0.7rem 0; }
.lb-code-label { font-size: 0.8rem; }
.lb-code-value { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 1rem; letter-spacing: 0.08em; padding: 0.15rem 0.5rem; border: 1px solid var(--color-border); border-radius: var(--radius); }
.lb-code-form { margin: 0; }

/* The chart. stroke-width is set here so a colour change never has to think
   about line weight, and fill:none matters because <polyline> fills by default. */
.lb-graph { margin: 0.8rem 0; }
.lb-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }

.lb-table { width: 100%; border-collapse: collapse; margin-top: 0.5rem; }
.lb-table th, .lb-table td { text-align: left; padding: 0.4rem 0.6rem; border-bottom: 1px solid var(--color-border); }
.lb-table th { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--color-text-muted); }
.lb-table tr.is-me { background: color-mix(in srgb, var(--color-primary) 12%, transparent); }
.lb-rank { width: 2.5rem; color: var(--color-text-muted); }
.lb-swatch { display: inline-block; width: 0.8rem; height: 0.8rem; border-radius: 3px; margin-right: 0.45rem; vertical-align: -1px; }

.lb-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; margin-top: 0.9rem; }
.lb-actions form { margin: 0; }
.lb-colour-form { display: flex; gap: 0.4rem; align-items: center; }
.lb-colour-label { margin: 0; }

.lb-archived-list { display: flex; flex-direction: column; gap: 0.4rem; margin-top: 0.6rem; }
.lb-archived-row { display: flex; gap: 0.6rem; align-items: center; flex-wrap: wrap; padding: 0.4rem 0.6rem; border: 1px solid var(--color-border); border-radius: var(--radius); }
.lb-archived-row .cell-main { font-weight: 600; }
.lb-archived-row form { margin: 0 0 0 auto; }
.lb-archived-row form + form { margin-left: 0.4rem; }

.lb-admin-form { display: flex; gap: 0.4rem; align-items: center; margin: 0; flex-wrap: wrap; }

@media (max-width: 40rem) {
	.lb-head-forms { flex-direction: column; align-items: stretch; }
	.lb-actions { align-items: stretch; }
}
