/* =============================================================================
   OpusCMS — Default Theme Stylesheet
   -----------------------------------------------------------------------------
   The SINGLE source of styling for the public-facing site. Goal: a clean,
   minimalist baseline that looks finished out of the box and is easy to read
   and re-skin.

   HOW TO RE-COLOR THE WHOLE SITE
     Edit the variables in section 1 (:root). Every component pulls its colors,
     radii and spacing from there — change a token, the site follows.

   HOW TO RE-SKIN A SINGLE SECTION
     Each section below maps 1:1 to a template under /system/<controller>/*.php.
     Class names mirror the markup, so search the class to find both ends.

   CONVENTIONS
     - All design decisions live in CSS variables (section 1).
     - No external fonts, no @imports, no CSS-in-JS — stays light on purpose.
     - Ordered generic -> specific (reset, base, layout, then per-controller).
     - Light and dark live side by side in section 1 via light-dark(). The
       visitor's OS preference wins by default; the header toggle overrides it
       per browser by setting data-theme="light|dark" on <html>. To force a
       single palette, replace the light-dark() pairs with plain values.

   TABLE OF CONTENTS
     1.  Design tokens (variables)
     2.  Reset & base elements
     3.  Layout (header, nav, main, footer, container)
     4.  Breadcrumbs
     5.  Typography & prose (.content-body)
     6.  Buttons & pills
     7.  Covers (page / post / entry)
     8.  Card grid (blog, gallery, glossary, books, music, categories)
     9.  Tags & filters
     10. Glossary (alphabet + term list)
     11. Gallery (image grid)
     12. Author page
     13. Knowledge Base
     14. News
     15. Pagination
     16. Error & empty states
     17. Detail meta / single-entity bits
     18. Books & Music (single-entity two-column layouts)
     19. Link-in-bio layout
     20. Image lightbox (paired with /system/assets/js/main.js)
     21. Dark mode (color-scheme wiring + media-only tweaks)
     22. Responsive overrides + reduced motion
     23. Redactix WYSIWYG blocks (callouts, quote-cards, galleries, embeds,
         video, spoiler, mark — extends section 5 / .content-body)
   ============================================================================= */


/* ----- 1. Design tokens ----------------------------------------------------- */
:root {
    /* Follow the OS preference unless the header toggle pins one (section 21). */
    color-scheme: light dark;

    /* Color — one line per token, light value first, dark second.
       light-dark() picks a side from the `color-scheme` above, so there is a
       single place to recolor and no separate dark-mode block to keep in sync.
       (Section 21 only decides WHICH side is active.)                         */
    --color-bg:            light-dark(#ffffff, #0d0f13);   /* page background       */
    --color-surface:       light-dark(#f5f6f8, #171a20);   /* cards, code, callouts */
    --color-surface-2:     light-dark(#eceef1, #21252d);   /* stronger fill / hover */
    --color-text:          light-dark(#18181b, #e6e7ea);   /* body text             */
    --color-text-muted:    light-dark(#6b7280, #9aa0ab);   /* meta, captions        */
    --color-heading:       light-dark(#0f172a, #f3f4f6);   /* headings              */
    --color-border:        light-dark(#e5e7eb, #272b33);   /* hairlines, outlines   */
    --color-primary:       light-dark(#2563eb, #60a5fa);   /* links, accents        */
    --color-primary-hover: light-dark(#1d4ed8, #93c5fd);
    --color-primary-soft:  light-dark(#eff4ff, #18233b);   /* tint behind filters   */
    --color-danger:        light-dark(#dc2626, #f87171);

    /* Amber "author notes" callout (self-contained, stays light in dark mode) */
    --color-note-bg:     #fffbeb;
    --color-note-border: #fde68a;
    --color-note-text:   #92400e;

    /* Typography */
    --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

    /* Sizing */
    --max-width:     1080px;   /* outer container (lists, grids, headers) */
    --reading-width: 72ch;     /* prose column width for comfy line length */

    /* Media shapes — every cropped image box derives its ratio from a token,
       so a theme can re-proportion a whole class of images in one line. */
    /* A hero cover is a banner: wide and short. Editors upload portraits too,
       and a tall frame turns those into a wall of image that pushes the article
       off the screen — the wide frame keeps every page's header the same height
       whatever was uploaded. */
    --cover-ratio: 16 / 9;     /* hero cover on pages / posts / entries / KB */
    --card-ratio:  16 / 10;    /* card thumbnails in list grids              */
    /* Which part of an off-ratio image survives the crop. Subjects sit well
       above the centre in portrait shots, so the frame favours the top. */
    --cover-focus: center 25%;

    /* Radii */
    --radius-sm:   8px;
    --radius-md:   12px;
    --radius-lg:   16px;
    --radius-full: 9999px;

    /* Elevation. light-dark() only takes colors, so the geometry stays fixed
       and only the tint switches — shadows go deeper on a dark page. */
    --shadow-tint-1: light-dark(rgba(15, 23, 42, .04), rgba(0, 0, 0, .36));
    --shadow-tint-2: light-dark(rgba(15, 23, 42, .06), rgba(0, 0, 0, .44));
    --shadow-tint-3: light-dark(rgba(15, 23, 42, .08), rgba(0, 0, 0, .50));
    --shadow-tint-4: light-dark(rgba(15, 23, 42, .05), rgba(0, 0, 0, .38));
    --shadow-sm: 0 1px 2px var(--shadow-tint-1), 0 1px 3px var(--shadow-tint-2);
    --shadow-md: 0 6px 16px var(--shadow-tint-3), 0 2px 6px var(--shadow-tint-4);

    /* Motion */
    --ease: cubic-bezier(.4, 0, .2, 1);
}


/* ----- 2. Reset & base ------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

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

body {
    font-family: var(--font-sans);
    font-size: 16px;
    line-height: 1.6;
    color: var(--color-text);
    background: var(--color-bg);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

a { color: var(--color-primary); text-decoration: none; }
a:hover { color: var(--color-primary-hover); text-decoration: underline; }

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

ul, ol { padding-left: 1.4em; }

::selection { background: var(--color-primary); color: #fff; }

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


/* ----- 3. Layout ------------------------------------------------------------ */
.container {
    max-width: var(--max-width);
    margin: 0 auto;
    padding: 0 20px;
}

/* Article pages are a single column of prose, so the CONTAINER narrows and
   stays centred — title, meta, cover and body all line up in the middle of the
   viewport. Capping only the text inside a full-width container is what leaves
   a narrow column pinned to the left with a field of empty space beside it.
   Templates opt in with `$content_width = 'narrow';` (see layouts/default.php);
   grids and two-column layouts keep the full width. */
.container-narrow { max-width: calc(var(--reading-width) + 40px); }

/* Keyboard-only shortcut past the header straight into the content. Off-screen
   until focused, then it parks itself over the top-left corner. */
.skip-link {
    position: absolute;
    left: 8px;
    top: -60px;
    z-index: 100;
    padding: 10px 16px;
    background: var(--color-primary);
    color: #fff;
    border-radius: var(--radius-sm);
    font-size: 14px;
    font-weight: 600;
    transition: top .15s var(--ease);
}
.skip-link:focus { top: 8px; text-decoration: none; color: #fff; }

/* Sticky, lightly translucent header (solid fallback for old browsers) */
.site-header {
    position: sticky;
    top: 0;
    z-index: 50;
    background: var(--color-bg);
    background: color-mix(in srgb, var(--color-bg) 82%, transparent);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--color-border);
}
.site-header .container {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 20px;
    min-height: 60px;
    padding-top: 12px;
    padding-bottom: 12px;
}
.site-logo {
    font-size: 19px;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--color-heading);
    margin-right: auto;      /* pushes nav + actions to the right edge */
}
.site-logo:hover { text-decoration: none; opacity: .85; }

.site-nav { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.site-nav a {
    color: var(--color-text-muted);
    font-size: 15px;
    padding: 6px 10px;
    border-radius: var(--radius-sm);
    transition: color .15s var(--ease), background .15s var(--ease);
}
.site-nav a:hover {
    color: var(--color-text);
    background: var(--color-surface);
    text-decoration: none;
}

/* "Explore" dropdown — a native <details> styled as a menu (no-JS baseline). */
.nav-menu { position: relative; }
.nav-menu > summary {
    list-style: none;            /* hide the default disclosure triangle */
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 6px 10px;
    border-radius: var(--radius-sm);
    color: var(--color-text-muted);
    font-size: 15px;
    transition: color .15s var(--ease), background .15s var(--ease);
}
.nav-menu > summary::-webkit-details-marker { display: none; }
.nav-menu > summary::after { content: "\25BE"; font-size: 11px; opacity: .7; transition: transform .15s var(--ease); }
.nav-menu > summary:hover,
.nav-menu[open] > summary { color: var(--color-text); background: var(--color-surface); }
.nav-menu[open] > summary::after { transform: rotate(180deg); }

.nav-menu-panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;                    /* right-anchored so it never clips off-screen */
    z-index: 60;
    min-width: 200px;
    max-width: min(280px, 86vw);
    max-height: 72vh;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    padding: 6px;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
}
.nav-menu-panel a {
    padding: 9px 12px;
    border-radius: var(--radius-sm);
    color: var(--color-text);
    font-size: 15px;
    white-space: nowrap;
}
.nav-menu-panel a:hover { background: var(--color-surface); color: var(--color-primary); text-decoration: none; }

/* Marks the current section in the header and in the dropdown. */
.site-nav a[aria-current="page"],
.nav-menu-panel a[aria-current="page"] { color: var(--color-primary); background: var(--color-primary-soft); }

/* Language switcher (multilingual mode) — a .nav-menu dropdown living in
   .header-actions. The icon slot renders config-supplied markup: an emoji,
   an inline <svg> or an <img>. */
.header-actions .lang-menu > summary { display: inline-flex; align-items: center; gap: 6px; }
.lang-menu .lang-icon { display: inline-flex; align-items: center; }
.lang-menu .lang-icon svg,
.lang-menu .lang-icon img { width: 16px; height: 16px; display: block; }
.lang-menu .lang-code { font-size: 12px; letter-spacing: .04em; }
.header-actions .lang-menu .nav-menu-panel { right: 0; left: auto; }
.lang-menu .nav-menu-panel a { display: flex; align-items: center; gap: 8px; }
.lang-menu .nav-menu-panel a[aria-current="true"] { color: var(--color-primary); background: var(--color-primary-soft); }

/* Header buttons: theme toggle + mobile menu. Both are icon-sized squares so
   they line up with the nav links without changing the header height. */
.header-actions { display: flex; align-items: center; gap: 4px; }

.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--color-text-muted);
    cursor: pointer;
    line-height: 1;
    transition: color .15s var(--ease), background .15s var(--ease);
}
.icon-btn:hover { color: var(--color-text); background: var(--color-surface); }
.icon-btn svg { width: 18px; height: 18px; }

/* Both buttons do nothing without JS, so they only exist once theme.js has
   marked the document (it runs in <head>, before the header is parsed). */
.theme-toggle, .nav-toggle { display: none; }
.has-js .theme-toggle { display: inline-flex; }

/* One icon at a time, chosen by the palette actually in effect — including the
   un-pinned case, where the OS decides and no data-theme is set. */
.theme-toggle .icon-dark { display: none; }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .theme-toggle .icon-dark  { display: block; }
    :root:not([data-theme="light"]) .theme-toggle .icon-light { display: none; }
}
:root[data-theme="dark"] .theme-toggle .icon-dark  { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-light { display: none; }

.site-main {
    padding: 40px 0 56px;
    min-height: 64vh;
}

.site-footer {
    border-top: 1px solid var(--color-border);
    margin-top: 40px;
    padding: 32px 0;
    color: var(--color-text-muted);
    font-size: 14px;
}
/* Sections on the left, copyright on the right; stacks and centers on mobile. */
.site-footer .container {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px 24px;
}
.footer-nav { display: flex; flex-wrap: wrap; gap: 4px 16px; }
.footer-nav a { color: var(--color-text-muted); }
.footer-nav a:hover { color: var(--color-text); }
.site-footer-copy { margin-left: auto; }

/* Admin-only "this entry isn't published yet" banner (default layout) */
.preview-banner {
    background: var(--color-note-bg);
    color: var(--color-note-text);
    border-bottom: 1px solid var(--color-note-border);
    padding: 10px 16px;
    text-align: center;
    font-size: 14px;
    font-weight: 600;
}


/* ----- 4. Breadcrumbs ------------------------------------------------------- */
.breadcrumbs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: var(--color-text-muted);
    margin-bottom: 28px;
}
.breadcrumbs a { color: var(--color-text-muted); }
.breadcrumbs a:hover { color: var(--color-text); }
.breadcrumbs .sep { color: var(--color-border); }


/* ----- 5. Typography & prose ------------------------------------------------ */
h1, h2, h3, h4 { color: var(--color-heading); letter-spacing: -0.015em; }
h1 { font-size: clamp(28px, 4vw, 36px); font-weight: 700; line-height: 1.15; margin-bottom: 18px; text-wrap: balance; }
h2 { font-size: 24px; font-weight: 700; line-height: 1.25; }
h3 { font-size: 19px; font-weight: 600; line-height: 1.3; }

/* .content-body = HTML coming from the WYSIWYG editor (post/page/entry body). */
.content-body {
    font-size: 17px;
    line-height: 1.7;
    max-width: var(--reading-width);   /* readable line length */
}
.content-body > * + * { margin-top: 18px; }   /* vertical rhythm */
.content-body h2 { margin-top: 40px; margin-bottom: 8px; }
.content-body h3 { margin-top: 28px; margin-bottom: 8px; }
.content-body a { text-decoration: underline; text-underline-offset: 2px; }
.content-body ul, .content-body ol { padding-left: 1.5em; }
.content-body li + li { margin-top: 6px; }
.content-body img { border-radius: var(--radius-md); margin: 8px 0; }
.content-body figure { margin: 8px 0; }
.content-body figcaption { font-size: 14px; color: var(--color-text-muted); margin-top: 6px; }
.content-body blockquote {
    border-left: 3px solid var(--color-primary);
    padding: 4px 0 4px 18px;
    color: var(--color-text-muted);
    font-style: italic;
}
.content-body hr { border: 0; border-top: 1px solid var(--color-border); margin: 32px 0; }
.content-body code {
    font-family: var(--font-mono);
    font-size: .9em;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 5px;
    padding: .1em .35em;
}
.content-body pre {
    font-family: var(--font-mono);
    font-size: 14px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: 16px;
    overflow-x: auto;
}
.content-body pre code { background: none; border: 0; padding: 0; }
.content-body table { width: 100%; border-collapse: collapse; font-size: 15px; }
.content-body th, .content-body td { border: 1px solid var(--color-border); padding: 8px 12px; text-align: left; }
.content-body th { background: var(--color-surface); font-weight: 600; }


/* ----- 6. Buttons & pills --------------------------------------------------- */
/* Small reusable accent button (not heavily used by stock templates, but handy
   for theme overrides and keeps look consistent). */
.btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 9px 16px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-border);
    background: var(--color-bg);
    color: var(--color-text);
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    transition: background .15s var(--ease), border-color .15s var(--ease);
}
.btn:hover { background: var(--color-surface); text-decoration: none; }
.btn-primary { background: var(--color-primary); border-color: var(--color-primary); color: #fff; }
.btn-primary:hover { background: var(--color-primary-hover); border-color: var(--color-primary-hover); color: #fff; }


/* ----- 7. Covers ------------------------------------------------------------ */
/* Hero cover image on pages / posts / entries / KB articles.

   MARKUP
     <figure class="cover page-cover"> … </figure>
   The second class is the legacy per-section name (.page-cover /
   .post-cover-main / .entry-cover / .kb-article-cover). It carries no rules of
   its own any more — it stays so themes that already target it keep working.

   SHAPE
     The frame is a fixed aspect box (--cover-ratio) and the image fills it with
     object-fit: cover. That is what makes every page look the same regardless
     of what the editor uploaded: a panorama and a portrait both land in the
     same rectangle instead of the old "whatever height the file happens to be,
     capped at 460px". Reserving the box also means zero layout shift.

     Width matches the prose column below it, so the article reads as one
     column instead of a wide image over a narrow text block. Add .cover-wide
     for the full-container, edge-to-edge variant.

   PER-PAGE OVERRIDE
     Cropping a tall photo into a wide frame always loses something, so both
     the frame and the part that survives it are tokens a single cover can
     override inline — there is no per-image focal point in the DB:
       <figure class="cover" style="--cover-ratio: 3/4; --cover-focus: top">   */
.cover {
    display: block;
    margin: 0 0 32px;
    max-width: var(--reading-width);
    aspect-ratio: var(--cover-ratio);
    overflow: hidden;
    border-radius: var(--radius-lg);
    /* Hairline so a light photo never bleeds into a light page. The global
       border-box reset keeps it out of the aspect-ratio maths. */
    border: 1px solid color-mix(in srgb, var(--color-text) 9%, transparent);
    background: var(--color-surface);
}
.cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: var(--cover-focus);
}
/* Full-bleed variant — for image-led pages where the cover IS the statement. */
.cover-wide { max-width: none; }

/* Legacy markup: <div class="page-cover"><img …> with no .cover on the
   wrapper. A theme that still ships the old shape gets the same frame — the
   aspect box moves onto the image, since the wrapper isn't sized here. Without
   this an un-migrated template renders the file at its natural height, which
   for a portrait photo means a full screen of image. */
.page-cover:not(.cover),
.post-cover-main:not(.cover),
.entry-cover:not(.cover),
.kb-article-cover:not(.cover) {
    display: block;
    margin: 0 0 32px;
    max-width: var(--reading-width);
    overflow: hidden;
    border-radius: var(--radius-lg);
    border: 1px solid color-mix(in srgb, var(--color-text) 9%, transparent);
    background: var(--color-surface);
}
.page-cover:not(.cover) img,
.post-cover-main:not(.cover) img,
.entry-cover:not(.cover) img,
.kb-article-cover:not(.cover) img {
    width: 100%;
    aspect-ratio: var(--cover-ratio);
    object-fit: cover;
    object-position: var(--cover-focus);
}

/* Optional caption under a cover (<figcaption>), aligned with the prose. */
.cover-caption {
    max-width: var(--reading-width);
    margin: -24px 0 32px;
    font-size: 14px;
    color: var(--color-text-muted);
}


/* ----- 8. Card grid --------------------------------------------------------- */
/* Used by blog/list, gallery/list, glossary collection, books, music, categories */
.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(248px, 1fr));
    gap: 24px;
    margin-top: 24px;
}

.cms-card {
    display: flex;
    flex-direction: column;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    overflow: hidden;
    transition: transform .18s var(--ease), box-shadow .18s var(--ease), border-color .18s var(--ease);
}
.cms-card:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow-md);
    border-color: transparent;
}

/* Thumbnail shape: --card-ratio by default (landscape, suits articles and
   photos); .square for albums, .portrait for book jackets. Anything with a
   genuinely portrait source should say so — cropping a wide photo into 3/4
   cuts the subject in half, which is why the blog no longer asks for it.     */
.cms-card-cover {
    display: block;
    position: relative;
    aspect-ratio: var(--card-ratio);
    background: var(--color-surface);
    overflow: hidden;
}
.cms-card-cover.square   { aspect-ratio: 1 / 1; }
.cms-card-cover.portrait { aspect-ratio: 3 / 4; }
.cms-card-cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: var(--cover-focus);
    transition: transform .35s var(--ease);
}
.cms-card:hover .cms-card-cover img { transform: scale(1.04); }

/* No cover uploaded. A bare emoji on flat grey reads as "broken"; the hairline
   grid behind it reads as a deliberate empty slot, and the glyph shrinks to a
   marker of the content type rather than the main event. */
.cms-card-cover-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 26px;
    opacity: .5;
    background-color: var(--color-surface);
    background-image:
        linear-gradient(color-mix(in srgb, var(--color-text) 5%, transparent) 1px, transparent 1px),
        linear-gradient(90deg, color-mix(in srgb, var(--color-text) 5%, transparent) 1px, transparent 1px);
    background-size: 22px 22px, 22px 22px;
    background-position: center;
}

.cms-card-badge {
    position: absolute;
    top: 10px;
    right: 10px;
    background: rgba(15, 23, 42, .72);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    color: #fff;
    padding: 4px 10px;
    border-radius: var(--radius-full);
    font-size: 12px;
    font-weight: 600;
    line-height: 1.4;
}
.cms-card-badge.bg-red  { background: var(--color-danger); }
.cms-card-badge.bg-blue { background: var(--color-primary); }
.cms-card-badge.bottom  { top: auto; bottom: 10px; }   /* 18+, Explicit */

.cms-card-body {
    padding: 16px;
    display: flex;
    flex-direction: column;
    flex: 1;
    gap: 8px;
}
.cms-card-title { font-size: 17px; font-weight: 600; line-height: 1.3; }
.cms-card-title a { color: var(--color-heading); }
.cms-card-title a:hover { color: var(--color-primary); text-decoration: none; }

.cms-card-meta {
    font-size: 13px;
    color: var(--color-text-muted);
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
}
.cms-card-preview {
    font-size: 14px;
    color: var(--color-text-muted);
    line-height: 1.55;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.cms-card-footer {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: auto;
    padding-top: 4px;
}


/* ----- 9. Tags & filters ---------------------------------------------------- */
.tag-pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 10px;
    border-radius: var(--radius-full);
    font-size: 12px;
    font-weight: 500;
    background: var(--color-surface);
    color: var(--color-text-muted);
    border: 1px solid var(--color-border);
    transition: background .15s var(--ease), color .15s var(--ease), border-color .15s var(--ease);
}
a.tag-pill:hover {
    background: var(--color-primary);
    color: #fff;
    border-color: var(--color-primary);
    text-decoration: none;
}

.active-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding: 12px 14px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    font-size: 14px;
    color: var(--color-text-muted);
    margin-bottom: 24px;
}
.active-filters .tag-pill {
    background: var(--color-primary-soft);
    color: var(--color-primary);
    border-color: transparent;
}
.clear-filters { color: var(--color-danger); margin-left: auto; font-size: 13px; }


/* ----- 10. Glossary --------------------------------------------------------- */
.letter-filter { display: flex; flex-wrap: wrap; gap: 6px; margin: 24px 0 8px; }
.letter-filter a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 36px;
    height: 36px;
    padding: 0 8px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    font-size: 14px;
    color: var(--color-text-muted);
    background: var(--color-bg);
    transition: all .15s var(--ease);
}
.letter-filter a:hover,
.letter-filter a.active {
    background: var(--color-primary);
    color: #fff;
    border-color: var(--color-primary);
    text-decoration: none;
}

.letter-heading {
    margin-top: 36px;
    margin-bottom: 14px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--color-border);
}

.term-list {
    list-style: none;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 8px;
}
.term-list li a {
    display: block;
    padding: 9px 14px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    color: var(--color-text);
    font-size: 14px;
    transition: border-color .15s var(--ease), color .15s var(--ease), background .15s var(--ease);
}
.term-list li a:hover {
    border-color: var(--color-primary);
    color: var(--color-primary);
    background: var(--color-primary-soft);
    text-decoration: none;
}


/* ----- 11. Gallery image grid ----------------------------------------------- */
.gallery-images {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 16px;
    margin: 28px 0;
}
.gallery-figure {
    margin: 0;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--color-bg);
    transition: box-shadow .18s var(--ease), transform .18s var(--ease);
}
.gallery-figure:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); }
.gallery-figure > a { display: block; overflow: hidden; }
.gallery-figure img {
    width: 100%;
    height: 220px;
    object-fit: cover;
    transition: transform .35s var(--ease);
}
.gallery-figure:hover img { transform: scale(1.05); }
.gallery-figure figcaption { padding: 12px 14px; font-size: 14px; border-top: 1px solid var(--color-border); }
.gallery-figure-title { display: block; font-weight: 600; margin-bottom: 2px; }
.gallery-figure-description { color: var(--color-text-muted); font-size: 13px; }


/* ----- 12. Author page ------------------------------------------------------ */
.author-header {
    display: flex;
    gap: 28px;
    align-items: flex-start;
    margin-bottom: 36px;
    padding-bottom: 28px;
    border-bottom: 1px solid var(--color-border);
}
.author-avatar {
    width: 112px;
    height: 112px;
    border-radius: var(--radius-full);
    object-fit: cover;
    flex-shrink: 0;
    box-shadow: var(--shadow-sm);
}
.author-bio { flex: 1; }
.author-bio h1 { margin-bottom: 8px; }
.author-bio-short { color: var(--color-text-muted); font-size: 17px; }

.author-links { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; }
.author-link-logo { width: 16px; height: 16px; }

.author-bio-full { margin-bottom: 8px; }

.author-materials { margin-top: 40px; }
.author-materials-title {
    padding-bottom: 10px;
    border-bottom: 2px solid var(--color-border);
    margin-bottom: 20px;
}
.material-group { margin-bottom: 28px; }
.material-group-title {
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-text-muted);
    margin-bottom: 12px;
}
.material-list { list-style: none; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.material-list li {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
    padding: 12px 16px;
    background: var(--color-surface);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    transition: border-color .15s var(--ease), background .15s var(--ease);
}
.material-list li:hover { border-color: var(--color-border); background: var(--color-bg); }
.material-list time { color: var(--color-text-muted); font-size: 13px; white-space: nowrap; }


/* ----- 13. Knowledge Base --------------------------------------------------- */
.kb-categories { display: flex; flex-direction: column; gap: 40px; margin-top: 24px; }
.kb-category {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: 24px;
    background: var(--color-bg);
}
.kb-category-cover {
    margin: -24px -24px 20px;
    aspect-ratio: 21 / 8;    /* 21/6 was a letterbox slit — it beheaded people */
    overflow: hidden;
    background: var(--color-surface);
}
.kb-category-cover img { width: 100%; height: 100%; object-fit: cover; object-position: var(--cover-focus); }
.kb-category-title { margin-bottom: 6px; }
.kb-category-description { color: var(--color-text-muted); margin-bottom: 16px; }

.kb-article-list { list-style: none; padding: 0; display: flex; flex-direction: column; }
.kb-article-list li {
    padding: 14px 0;
    border-top: 1px solid var(--color-border);
}
.kb-article-list li:first-child { border-top: 0; padding-top: 0; }
.kb-article-list li a { font-weight: 600; font-size: 16px; color: var(--color-heading); }
.kb-article-list li a:hover { color: var(--color-primary); text-decoration: none; }
.kb-article-description { color: var(--color-text-muted); font-size: 14px; margin-top: 3px; }

/* Single KB article */
.kb-article-category {
    display: inline-block;
    background: var(--color-primary-soft);
    color: var(--color-primary);
    padding: 2px 10px;
    border-radius: var(--radius-full);
    font-size: 12px;
    font-weight: 600;
}

.kb-prev-next {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    margin-top: 48px;
    padding-top: 24px;
    border-top: 1px solid var(--color-border);
}
.kb-nav-link {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 16px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    color: var(--color-text);
    transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
    height: 100%;
}
.kb-nav-link:hover { border-color: var(--color-primary); box-shadow: var(--shadow-sm); text-decoration: none; }
.kb-nav-next { text-align: right; }
.kb-nav-direction { font-size: 12px; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: .04em; }
.kb-nav-title { font-weight: 600; color: var(--color-heading); }
.kb-nav-category { font-size: 13px; color: var(--color-text-muted); }

.kb-category-siblings {
    margin-top: 40px;
    padding: 20px 24px;
    background: var(--color-surface);
    border-radius: var(--radius-md);
}
.kb-category-siblings h2 { font-size: 17px; margin-bottom: 12px; }
.kb-category-siblings .kb-article-list li { border-color: var(--color-surface-2); }


/* ----- 14. News ------------------------------------------------------------- */
.news-list { list-style: none; padding: 0; display: flex; flex-direction: column; }
.news-item {
    padding: 24px 0;
    border-top: 1px solid var(--color-border);
}
.news-item:first-child { border-top: 0; padding-top: 8px; }
.news-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    font-size: 13px;
    color: var(--color-text-muted);
    margin-bottom: 6px;
}
.news-item-title { font-size: 22px; line-height: 1.25; margin-bottom: 6px; }
.news-item-title a { color: var(--color-heading); }
.news-item-title a:hover { color: var(--color-primary); text-decoration: none; }
.news-item-description { color: var(--color-text-muted); max-width: var(--reading-width); }

/* Single news article */
.news-article-description {
    font-size: 19px;
    color: var(--color-text-muted);
    margin-bottom: 24px;
    max-width: var(--reading-width);
}
.news-neighbours {
    margin-top: 48px;
    padding-top: 24px;
    border-top: 1px solid var(--color-border);
}
.news-neighbours h2 { font-size: 18px; margin-bottom: 14px; }
.news-neighbours-list { list-style: none; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.news-neighbours-list li {
    display: flex;
    gap: 14px;
    align-items: baseline;
    padding: 8px 0;
}
.news-neighbours-list time { color: var(--color-text-muted); font-size: 13px; white-space: nowrap; min-width: 92px; }


/* ----- 15. Pagination ------------------------------------------------------- */
.pagination {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    justify-content: center;
    margin-top: 40px;
}
.pagination a,
.pagination span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 38px;
    height: 38px;
    padding: 0 12px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    font-size: 14px;
    color: var(--color-text);
    background: var(--color-bg);
    transition: border-color .15s var(--ease), color .15s var(--ease);
}
.pagination a:hover { border-color: var(--color-primary); color: var(--color-primary); text-decoration: none; }
.pagination span.current {
    background: var(--color-primary);
    color: #fff;
    border-color: var(--color-primary);
    font-weight: 600;
}
/* Collapsed run of pages in compact mode — a separator, not a target */
.pagination span.gap {
    border-color: transparent;
    background: none;
    color: var(--color-text-muted);
    min-width: 0;
    padding: 0 4px;
}


/* ----- 16. Error & empty states --------------------------------------------- */
/* An error page is a dead end unless it offers somewhere to go, so the status
   code is demoted to a label and the actions get button weight. */
.error-page {
    text-align: center;
    max-width: 480px;
    margin: 0 auto;
    padding: 72px 0 88px;
}
.error-page h1 {
    font-size: 15px;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--color-text-muted);
    margin-bottom: 14px;
}
.error-page-message {
    font-size: clamp(22px, 3.2vw, 28px);
    font-weight: 700;
    line-height: 1.25;
    color: var(--color-heading);
    letter-spacing: -0.015em;
    margin-bottom: 12px;
    text-wrap: balance;
}
.error-page p { color: var(--color-text-muted); margin-bottom: 16px; }
.error-page-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    justify-content: center;
    margin-top: 24px;
}

.no-results {
    text-align: center;
    padding: 56px 20px;
    color: var(--color-text-muted);
    border: 1px dashed var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
}
.no-results p { margin: 0; }
.no-results p + p { margin-top: 8px; font-size: 14px; }


/* ----- 17. Detail meta / single-entity bits --------------------------------- */
/* Shared meta line atop blog post / gallery item / glossary entry / KB / news */
.detail-meta {
    font-size: 14px;
    color: var(--color-text-muted);
    margin-bottom: 24px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

/* Tag row under detail pages */
.detail-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 40px;
    padding-top: 20px;
    border-top: 1px solid var(--color-border);
}

/* Inline terms list above content (glossary entry) */
.entry-terms {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 20px;
}
.entry-terms-label {
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--color-text-muted);
}

/* Description / content block atop collection & category pages */
.collection-description { margin-bottom: 32px; }


/* ----- 18. Books & Music (single-entity two-column layouts) ----------------- */
.book-layout,
.album-layout {
    display: grid;
    grid-template-columns: 300px 1fr;
    gap: 40px;
    align-items: start;
    margin-top: 8px;
}
/* Sidebar sticks while the long main column scrolls */
.book-sidebar,
.album-sidebar {
    display: flex;
    flex-direction: column;
    gap: 24px;
    position: sticky;
    top: 84px;
}

.book-cover-wrap {
    padding: 10px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
}
.book-cover-img { width: 100%; border-radius: var(--radius-sm); }

.book-links h2,
.album-links h2,
.album-credits h2 {
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: .05em;
    margin-bottom: 12px;
    color: var(--color-text-muted);
}
.book-features {
    padding: 14px 16px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    font-size: 14px;
    color: var(--color-text-muted);
}
.book-features ul { padding-left: 1.2em; display: flex; flex-direction: column; gap: 6px; }

.book-title, .album-title { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.book-series-label { color: var(--color-text-muted); font-size: 14px; margin-bottom: 16px; }

.book-meta, .album-meta {
    font-size: 14px;
    color: var(--color-text-muted);
    margin-bottom: 20px;
    display: flex;
    flex-wrap: wrap;
    gap: 8px 18px;
}
.book-meta strong, .album-meta strong { color: var(--color-text); font-weight: 600; }

.book-genres { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 20px; }

/* Synopsis = italic blurb above the main content */
.book-synopsis {
    font-style: italic;
    padding: 16px 20px;
    background: var(--color-surface);
    border-left: 3px solid var(--color-primary);
    border-radius: var(--radius-sm);
    margin-bottom: 28px;
}

.book-chapters, .album-songs, .album-videos { margin-top: 36px; }
.book-chapters h2, .album-songs h2, .album-videos h2 {
    padding-bottom: 10px;
    border-bottom: 1px solid var(--color-border);
    margin-bottom: 18px;
}
.chapter-item {
    padding: 16px 18px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    margin-bottom: 12px;
}
.chapter-title { font-weight: 600; font-size: 17px; margin-bottom: 4px; }
.chapter-description { color: var(--color-text-muted); font-size: 14px; margin-bottom: 8px; }
.chapter-content { margin-top: 12px; line-height: 1.7; }
.chapter-item details summary,
.song-lyrics-container summary { cursor: pointer; color: var(--color-primary); font-size: 14px; font-weight: 500; }

/* Amber "author notes" callout — shared between books and music */
.author-notes {
    padding: 18px 20px;
    background: var(--color-note-bg);
    border: 1px solid var(--color-note-border);
    border-radius: var(--radius-md);
    margin-top: 28px;
}
.author-notes h2 {
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--color-note-text);
    margin-bottom: 8px;
    border: 0;
    padding: 0;
}
.author-notes .content-body { color: var(--color-note-text); font-size: 15px; max-width: none; }

/* "18+" / "Explicit" inline badges next to a title */
.adult-badge,
.explicit-badge {
    display: inline-block;
    background: var(--color-danger);
    color: #fff;
    padding: 2px 8px;
    border-radius: var(--radius-sm);
    font-size: 12px;
    font-weight: 700;
    vertical-align: middle;
}
.explicit-badge.small { padding: 1px 5px; font-size: 10px; margin-left: 4px; }

/* Album */
.album-cover-wrap {
    aspect-ratio: 1 / 1;
    padding: 10px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    display: flex;
    align-items: center;
    justify-content: center;
}
.album-cover-img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-sm); }
.album-cover-placeholder { font-size: 64px; opacity: .35; }

.album-credits {
    padding: 14px 16px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    font-size: 14px;
}
.album-credits ul { list-style: none; padding: 0; display: grid; gap: 6px; }

.songs-list { display: flex; flex-direction: column; gap: 8px; }
.song-item {
    padding: 12px 14px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
}
.song-header { display: flex; gap: 14px; align-items: flex-start; }
.song-number { font-weight: 700; color: var(--color-text-muted); min-width: 22px; text-align: right; }
.song-info { flex: 1; min-width: 0; }
.song-title { font-weight: 600; }
.song-description { color: var(--color-text-muted); font-size: 14px; }
.song-duration { color: var(--color-text-muted); font-size: 14px; margin-left: auto; font-variant-numeric: tabular-nums; }

.song-lyrics-container { margin-top: 10px; margin-left: 36px; }
.song-lyrics {
    margin-top: 8px;
    padding: 12px 14px;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    font-size: 14px;
    line-height: 1.6;
}

.album-videos { display: flex; flex-direction: column; gap: 20px; }
.album-videos h2 { margin-bottom: 0; }
.video-embed {
    position: relative;
    padding-bottom: 56.25%;
    height: 0;
    overflow: hidden;
    border-radius: var(--radius-md);
    background: #000;
}
.video-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* Series sections on /books */
.book-series-section { margin-bottom: 48px; }
.series-description { color: var(--color-text-muted); margin-bottom: 16px; max-width: var(--reading-width); }


/* ----- 19. Link-in-bio layout ----------------------------------------------- */
/* Styles theme-independent /links page (layout: linkinbio.php). Narrow, centered.
   Reused by the Books "Where to get" and Music "Listen on" link blocks.        */
.lib-container {
    max-width: 560px;
    margin: 0 auto;
    padding: 48px 16px 64px;
    color: var(--color-text);
}

/* Language switcher (multilingual sites only, and only for languages this
   card actually exists in — see layouts/linkinbio.php).                       */
.lib-langs {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: 14px;
    margin-top: 32px;
    font-size: 14px;
}
.lib-langs a {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--color-text-muted);
    text-decoration: none;
}
.lib-langs a:hover { color: var(--color-text); }
.lib-langs a[aria-current] { color: var(--color-text); font-weight: 600; }

.lib-hero { text-align: center; margin-bottom: 28px; }
.lib-avatar {
    width: 96px;
    height: 96px;
    border-radius: 50%;
    object-fit: cover;
    margin: 0 auto 14px;
    border: 3px solid var(--color-bg);
    box-shadow: var(--shadow-md);
}
.lib-hero-title { font-size: 22px; font-weight: 700; margin-bottom: 4px; }
.lib-hero-description {
    font-size: 14px;
    color: var(--color-text-muted);
    max-width: 400px;
    margin: 0 auto 16px;
    white-space: pre-line;
}

.lib-bullets { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.lib-bullet {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border-radius: 50%;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    transition: transform .15s var(--ease), border-color .15s var(--ease);
}
.lib-bullet:hover { transform: translateY(-2px); border-color: var(--color-primary); }
.lib-bullet img { width: 20px; height: 20px; object-fit: contain; }

.lib-blocks { display: flex; flex-direction: column; gap: 10px; margin-top: 24px; }

.lib-link {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    color: var(--color-text);
    transition: transform .15s var(--ease), border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.lib-link:hover { transform: translateY(-2px); border-color: var(--color-primary); box-shadow: var(--shadow-sm); text-decoration: none; }
.lib-link-logo { width: 28px; height: 28px; object-fit: contain; flex-shrink: 0; }
.lib-link-content { flex: 1; min-width: 0; }
.lib-link-title { font-size: 15px; font-weight: 600; }
.lib-link-description { font-size: 13px; color: var(--color-text-muted); margin-top: 2px; }
.lib-link-nsfw {
    font-size: 10px;
    font-weight: 700;
    color: var(--color-danger);
    background: rgba(220, 38, 38, .1);
    padding: 2px 6px;
    border-radius: var(--radius-sm);
}
.lib-link-arrow { color: var(--color-text-muted); font-size: 16px; }

.lib-youtube {
    position: relative;
    padding-bottom: 56.25%;
    height: 0;
    border-radius: var(--radius-md);
    overflow: hidden;
}
.lib-youtube iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.lib-heading { text-align: center; color: var(--color-text-muted); margin-top: 8px; }
.lib-hr { border: 0; border-top: 1px solid var(--color-border); margin: 8px 0; }
.lib-image { border-radius: var(--radius-md); overflow: hidden; }
.lib-paragraph { font-size: 14px; color: var(--color-text-muted); text-align: center; }


/* ----- 20. Image lightbox --------------------------------------------------- */
/* Markup is injected by /system/assets/js/main.js. Any <a data-lightbox="..">
   wrapping an image, plus images inside .content-body, open here. Features:
   wheel-zoom, drag-to-pan, prev/next gallery, keyboard + ESC.                  */

/* JS marks enhanced thumbnails so the cursor hints they are clickable. */
.lightbox-enabled { cursor: zoom-in; }

.lightbox {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(10, 12, 16, .92);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    opacity: 0;
    visibility: hidden;
    transition: opacity .2s var(--ease), visibility .2s var(--ease);
}
.lightbox.is-open { opacity: 1; visibility: visible; }

.lightbox-stage {
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    touch-action: none;   /* we handle pan/zoom ourselves */
}
.lightbox-img {
    max-width: 92vw;
    max-height: 86vh;
    object-fit: contain;
    border-radius: 4px;
    box-shadow: 0 12px 48px rgba(0, 0, 0, .5);
    transform-origin: center center;
    will-change: transform;
    cursor: grab;
    user-select: none;
    -webkit-user-drag: none;
    /* Only opacity animates (fade-in on load) — transform stays instant so
       wheel-zoom and drag-pan feel responsive. */
    transition: opacity .2s var(--ease);
}
.lightbox-img.is-zoomed { cursor: grab; }
.lightbox-img.is-panning { cursor: grabbing; transition: none; }

/* Control buttons */
.lightbox-btn {
    position: absolute;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    border: 0;
    border-radius: var(--radius-full);
    background: rgba(255, 255, 255, .1);
    color: #fff;
    font-size: 26px;
    line-height: 1;
    cursor: pointer;
    transition: background .15s var(--ease);
}
.lightbox-btn:hover { background: rgba(255, 255, 255, .22); }
.lightbox-close { top: 16px; right: 16px; font-size: 30px; }
.lightbox-prev { left: 16px; top: 50%; transform: translateY(-50%); }
.lightbox-next { right: 16px; top: 50%; transform: translateY(-50%); }
.lightbox.is-single .lightbox-prev,
.lightbox.is-single .lightbox-next { display: none; }

.lightbox-caption {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 16px 20px;
    text-align: center;
    color: rgba(255, 255, 255, .92);
    font-size: 14px;
    background: linear-gradient(to top, rgba(0, 0, 0, .55), transparent);
    pointer-events: none;
}
.lightbox-counter { color: rgba(255, 255, 255, .6); margin-right: 8px; font-variant-numeric: tabular-nums; }


/* ----- 21. Dark mode -------------------------------------------------------- */
/* The palettes themselves live in section 1 (light-dark pairs). This section
   only decides which side is active:

     - no data-theme    → `color-scheme: light dark` from section 1, i.e. the
                          visitor's OS setting decides (the default);
     - data-theme=...   → pinned by the header toggle, remembered per browser
                          in localStorage and re-applied by js/theme.js before
                          the first paint (so there is no flash of the wrong
                          palette).

   Delete both rules below plus the toggle in the layout to force one palette,
   or hardcode `color-scheme: light` on :root to opt out of dark entirely.     */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"]  { color-scheme: dark; }

/* Large media reads brighter than the page around it on a dark background;
   knock it back a touch so a white photo doesn't glare. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .cover img,
    :root:not([data-theme="light"]) .kb-category-cover img { filter: brightness(.92); }
}
:root[data-theme="dark"] .cover img,
:root[data-theme="dark"] .kb-category-cover img { filter: brightness(.92); }


/* ----- 22. Responsive + reduced motion -------------------------------------- */
@media (max-width: 860px) {
    .book-layout,
    .album-layout { grid-template-columns: 1fr; }
    .book-sidebar,
    .album-sidebar { position: static; }
    .album-cover-wrap { max-width: 320px; }
}

@media (max-width: 720px) {
    /* Nav collapses behind the burger. Guarded by .has-js: with scripting off
       the button can't open anything, so the links stay visible instead (they
       simply wrap onto a second row, which is the pre-burger behaviour). */
    .has-js .nav-toggle { display: inline-flex; }
    .has-js .site-nav { display: none; }
    .has-js .site-nav[data-open] {
        display: flex;
        order: 3;                /* full-width row under the logo + buttons */
        flex-basis: 100%;
        flex-direction: column;
        align-items: stretch;
        gap: 2px;
        padding: 8px 0 4px;
        border-top: 1px solid var(--color-border);
    }
    .has-js .site-nav[data-open] a { padding: 10px 12px; font-size: 15px; }
    /* An absolutely-positioned dropdown inside a stacked menu would cover the
       links under it — inline the panel instead. */
    .has-js .site-nav[data-open] .nav-menu { width: 100%; }
    .has-js .site-nav[data-open] .nav-menu > summary { justify-content: space-between; padding: 10px 12px; }
    .has-js .site-nav[data-open] .nav-menu-panel {
        position: static;
        max-width: none;
        border: 0;
        border-radius: 0;
        box-shadow: none;
        padding: 0 0 0 12px;
    }
}

@media (max-width: 640px) {
    .site-nav { gap: 2px; }
    .site-nav a { padding: 6px 8px; font-size: 14px; }
    .site-main { padding: 28px 0 40px; }
    .site-footer .container { justify-content: center; text-align: center; }
    .footer-nav { justify-content: center; }
    .site-footer-copy { margin-left: 0; }
    .author-header { flex-direction: column; align-items: center; text-align: center; }
    .author-links { justify-content: center; }
    .kb-prev-next { grid-template-columns: 1fr; }
    .song-lyrics-container { margin-left: 0; }
    .lightbox-img { max-width: 96vw; max-height: 80vh; }
    .lightbox-btn { width: 42px; height: 42px; }
    /* A 16/9 hero eats most of a phone screen before any text shows. */
    :root { --cover-ratio: 4 / 3; }
}

/* Visitors who asked the OS to reduce motion get the same layout with the
   movement removed: no card lift, no zooming thumbnails, no transitions. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
    .cms-card:hover { transform: none; }
    .cms-card:hover .cms-card-cover img,
    .gallery-figure:hover img,
    .content-body .redactix-gallery-grid a:hover img { transform: none; }
    .gallery-figure:hover,
    .lib-link:hover,
    .lib-bullet:hover { transform: none; }
}


/* ----- 23. Redactix WYSIWYG blocks ------------------------------------------ */
/* Styling for the rich blocks the Redactix editor emits inside .content-body.
   The plain elements (p / h1-h3 / lists / tables / pre / code / blockquote /
   img+figure / hr / inline b,i,u,s,sub,sup) are already covered by section 5
   and browser defaults. This section adds only what Redactix wraps in its own
   classes. All colors come from section-1 tokens (or color-mix against them),
   so callouts/quotes/spoiler/mark auto-adapt to dark mode with no extra rules.
   Markup reference: https://github.com/fedorananin/redactix (style.md).         */

/* Lead heading the editor may place in body content (h2/h3 already have rhythm) */
.content-body h1 { margin-top: 36px; margin-bottom: 10px; }
.content-body h1:first-child { margin-top: 0; }

/* --- Inline: highlight + spoiler --- */
/* <mark> — token-tinted so it stays legible on both light and dark pages. */
.content-body mark {
    background: color-mix(in srgb, #facc15 38%, transparent);
    color: inherit;
    padding: 0 .15em;
    border-radius: 3px;
}
/* <span class="spoiler"> — blacked-out bar, revealed on hover / focus / tap. */
.content-body .spoiler {
    background: var(--color-text);
    color: transparent;
    border-radius: 3px;
    padding: 0 .2em;
    cursor: help;
    transition: color .15s var(--ease), background .15s var(--ease);
}
.content-body .spoiler:hover,
.content-body .spoiler:focus,
.content-body .spoiler:active {
    background: var(--color-surface-2);
    color: var(--color-text);
}

/* --- Callouts: <aside> (default) + .information/.success/.warning/.danger --- */
/* Optional leading icon lives in the data-emoji attribute. */
.content-body aside {
    --callout-accent: var(--color-primary);
    position: relative;
    margin: 24px 0;
    padding: 14px 16px;
    background: color-mix(in srgb, var(--callout-accent) 9%, var(--color-bg));
    border: 1px solid color-mix(in srgb, var(--callout-accent) 26%, var(--color-border));
    border-left: 3px solid var(--callout-accent);
    border-radius: var(--radius-md);
}
.content-body aside.information { --callout-accent: var(--color-primary); }
.content-body aside.success     { --callout-accent: #16a34a; }
.content-body aside.warning     { --callout-accent: #d97706; }
.content-body aside.danger      { --callout-accent: var(--color-danger); }
/* Restore vertical rhythm for children (the section-5 rule only spaces direct
   children of .content-body, not of nested asides). */
.content-body aside > * + * { margin-top: 10px; }
.content-body aside > :first-child { margin-top: 0; }
.content-body aside h3 { margin-top: 0; margin-bottom: 0; font-size: 16px; }
.content-body aside hr { margin: 10px 0; }
/* Emoji marker, set off in a left gutter so it never overlaps the text. */
.content-body aside[data-emoji] { padding-left: 46px; }
.content-body aside[data-emoji]::before {
    content: attr(data-emoji);
    position: absolute;
    left: 15px;
    top: 13px;
    font-size: 18px;
    line-height: 1.4;
}

/* --- Quote card: <figure class="quote-card"> (+ .big) --- */
.content-body figure.quote-card {
    margin: 28px 0;
    padding: 20px 24px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-left: 4px solid var(--color-primary);
    border-radius: var(--radius-md);
}
/* Reset the generic section-5 blockquote treatment inside the card. */
.content-body figure.quote-card blockquote {
    margin: 0;
    padding: 0;
    border: 0;
    font-style: normal;
    color: var(--color-text);
}
.content-body figure.quote-card blockquote p + p { margin-top: 12px; }
.content-body figure.quote-card figcaption {
    margin-top: 12px;
    font-weight: 600;
    color: var(--color-text-muted);
}
.content-body figure.quote-card figcaption::before { content: "\2014\00a0"; }   /* em dash */
/* Big / pull-quote variant: centered, larger, no side rule. */
.content-body figure.quote-card.big {
    text-align: center;
    padding: 28px 32px;
    border-left: 0;
}
.content-body figure.quote-card.big blockquote {
    font-size: 1.3em;
    line-height: 1.5;
    font-style: italic;
}

/* --- Inline photo gallery: figure.redactix-gallery > .redactix-gallery-grid --- */
.content-body figure.redactix-gallery { margin: 24px 0; }
.content-body .redactix-gallery-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 8px;
}
.content-body .redactix-gallery-grid a { display: block; overflow: hidden; border-radius: var(--radius-sm); }
.content-body .redactix-gallery-grid img {
    width: 100%;
    height: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    margin: 0;                          /* cancel the section-5 img margin */
    border-radius: var(--radius-sm);
    transition: transform .35s var(--ease);
}
.content-body .redactix-gallery-grid a:hover img { transform: scale(1.05); }

/* --- Embeds: figure.redactix-embed > .redactix-embed-frame (iframe) --- */
/* The aspect-ratio / sizing is carried by inline styles on the frame + iframe;
   we only add the visual frame (rounded corners + fill behind a loading embed). */
.content-body figure.redactix-embed { margin: 24px 0; }
.content-body .redactix-embed-frame {
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--color-surface);
}

/* --- Native video: figure.redactix-video > <video> (inline aspect-ratio) --- */
.content-body figure.redactix-video { margin: 24px 0; }
.content-body .redactix-video video {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--radius-md);
    background: #000;
}

/* figcaption under any of the above already inherits the section-5 caption style */
