/*
Theme Name:  FICTBASE Author
Theme URI:   https://fictbase.com/themes/author
Author:      FICTBASE
Author URI:  https://fictbase.com
Description: The reusable theme behind every FICTBASE managed author site. One codebase, per-site colour schemes set from the FICTBASE admin panel, and a reader-facing light/dark switch with exactly two options.
Version:     1.0.0
Requires at least: 6.5
Tested up to: 6.9
Requires PHP: 8.0
License:     GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: fictbase-author
Tags:        blog, one-column, block-patterns, full-site-editing, custom-colors, dark-mode
*/

/* ==========================================================================
   1. Fonts — self-hosted, latin subset, variable
   ========================================================================== */

@font-face {
	font-family: "Literata";
	src: url("assets/fonts/Literata.woff2") format("woff2-variations");
	font-weight: 300 600;
	font-stretch: normal;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Fraunces";
	src: url("assets/fonts/Fraunces.woff2") format("woff2-variations");
	font-weight: 400 700;
	font-stretch: normal;
	font-style: normal;
	font-display: swap;
}

/* ==========================================================================
   2. Tokens
   --------------------------------------------------------------------------
   Two independent axes:
     [data-scheme] — the site's colour scheme. We set it, once, per site.
     [data-theme]  — light or dark. The reader sets it. Exactly two options.
   Nothing below this block may use a literal colour. A hex in a component
   rule is a bug: it will be right in one mode and wrong in the other.
   ========================================================================== */

:root {
	/* Type */
	--fb-font-display: "Fraunces", ui-serif, Georgia, "Times New Roman", serif;
	--fb-font-body: "Literata", ui-serif, Georgia, Cambria, serif;
	--fb-font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

	--fb-text-base: 1.0625rem;
	/* A fixed length, not ch: ch resolves against each element own font, so a
	   heading in the display face would compute a far wider measure than the
	   body text and break out of the column. 42rem is 68ch of the body face. */
	--fb-measure: 42rem;

	/* Rhythm — everything is a multiple of 8px */
	--fb-gutter: clamp(1.25rem, 5vw, 2.5rem);
	--fb-section-y: clamp(4rem, 9vw, 7.5rem);
	--fb-radius: 12px;
	--fb-radius-sm: 8px;

	/* Motion */
	--fb-ease: cubic-bezier(0.25, 0.46, 0.45, 0.94);
	--fb-dur: 0.5s;

	/* --- Neutral ramps, declared once, applied by the mode blocks --------- */
	--_l-bg: #FCFCFA;
	--_l-text: #1B1B18;
	--_l-muted: #6A6A62;
	--_l-shadow: rgba(24, 24, 20, 0.08);

	--_d-bg: #101012;
	--_d-text: #E9E9E4;
	--_d-muted: #9A9A92;
	--_d-shadow: rgba(0, 0, 0, 0.5);

	/* --- Light mode is the default state --------------------------------- */
	--fb-bg: var(--_l-bg);
	--fb-text: var(--_l-text);
	--fb-text-muted: var(--_l-muted);
	--fb-accent: var(--_accent-l);
	--fb-accent-ink: var(--_ink-l);
	--fb-shadow: var(--_l-shadow);
	color-scheme: light;
}

/* Surfaces and borders are derived, so every scheme gets neutrals subtly
   tinted toward its own accent rather than a flat unconsidered grey.

   Two things to note about this block:

   1. The doubled `:root:root` raises specificity above the [data-theme] and
      media blocks below, so it is applied last regardless of source order.
      The formulas still resolve against whichever --fb-bg and --fb-accent the
      mode in force has set, because custom properties substitute at
      computed-value time.
   2. Each token is declared twice. The first value is a translucent grey,
      which reads correctly over a light OR a dark ground and needs nothing
      newer than rgba(). The second uses color-mix() and, in any browser that
      does not support it, is dropped at parse time leaving the fallback
      standing. */
:root:root {
	--fb-surface: rgba(128, 128, 128, 0.07);
	--fb-surface: color-mix(in oklab, var(--fb-bg) 95%, var(--fb-accent));

	--fb-surface-2: rgba(128, 128, 128, 0.13);
	--fb-surface-2: color-mix(in oklab, var(--fb-bg) 89%, var(--fb-accent));

	--fb-border: rgba(128, 128, 128, 0.3);
	--fb-border: color-mix(in oklab, var(--fb-bg) 84%, var(--fb-text));

	--fb-accent-soft: rgba(128, 128, 128, 0.1);
	--fb-accent-soft: color-mix(in oklab, var(--fb-bg) 88%, var(--fb-accent));

	--fb-focus: var(--fb-accent);
}

/* Dark, when the OS asks for it and the reader has not overridden it. */
@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) {
		--fb-bg: var(--_d-bg);
		--fb-text: var(--_d-text);
		--fb-text-muted: var(--_d-muted);
		--fb-accent: var(--_accent-d);
		--fb-accent-ink: var(--_ink-d);
		--fb-shadow: var(--_d-shadow);
		color-scheme: dark;
	}
}

/* Dark, chosen explicitly. Must also win over a light OS. */
:root[data-theme="dark"] {
	--fb-bg: var(--_d-bg);
	--fb-text: var(--_d-text);
	--fb-text-muted: var(--_d-muted);
	--fb-accent: var(--_accent-d);
	--fb-accent-ink: var(--_ink-d);
	--fb-shadow: var(--_d-shadow);
	color-scheme: dark;
}

/* ==========================================================================
   3. Schemes
   --------------------------------------------------------------------------
   Each declares an accent for light and one for dark. They are not the same
   colour: an accent that reads well on paper-white is muddy on near-black,
   and one that glows on near-black is illegible on white.
   --ink-* is the text placed ON the accent, chosen by luminance so a button
   label never disappears into its own background.
   ========================================================================== */

:root,
:root[data-scheme="ink"] {
	--_accent-l: #2E3440;
	--_accent-d: #C3CBDA;
	--_ink-l: #FFFFFF;
	--_ink-d: #191C22;
}

:root[data-scheme="oxblood"] {
	--_accent-l: #8C2F39;
	--_accent-d: #E5707C;
	--_ink-l: #FFFFFF;
	--_ink-d: #2A0F13;
}

:root[data-scheme="sage"] {
	--_accent-l: #40614A;
	--_accent-d: #8FBF9A;
	--_ink-l: #FFFFFF;
	--_ink-d: #10200F;
}

:root[data-scheme="cobalt"] {
	--_accent-l: #24509E;
	--_accent-d: #7FA9F0;
	--_ink-l: #FFFFFF;
	--_ink-d: #0B1830;
}

:root[data-scheme="amber"] {
	--_accent-l: #9A5410;
	--_accent-d: #F0A552;
	--_ink-l: #FFFFFF;
	--_ink-d: #241505;
}

:root[data-scheme="plum"] {
	--_accent-l: #653C97;
	--_accent-d: #B490E8;
	--_ink-l: #FFFFFF;
	--_ink-d: #1D1030;
}

/* ==========================================================================
   4. Base
   ========================================================================== */

*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
	margin: 0;
	background: var(--fb-bg);
	color: var(--fb-text);
	font-family: var(--fb-font-body);
	font-size: var(--fb-text-base);
	line-height: 1.65;
	font-optical-sizing: auto;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

img,
svg,
video { max-width: 100%; height: auto; }

a { color: var(--fb-accent); text-underline-offset: 0.18em; text-decoration-thickness: 1px; }
a:hover { text-decoration-thickness: 2px; }

:focus-visible {
	outline: 2px solid var(--fb-focus);
	outline-offset: 3px;
	border-radius: 2px;
}

::selection { background: var(--fb-accent); color: var(--fb-accent-ink); }

.fb-skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 100;
	padding: 12px 20px;
	background: var(--fb-accent);
	color: var(--fb-accent-ink);
	border-radius: 0 0 var(--fb-radius-sm) 0;
	font-family: var(--fb-font-display);
	text-decoration: none;
}
.fb-skip-link:focus { left: 0; }

.screen-reader-text {
	position: absolute !important;
	width: 1px; height: 1px;
	overflow: hidden; clip-path: inset(50%);
	white-space: nowrap;
}

/* ==========================================================================
   5. Typography
   --------------------------------------------------------------------------
   Headings tight and heavy, body open and light. Never mixed.
   ========================================================================== */

h1, h2, h3, h4, h5, h6 {
	font-family: var(--fb-font-display);
	font-weight: 620;
	line-height: 1.14;
	letter-spacing: -0.022em;
	text-wrap: balance;
	margin: 0 0 0.5em;
	font-variation-settings: "SOFT" 0, "WONK" 0;
}

h1 { font-size: clamp(2.25rem, 5vw, 3.75rem); letter-spacing: -0.032em; }
h2 { font-size: clamp(1.625rem, 3vw, 2.375rem); letter-spacing: -0.026em; }
h3 { font-size: clamp(1.1875rem, 2vw, 1.4375rem); }
h4 { font-size: 1.125rem; }

p, ul, ol, blockquote { margin: 0 0 1.4em; }
p:last-child { margin-bottom: 0; }

.fb-lede,
.is-style-fb-lede {
	font-size: clamp(1.125rem, 2vw, 1.3125rem);
	line-height: 1.55;
	color: var(--fb-text-muted);
	max-width: 35rem;
	text-wrap: pretty;
}

.fb-eyebrow,
.is-style-fb-eyebrow {
	font-family: var(--fb-font-mono);
	font-size: 0.75rem;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--fb-text-muted);
	margin: 0 0 1rem;
	display: block;
}

blockquote {
	border-left: 2px solid var(--fb-accent);
	padding-left: 1.25rem;
	font-style: italic;
	color: var(--fb-text-muted);
}

hr, .wp-block-separator {
	border: 0;
	border-top: 1px solid var(--fb-border);
	margin: var(--fb-section-y) 0;
}

code, kbd, pre { font-family: var(--fb-font-mono); font-size: 0.9em; }

/* ==========================================================================
   6. Layout
   ========================================================================== */

.fb-shell { display: flex; flex-direction: column; min-height: 100vh; }
.fb-main { flex: 1 0 auto; }

.fb-wrap {
	width: 100%;
	max-width: 68rem;
	margin-inline: auto;
	padding-inline: var(--fb-gutter);
}

.fb-prose {
	max-width: var(--fb-measure);
	margin-inline: auto;
	text-wrap: pretty;
}

.fb-section { padding-block: var(--fb-section-y); }
.fb-section + .fb-section { padding-top: 0; }

.fb-stack { display: flex; flex-direction: column; gap: 1.5rem; }

/* ==========================================================================
   7. Header
   ========================================================================== */

.fb-header {
	position: sticky;
	top: 0;
	z-index: 50;
	background: color-mix(in oklab, var(--fb-bg) 88%, transparent);
	backdrop-filter: blur(12px);
	-webkit-backdrop-filter: blur(12px);
	border-bottom: 1px solid var(--fb-border);
}

.fb-header__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	min-height: 64px;
}

.fb-brand {
	font-family: var(--fb-font-display);
	font-weight: 660;
	font-size: 1.0625rem;
	letter-spacing: -0.02em;
	color: var(--fb-text);
	text-decoration: none;
	white-space: nowrap;
	/* Padding, not height: keeps the 44px thumb target without moving the text. */
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding-block: 0.5rem;
}
.fb-brand:hover { color: var(--fb-accent); }

.fb-nav { display: flex; align-items: center; }

.fb-menu {
	display: flex;
	align-items: center;
	gap: 0.25rem;
	list-style: none;
	margin: 0;
	padding: 0;
}
.fb-menu li { margin: 0; }

.fb-header__controls { display: flex; align-items: center; gap: 0.5rem; }

.fb-nav a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: 0 0.75rem;
	border-radius: var(--fb-radius-sm);
	color: var(--fb-text-muted);
	text-decoration: none;
	font-size: 0.9375rem;
	transition: color 0.2s var(--fb-ease), background-color 0.2s var(--fb-ease);
}
.fb-nav a:hover { color: var(--fb-text); background: var(--fb-surface-2); }
.fb-nav a[aria-current="page"] { color: var(--fb-text); font-weight: 500; }

/* Theme toggle — two states, never three */
.fb-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	flex: 0 0 44px;
	padding: 0;
	border: 1px solid var(--fb-border);
	border-radius: 999px;
	background: transparent;
	color: var(--fb-text-muted);
	cursor: pointer;
	transition: color 0.2s var(--fb-ease), border-color 0.2s var(--fb-ease);
}
.fb-toggle:hover { color: var(--fb-text); border-color: var(--fb-text-muted); }
.fb-toggle svg { width: 18px; height: 18px; display: block; }
.fb-toggle .fb-toggle__moon { display: none; }
/* Show the icon for the mode the button will switch TO. */
:root[data-theme="dark"] .fb-toggle__sun { display: none; }
:root[data-theme="dark"] .fb-toggle__moon { display: block; }
@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) .fb-toggle__sun { display: none; }
	:root:not([data-theme="light"]) .fb-toggle__moon { display: block; }
}

/* Mobile disclosure */
.fb-burger { display: none; }

/* ==========================================================================
   8. Hero
   ========================================================================== */

.fb-hero { padding-block: clamp(3.5rem, 8vw, 6.5rem) clamp(3rem, 6vw, 5rem); }

.fb-hero__grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	gap: clamp(2rem, 5vw, 4rem);
	align-items: center;
}

.fb-hero h1 { margin-bottom: 0.35em; }

.fb-hero__tag {
	font-family: var(--fb-font-mono);
	font-size: 0.8125rem;
	letter-spacing: 0.06em;
	color: var(--fb-accent);
	margin: 0 0 1.25rem;
}

.fb-portrait {
	width: clamp(140px, 22vw, 232px);
	aspect-ratio: 1;
	border-radius: 50%;
	object-fit: cover;
	border: 1px solid var(--fb-border);
	box-shadow: 0 24px 60px -20px var(--fb-shadow);
}

.fb-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 2rem; }

/* ==========================================================================
   9. Buttons
   ========================================================================== */

.fb-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	min-height: 44px;
	padding: 0.6875rem 1.375rem;
	border-radius: var(--fb-radius-sm);
	border: 1px solid transparent;
	font-family: var(--fb-font-display);
	font-size: 0.9375rem;
	font-weight: 600;
	line-height: 1;
	text-decoration: none;
	cursor: pointer;
	transition: transform 0.2s var(--fb-ease), background-color 0.2s var(--fb-ease),
		border-color 0.2s var(--fb-ease), color 0.2s var(--fb-ease);
}
.fb-btn:hover { transform: translateY(-1px); }
.fb-btn:active { transform: translateY(0); }

.fb-btn--primary { background: var(--fb-accent); color: var(--fb-accent-ink); }
.fb-btn--primary:hover { background: color-mix(in oklab, var(--fb-accent) 88%, var(--fb-text)); }

.fb-btn--ghost { border-color: var(--fb-border); color: var(--fb-text); background: transparent; }
.fb-btn--ghost:hover { border-color: var(--fb-accent); color: var(--fb-accent); }

/* ==========================================================================
   10. Cards and the works list
   ========================================================================== */

.fb-grid {
	display: grid;
	gap: 1.25rem;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
}

.fb-card {
	display: flex;
	flex-direction: column;
	gap: 0.625rem;
	padding: 1.5rem;
	background: var(--fb-surface);
	border: 1px solid var(--fb-border);
	border-radius: var(--fb-radius);
	transition: transform 0.25s var(--fb-ease), border-color 0.25s var(--fb-ease);
}
.fb-card:hover { transform: translateY(-2px); border-color: color-mix(in oklab, var(--fb-accent) 45%, var(--fb-border)); }

.fb-card h3 { margin: 0; }
.fb-card h3 a { color: inherit; text-decoration: none; }
.fb-card h3 a:hover { color: var(--fb-accent); }
.fb-card p { color: var(--fb-text-muted); font-size: 0.9375rem; margin: 0; }

/* Status is information, so it is encoded in colour AND in words. */
.fb-status {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	align-self: flex-start;
	padding: 0.25rem 0.625rem;
	border-radius: 999px;
	font-family: var(--fb-font-mono);
	font-size: 0.6875rem;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	background: var(--fb-accent-soft);
	color: var(--fb-text);
	border: 1px solid var(--fb-border);
}
.fb-status::before {
	content: "";
	width: 6px; height: 6px;
	border-radius: 50%;
	background: var(--fb-text-muted);
}
.fb-status--complete::before { background: var(--fb-accent); }
.fb-status--progress::before {
	background: var(--fb-accent);
	box-shadow: 0 0 0 3px color-mix(in oklab, var(--fb-accent) 22%, transparent);
}
.fb-status--hiatus::before { background: transparent; border: 1px solid var(--fb-text-muted); }

.fb-meta {
	font-family: var(--fb-font-mono);
	font-size: 0.75rem;
	letter-spacing: 0.05em;
	color: var(--fb-text-muted);
}

/* A callout used for the content warning and the IP notice. */
.fb-note,
.is-style-fb-note {
	padding: 1.25rem 1.5rem;
	background: var(--fb-surface);
	border: 1px solid var(--fb-border);
	border-left: 3px solid var(--fb-accent);
	border-radius: 0 var(--fb-radius-sm) var(--fb-radius-sm) 0;
	font-size: 0.9375rem;
	color: var(--fb-text-muted);
}
.fb-note strong,
.is-style-fb-note strong { color: var(--fb-text); }

/* Link list — the "where to find me" block.

   The row, not the anchor, is the box. That way the list is an ordinary
   core/list block — a link followed by a sentence — and the whole row is
   still one target, via a stretched ::after over the padded <li>. The older
   shape (a flex <a> wrapping <b> and <span>) needed hand-written HTML and
   reordered its own children, which is the bug .fb-marks documents below. */
.fb-links,
.is-style-fb-links { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.fb-links li,
.is-style-fb-links li {
	position: relative;
	margin: 0;
	padding: 0.75rem 1rem;
	min-height: 44px;
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 0.25rem 0.75rem;
	border: 1px solid var(--fb-border);
	border-radius: var(--fb-radius-sm);
	color: var(--fb-text-muted);
	font-size: 0.875rem;
	transition: border-color 0.2s var(--fb-ease), background-color 0.2s var(--fb-ease);
}
.fb-links li:hover,
.is-style-fb-links li:hover { border-color: var(--fb-accent); background: var(--fb-surface); }
.fb-links li > a,
.is-style-fb-links li > a {
	font-family: var(--fb-font-display);
	font-weight: 620;
	font-size: 1.0625rem;
	white-space: nowrap;
	color: var(--fb-text);
	text-decoration: none;
}
/* Stretched hit area: the row is the target, but only the anchor is focusable,
   so keyboard and pointer agree on what is being activated. */
.fb-links li > a::after,
.is-style-fb-links li > a::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: var(--fb-radius-sm);
}
.fb-links li:focus-within,
.is-style-fb-links li:focus-within { border-color: var(--fb-accent); }

/* Marked list — a short run of facts. The marker is a ::before rather than a
   flex child: an <li> laid out as a flex container turns every inline child
   into a flex item, which reorders <strong> and <em> out of the sentence. */
.fb-marks,
.is-style-fb-marks {
	list-style: none;
	margin: 0 0 2.5rem;
	padding: 0;
	max-width: none;
	display: grid;
	gap: 0.75rem;
}
.fb-marks li,
.is-style-fb-marks li { position: relative; margin: 0; padding-left: 1.5rem; }
.fb-marks li::before,
.is-style-fb-marks li::before {
	/* The second declaration gives the glyph an empty accessible name so screen
	   readers do not announce it; the markup it replaced carried aria-hidden for
	   the same reason. Browsers without alt-text support keep the first. */
	content: "\203A";
	content: "\203A" / "";
	position: absolute;
	left: 0.25rem;
	color: var(--fb-accent);
}

/* ==========================================================================
   11. Forms
   ========================================================================== */

.fb-field { display: flex; flex-direction: column; gap: 0.4rem; margin-bottom: 1.125rem; }
.fb-field label { font-family: var(--fb-font-display); font-weight: 600; font-size: 0.9375rem; }

input[type="text"], input[type="email"], input[type="url"],
input[type="search"], input[type="tel"], input[type="number"],
input[type="password"], input[type="date"], textarea, select {
	width: 100%;
	padding: 0.75rem 0.875rem;
	font-family: inherit;
	font-size: 1rem; /* 16px — anything smaller makes iOS zoom on focus */
	color: var(--fb-text);
	background: var(--fb-bg);
	border: 1px solid var(--fb-border);
	border-radius: var(--fb-radius-sm);
	transition: border-color 0.2s var(--fb-ease);
}
input:focus, textarea:focus, select:focus { border-color: var(--fb-accent); }
/* Safari styles a search input as a rounded pill and ignores the box above. */
input[type="search"] { -webkit-appearance: none; appearance: none; }
textarea { min-height: 9rem; resize: vertical; }

/* ==========================================================================
   12. Footer
   ========================================================================== */

.fb-footer {
	margin-top: var(--fb-section-y);
	padding-block: 2.5rem;
	border-top: 1px solid var(--fb-border);
	color: var(--fb-text-muted);
	font-size: 0.875rem;
}
.fb-footer__inner {
	display: flex;
	flex-wrap: wrap;
	gap: 1rem;
	align-items: center;
	justify-content: space-between;
}
.fb-footer a { color: var(--fb-text-muted); }
.fb-footer a:hover { color: var(--fb-accent); }

/* ==========================================================================
   13. Motion
   --------------------------------------------------------------------------
   Reveals run once. On a long chapter page, re-animating on scroll-back is
   nausea, not polish.
   ========================================================================== */

/* Hiding is opt-in, and only a document that has actually run theme.js opts
   in. The inverse — hide by default, unhide for `.no-js` — leaves the content
   invisible for ever anywhere the script is absent but the stylesheet is not.
   The block editor is exactly that place: it loads style.css into the canvas
   and none of the theme's JS, so under the old rule all 22 reveal groups on
   the home page sat at opacity 0 and the author saw an empty page. */
.fb-js .fb-reveal {
	opacity: 0;
	transform: translateY(16px);
	transition: opacity var(--fb-dur) var(--fb-ease), transform var(--fb-dur) var(--fb-ease);
	transition-delay: var(--fb-delay, 0s);
}
.fb-js .fb-reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
	.fb-js .fb-reveal { opacity: 1; transform: none; }
	.fb-btn:hover, .fb-card:hover { transform: none; }
}

/* ==========================================================================
   14. Responsive
   ========================================================================== */

@media (max-width: 1024px) {
	:root { --fb-measure: 39.5rem; }
}

@media (max-width: 640px) {
	:root { --fb-text-base: 1.0625rem; }

	.fb-hero__grid { grid-template-columns: 1fr; text-align: left; }
	.fb-portrait { width: 128px; order: -1; }
	.fb-lede,
	.is-style-fb-lede { max-width: none; }

	.fb-burger {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		width: 44px; height: 44px;
		padding: 0;
		border: 1px solid var(--fb-border);
		border-radius: var(--fb-radius-sm);
		background: transparent;
		color: var(--fb-text);
		cursor: pointer;
	}
	.fb-burger svg { width: 20px; height: 20px; }

	.fb-nav {
		display: none;
		position: absolute;
		inset-inline: 0;
		top: 100%;
		flex-direction: column;
		align-items: stretch;
		gap: 0;
		padding: 0.5rem var(--fb-gutter) 1rem;
		background: var(--fb-bg);
		border-bottom: 1px solid var(--fb-border);
	}
	.fb-header[data-open="true"] .fb-nav { display: flex; }
	.fb-menu { flex-direction: column; align-items: stretch; gap: 0; width: 100%; }
	.fb-nav a { min-height: 48px; padding-inline: 0; font-size: 1rem; }

	.fb-header__inner { position: relative; }
	.fb-actions .fb-btn { flex: 1 1 auto; }
	.fb-footer__inner { flex-direction: column; align-items: flex-start; }
}

/* Anything wide gets to scroll inside itself; the page never scrolls sideways. */
.wp-block-table, pre, .fb-scroll { overflow-x: auto; max-width: 100%; }

@media print {
	.fb-header, .fb-footer, .fb-toggle, .fb-burger { display: none !important; }
	body { background: #fff; color: #000; }
}

/* ==========================================================================
   15. Post and page content
   --------------------------------------------------------------------------
   Blocks sit on the reading measure by default; only wide and full opt out.
   ========================================================================== */

.fb-page-content > * {
	max-width: var(--fb-measure);
	margin-inline: auto;
}

.fb-page-content > .alignwide { max-width: 68rem; }
.fb-page-content > .alignfull { max-width: none; }

/* Children are already capped at the measure by the rule above. Anything that
   also constrains itself would be centred inside that column by the auto
   margins, leaving a left edge that disagrees with the headings. */
.fb-page-content > .fb-lede,
.fb-page-content > .is-style-fb-lede,
.fb-page-content > .fb-contact { max-width: var(--fb-measure); }

.fb-page-content > * + * { margin-top: 1.5rem; }
.fb-page-content > h2 { margin-top: 2.75rem; }
.fb-page-content > h3 { margin-top: 2rem; }

.fb-page-content :where(figure, .wp-block-image) img { border-radius: var(--fb-radius-sm); }

.wp-block-image figcaption,
figcaption {
	font-size: 0.8125rem;
	color: var(--fb-text-muted);
	text-align: center;
	margin-top: 0.625rem;
}

/* Pagination */
.wp-block-query-pagination,
.navigation.pagination {
	display: flex;
	justify-content: center;
	gap: 0.5rem;
	margin-top: 3rem;
}
.navigation.pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	min-height: 44px;
	padding: 0 0.75rem;
	border: 1px solid var(--fb-border);
	border-radius: var(--fb-radius-sm);
	color: var(--fb-text-muted);
	text-decoration: none;
}
.navigation.pagination .page-numbers:hover { border-color: var(--fb-accent); color: var(--fb-accent); }
.navigation.pagination .page-numbers.current {
	background: var(--fb-accent);
	border-color: var(--fb-accent);
	color: var(--fb-accent-ink);
}

/* The FICTBASE plugin's own reader output, brought onto the theme's tokens
   rather than left on its defaults. */
.fictbase-story-list,
.fictbase-chapter-list { list-style: none; margin: 0; padding: 0; }

/* stretch, not flex-end: the button then matches the input height exactly
   instead of sitting a few pixels proud of it. */
.fb-searchform { display: flex; gap: 0.5rem; align-items: stretch; flex-wrap: wrap; }
.fb-searchform .fb-field { flex: 1 1 14rem; margin-bottom: 0; }

/* Front page sections manage their own width. */
.fb-home > * { max-width: none; }

/* The honeypot must be unreachable for people but present for bots, so it is
   moved off-screen rather than display:none, which some bots skip. */
.fb-hp {
	position: absolute !important;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

.fb-contact { max-width: 34rem; margin-bottom: 3rem; }
.fb-contact .fb-btn { margin-top: 0.5rem; }

/* ==========================================================================
   16. Standing down the plugin's own reader theme
   --------------------------------------------------------------------------
   FICTBASE (free) injects `body{background:#111113;color:#f4f4f5;}` inline
   when its own theme setting is dark or auto. This theme owns the palette in
   both modes, so that rule has to lose. It is specificity 0,0,1; `html body`
   is 0,0,2 and wins regardless of enqueue order.

   The theme also declares add_theme_support( 'fictbase-palette' ). Once a
   plugin release honours that flag the plugin will emit nothing here and this
   block becomes redundant belt-and-braces — harmless either way.
   ========================================================================== */

html body {
	background: var(--fb-bg);
	color: var(--fb-text);
}

/* The plugin's reader wrappers inherit the theme's tokens rather than its
   own hardcoded greys. */
.fb-theme-dark,
.fb-theme-light,
.fb-theme-auto {
	background: transparent;
	color: inherit;
}

/* ==========================================================================
   17. Bridging the plugin's palette onto the theme's
   --------------------------------------------------------------------------
   FICTBASE (free) ships a complete, hardcoded *light* palette in reader.css,
   declared under the same `--fb-*` names this theme sets on :root, scoped to
   its own containers:

       .fictbase-story-page, .fictbase-stories, .fictbase-stories-page,
       .fictbase-login-widget, .fictbase-bookmarks-page      (0,1,0)
       #fb-reader                                            (1,0,0)

   Inside those containers the plugin's values win for every descendant, so
   neither the site's colour scheme nor the reader's light/dark choice reaches
   any plugin UI. In dark mode that is not cosmetic: the chapter body and the
   story titles resolve to near-black on the near-black page and disappear.

   Fixing it from the theme side means re-declaring the plugin's names inside
   the plugin's own scopes, pointed at the theme's values. That cannot be done
   with the same names — `--fb-text: var(--fb-text)` in a nested scope is a
   self-reference, which is a cycle and computes as guaranteed-invalid. So the
   eight names that actually collide get a differently-named alias first.

   The rest of the theme's tokens (--fb-bg, --fb-text-muted, --fb-accent-soft,
   --fb-accent-ink, --fb-font-body, --fb-font-display) are NOT redeclared by
   the plugin, so they are already readable inside its containers and are used
   directly below.

   --fb-shadow deliberately has no alias: the theme's is a bare colour, the
   plugin's is a whole box-shadow value. Mapping one onto the other would put
   a colour where a shadow is expected and silently drop every shadow.

   All of this is belt-and-braces once a plugin release honours the
   `fictbase-palette` theme support flag declared in functions.php.
   ========================================================================== */

:root {
	--fbt-accent: var(--fb-accent);
	--fbt-text: var(--fb-text);
	--fbt-surface: var(--fb-surface);
	--fbt-surface-2: var(--fb-surface-2);
	--fbt-border: var(--fb-border);
	--fbt-radius: var(--fb-radius);
	--fbt-radius-sm: var(--fb-radius-sm);
}

/* `:root:root` is (0,2,0) on its own, so these land at (0,3,0) / (1,2,0) and
   clear the plugin's own dark block too, which peaks at `.fb-theme-dark
   #fb-reader` (1,1,0). */
:root:root .fictbase-story-page,
:root:root .fictbase-stories,
:root:root .fictbase-stories-page,
:root:root .fictbase-login-widget,
:root:root .fictbase-bookmarks-page,
:root:root #fb-reader {
	--fb-accent: var(--fbt-accent);
	--fb-accent-dk: color-mix(in oklab, var(--fbt-accent) 82%, #000);
	--fb-accent-bg: var(--fb-accent-soft);

	--fb-text: var(--fbt-text);
	--fb-text-2: var(--fbt-text);
	--fb-muted: var(--fb-text-muted);
	--fb-light: var(--fb-text-muted);

	--fb-surface: var(--fbt-surface);
	--fb-surface-2: var(--fbt-surface-2);
	--fb-border: var(--fbt-border);
	--fb-border-2: var(--fbt-border);

	--fb-radius: var(--fbt-radius);
	--fb-radius-sm: var(--fbt-radius-sm);

	--fb-font: var(--fb-font-body);
	--fb-font-serif: var(--fb-font-body);
}

/* The plugin writes a page background and text colour directly onto its
   wrappers, not through a token, whenever its own theme setting is dark or
   auto. The theme owns the page, so those lose — including the `#fb-reader`
   descendant form, which section 16 above does not reach. */
:root:root .fb-theme-dark,
:root:root .fb-theme-light,
:root:root .fb-theme-auto,
:root:root .fb-theme-dark #fb-reader,
:root:root .fb-theme-auto #fb-reader {
	background: transparent;
	color: inherit;
}

:root:root body.fictbase-reader-page { background: var(--fb-bg); }

/* --------------------------------------------------------------------------
   Literals the plugin never routed through a token. These are the ones that
   actually break — a white or near-white fill, or near-black text, painted
   unconditionally and therefore wrong in dark mode.
   -------------------------------------------------------------------------- */

:root:root .fb-reader-content { color: var(--fbt-text); }

:root:root .fb-follow-form__input,
:root:root .fb-btn--outline,
:root:root .fb-chapnav__prev { background: var(--fbt-surface); }

:root:root .fb-follow-widget {
	background: var(--fb-accent-soft);
	border-color: var(--fbt-border);
}

/* Indigo left over from the plugin's own brand: a focus ring, a hover tint,
   the button shadows and the progress bar's second gradient stop. */
:root:root .fb-follow-form__input:focus {
	box-shadow: 0 0 0 3px var(--fb-accent-soft);
}
:root:root .fb-btn--primary,
:root:root .fb-btn--primary:hover {
	color: var(--fb-accent-ink) !important;
	box-shadow: 0 1px 3px var(--fb-shadow);
}
:root:root .fb-filter-pill--active { color: var(--fb-accent-ink); }
:root:root #fb-reader .fb-reader-nav__bm-link:hover {
	color: var(--fbt-accent);
	background: var(--fb-accent-soft);
}
:root:root #fb-progress-bar { background: var(--fbt-accent); }

/* The plugin colours its separators and the chapter-link arrow with
   --fb-border, which is a hairline colour doing a glyph's job: 1.15:1 against
   its own page, and no better against ours. The arrow in particular is an
   affordance, so it gets the muted text colour instead. */
:root:root .fb-story-stats__sep,
:root:root .fb-chapter-ol__meta-sep,
:root:root .fb-chapter-ol__arrow { color: var(--fb-text-muted); }

/* space-between with no gap and no wrap: on a phone the story title and the
   chapter number shrink until they touch, reading as one run of words. */
:root:root .fb-reader-nav { flex-wrap: wrap; gap: 0.5rem 1rem; }

/* ==========================================================================
   18. Editing these components as blocks
   --------------------------------------------------------------------------
   Every component above is a plain class selector, so it attaches to whatever
   element carries the class — including a core block given the class through
   the editor's Advanced > Additional CSS class field, which is how the
   patterns in inc/class-patterns.php apply them.

   Two things have to be reconciled for that to hold up.
   ========================================================================== */

/* 1. Core wraps a group's children in its flow layout, which spaces them with
      `> * + * { margin-block-start }`. Inside a component that already spaces
      its children with gap, that margin is doubled — and inside a grid it
      pushes rows apart unevenly. The component owns its own spacing. */
.fb-grid.is-layout-flow > * + *,
.fb-card.is-layout-flow > * + *,
.fb-hero__grid.is-layout-flow > * + *,
.fb-actions.is-layout-flow > * + * { margin-block-start: 0; }

/* 2. A core button block puts the author's class on the wrapping <div>, not on
      the <a> that is actually painted, so .fb-btn cannot be applied directly.
      Style the anchor instead and the Button block simply looks right — no
      custom class for the author to remember, and the block styles registered
      in functions.php provide the variants by name. */
.wp-block-button__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	min-height: 44px;
	padding: 0.6875rem 1.375rem;
	border-radius: var(--fb-radius-sm);
	border: 1px solid transparent;
	background: var(--fb-accent);
	color: var(--fb-accent-ink);
	font-family: var(--fb-font-display);
	font-size: 0.9375rem;
	font-weight: 600;
	line-height: 1;
	text-decoration: none;
	transition: transform 0.2s var(--fb-ease), background-color 0.2s var(--fb-ease),
		border-color 0.2s var(--fb-ease), color 0.2s var(--fb-ease);
}
.wp-block-button__link:hover {
	transform: translateY(-1px);
	background: color-mix(in oklab, var(--fb-accent) 88%, var(--fb-text));
}
.wp-block-button__link:active { transform: translateY(0); }

.is-style-fb-ghost .wp-block-button__link {
	background: transparent;
	border-color: var(--fb-border);
	color: var(--fb-text);
}
.is-style-fb-ghost .wp-block-button__link:hover {
	background: transparent;
	border-color: var(--fb-accent);
	color: var(--fb-accent);
}

.wp-block-buttons.fb-actions { gap: 0.75rem; margin-top: 2rem; }

/* A core/image given the portrait class: core adds its own <figure> wrapper,
   so the class lands there and not on the image. The figure keeps the sizing;
   the circle, the border and the shadow have to move to the <img>, or they
   would frame a square box around a round picture. */
figure.fb-portrait {
	margin: 0;
	border: 0;
	border-radius: 0;
	box-shadow: none;
}
figure.fb-portrait img {
	display: block;
	width: 100%;
	height: 100%;
	border-radius: 50%;
	object-fit: cover;
	border: 1px solid var(--fb-border);
	box-shadow: 0 24px 60px -20px var(--fb-shadow);
}
