/* Mod page layout, loaded by templates/mod.php. style.css still owns the site's tokens, topbar,
   tags, badges, dialogs and README typography.

   Mobile first: base rules are the phone layout, wider arrangements go in min-width queries at
   640 / 768 / 900 / 1200. Widths are never hardcoded, so the topbar's expand toggle keeps
   working and the extra width lands in the README. */

/* A dialog or panel opening must not shift the page sideways: reserve the scrollbar gutter. */
html:has(main.modl) { scrollbar-gutter: stable; }

/* ── Shell ───────────────────────────────────────────────────────────────── */
main.modl { max-width: 1180px; padding-bottom: 3rem; }
html.full-width main.modl { max-width: none; }
/* The footer is a sibling of main, so the wider column has to be repeated here. */
body:has(main.modl) .site-footer-inner { max-width: 1180px; }
html.full-width body:has(main.modl) .site-footer-inner { max-width: none; }

.modl-crumb { margin-bottom: 0.6rem; font-size: 0.9rem; }
.modl-crumb a { color: var(--clr-text-muted); }
.modl-crumb a:hover { color: var(--clr-link); }

.modl-card { background: var(--clr-surface); border: 1px solid var(--clr-border); border-radius: var(--radius-large); box-shadow: var(--shadow-sm); padding: 1rem; }
@media (min-width: 768px) { .modl-card { padding: 1.25rem 1.4rem; }}

.mod-empty { color: var(--clr-text-muted); }

/* Stats live inline in the byline; the star is the only clickable one. */
.mod-stats { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; }
.mod-stat-sep { color: var(--clr-border); }
.star-toggle { display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.1rem 0.55rem; margin: 0; font: inherit; font-size: 0.82rem; font-weight: 600; line-height: 1.6; background: var(--clr-surface-alt); border: 1px solid var(--clr-border); border-radius: 999px; color: var(--clr-text); cursor: pointer; text-decoration: none; }
.star-toggle:hover { border-color: var(--clr-star); color: var(--clr-star); background: var(--clr-surface-alt); text-decoration: none; }
.star-toggle .star-icon { display: inline-flex; color: var(--clr-text-muted); }
.star-toggle:hover .star-icon, .star-toggle.is-starred .star-icon { color: var(--clr-star); }
.star-toggle.is-starred { border-color: var(--clr-star); color: var(--clr-star); }
.mod-stat-quiet { display: inline-flex; align-items: center; gap: 0.3rem; }

/* ── README: full width, never clamped by this stylesheet ───────────────── */
.mod-readme--plain { margin: 0; padding: 1rem; }
@media (min-width: 768px) { .mod-readme--plain { padding: 1.5rem 1.8rem; }}
.mod-readme--plain .mod-readme-edit-btn { float: right; font-size: 0.85rem; gap: 0.3rem; margin-left: 1rem; }

/* ── Related ─────────────────────────────────────────────────────────────── */
.mod-related + .mod-related { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--clr-border); }
.mod-related h4 { display: inline-flex; align-items: center; gap: 0.4rem; margin: 0 0 0.5rem; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--clr-text-muted); }
.mod-related summary { cursor: pointer; list-style: none; min-height: 32px; display: flex; align-items: center; }
.mod-related summary::-webkit-details-marker { display: none; }
.mod-related summary h4 { margin-bottom: 0; }
.mod-related summary::before { content: '▸'; color: var(--clr-text-muted); font-size: 0.8rem; margin-right: 0.35rem; }
.mod-related[open] summary::before { content: '▾'; }
.mod-related[open] summary { margin-bottom: 0.4rem; }
.mod-related ul { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.4rem; }
@media (min-width: 640px) { .mod-related ul { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0.5rem 1.25rem; }}
.mod-related li { display: flex; flex-direction: column; line-height: 1.35; min-width: 0; }
.mod-related-unlinked { color: var(--clr-text-muted); }
.mod-related code { overflow-wrap: anywhere; font-size: 0.78rem; }

/* ── Changelog ───────────────────────────────────────────────────────────── */
.mod-changelog-leading :is(h1, h2) { font-size: 1rem; margin: 0 0 0.5rem; }
.mod-changelog-leading { margin-bottom: 1rem; }
.mod-changelog-entry { display: grid; grid-template-columns: 1fr; gap: 0.35rem; padding: 0.9rem 0; }
.mod-changelog-entry + .mod-changelog-entry { border-top: 1px solid var(--clr-border); }
.mod-changelog-entry:first-child { padding-top: 0; }
.mod-changelog-version { font-weight: 700; font-size: 0.98rem; display: flex; align-items: center; gap: 0.5rem; }
.mod-changelog-body :first-child { margin-top: 0; }
.mod-changelog-body ul { padding-left: 1.1rem; }
.mod-changelog-more { margin-top: 1rem; padding-top: 0.9rem; border-top: 1px solid var(--clr-border); font-size: 0.9rem; }
@media (min-width: 768px) {
	.mod-changelog-entry { grid-template-columns: 7rem 1fr; gap: 1.5rem; }
	.mod-changelog-version { flex-direction: column; align-items: flex-start; gap: 0.35rem; }}

/* ── FAQ ─────────────────────────────────────────────────────────────────── */
.mod-faq-links { margin-top: -.6em; margin-left: -.6em; }
.mod-faq-inline .mod-faq-section-title { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--clr-text-muted); margin: 1.1rem 0 0.4rem; }
.mod-faq-inline .mod-faq-links li { padding: 0.35rem 0; border-bottom: 1px solid color-mix(in srgb, var(--clr-border) 60%, transparent); }
.mod-faq-inline .mod-faq-entry > summary { min-height: 32px; display: flex; align-items: center; gap: 0.35rem; }
.mod-faq-inline .mod-faq-entry-body { padding: 1rem 0 0.6rem 1rem; color: var(--clr-text-muted); }
.mod-faq-new-link { display: inline-block; margin-top: 0.9rem; font-size: 0.9rem; }

/* ── Threads ─────────────────────────────────────────────────────────────── */
.mod-threads-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem; margin-bottom: 0.9rem; }
.thread-filters { display: flex; gap: 0.3rem; overflow-x: auto; scrollbar-width: none; padding-bottom: 0.15rem; margin-inline: -0.25rem; padding-inline: 0.25rem; }
.thread-filters::-webkit-scrollbar { display: none; }
.thread-filter { background: var(--clr-surface-alt); border: 1px solid var(--clr-border); border-radius: 999px; padding: 0.25rem 0.7rem; margin: 0; font-size: 0.83rem; color: var(--clr-text-muted); cursor: pointer; display: inline-flex; gap: 0.35rem; align-items: center; white-space: nowrap; }
.thread-filter span { font-weight: 700; opacity: 0.75; }
.thread-filter:hover { border-color: var(--clr-link); color: var(--clr-link); background: var(--clr-surface-alt); }
.thread-filter.is-active { background: var(--clr-link); border-color: var(--clr-link); color: var(--clr-on-link); }
.mod-thread-new-btn { background: var(--clr-link); color: var(--clr-on-link); border: 1px solid var(--clr-link); border-radius: var(--radius-small); padding: 0.35rem 0.85rem; font-size: 0.88rem; font-weight: 600; cursor: pointer; text-decoration: none; white-space: nowrap; }
.mod-thread-new-btn:hover { background: var(--clr-link-hover); border-color: var(--clr-link-hover); color: var(--clr-on-link); text-decoration: none; }

.thread-rows { list-style: none; margin: 0; padding: 0; }
/* Fixed columns, so the badge and reply count line up down the list. */
.thread-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 0.25rem 0.75rem; padding: 0.65rem 0.5rem; margin: 0 -0.5rem; border-radius: var(--radius-small); border-bottom: 1px solid color-mix(in srgb, var(--clr-border) 70%, transparent); }
.thread-row:last-child { border-bottom: none; }
.thread-row-main { min-width: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.thread-row-title { font-weight: 600; line-height: 1.3; }
/* Two lines with a relative age, not one run of author, version and a full timestamp. */
.thread-row-sub { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; font-size: 0.8rem; color: var(--clr-text-muted); min-width: 0; }
.thread-row-author { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 16rem; }
.thread-row-dot { opacity: 0.55; }
.thread-row-ver { padding: 0 0.4em; border-radius: 999px; background: var(--clr-surface-alt); border: 1px solid var(--clr-border); font-size: 0.72rem; font-weight: 600; }
/* Status and replies ride with the title, wrapping under it when the title is long. */
.thread-row-head { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem 0.5rem; min-width: 0; }
.thread-replies { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.8rem; font-weight: 600; color: var(--clr-text-muted); }
.thread-row-actions { grid-column: 2; display: flex; gap: 0.35rem; align-items: center; justify-content: flex-end; }
@media (max-width: 639px) { .thread-row-actions { grid-column: 1 / -1; }}
.thread-row-actions select, .thread-row-actions button { font-size: 0.8rem; padding: 0.15rem 0.4rem; margin: 0; min-height: 32px; }
/* Fixed width: a select sizes to its selected option, stepping the grid in and out. */
.thread-row-actions select { width: 8.5rem; }
/* Quiet until hovered: a column of red Delete buttons reads as a wall of alarm. */
.thread-row-actions .destructive-action { border-color: var(--clr-border); color: var(--clr-text-muted); }
.thread-row:hover .thread-row-actions .destructive-action,
.thread-row-actions .destructive-action:focus-visible { border-color: var(--clr-danger); color: var(--clr-danger); }
.thread-show-all { display: block; width: 100%; margin: 0.85rem 0 0; padding: 0.55rem 1rem; background: var(--clr-surface-alt); border: 1px solid var(--clr-border); border-radius: var(--radius-small); font-size: 0.88rem; font-weight: 600; color: var(--clr-text-muted); cursor: pointer; min-height: 44px; }
.thread-show-all:hover { border-color: var(--clr-link); color: var(--clr-link); background: var(--clr-surface-alt); }
.thread-empty-filtered { padding: 1.5rem 0; color: var(--clr-text-muted); }
.mod-threads-extra { margin-top: 1.25rem; }
.mod-threads-extra summary { cursor: pointer; font-size: 0.9rem; color: var(--clr-text-muted); min-height: 32px; }
/* An empty filter stays visible but stops looking pressable. */
.thread-filter.is-empty { opacity: 0.45; cursor: default; }
.thread-filter.is-empty:hover { border-color: var(--clr-border); color: var(--clr-text-muted); background: none; }
@media (hover: hover) { .thread-row:hover { background: color-mix(in srgb, var(--clr-link) 5%, transparent); }}

/* ═══ Layout 2 — One page ════════════════════════════════════════════════ */
.op-jump { position: sticky; top: var(--header-height); z-index: 20; display: flex; margin: 0.6rem 0 0; padding: 0.35rem 0.5rem; background: color-mix(in srgb, var(--clr-surface) 94%, transparent); backdrop-filter: blur(8px); border: 1px solid var(--clr-border); border-radius: var(--radius-large); overflow-x: auto; scrollbar-width: none; gap: 0.6rem; }
.op-jump::-webkit-scrollbar { display: none; }
.op-jump a { display: inline-flex; align-items: center; gap: 0.35rem; padding: 0.35rem 0.75rem; border-radius: var(--radius-small); font-size: 0.88rem; font-weight: 600; color: var(--clr-text-muted); white-space: nowrap; min-height: 36px; }
.op-jump a:hover { background: var(--clr-surface-alt); color: var(--clr-text); text-decoration: none; }
.op-jump a.is-active { background: color-mix(in srgb, var(--clr-link) 14%, transparent); color: var(--clr-link); }
/* Same look as the section links, but a <button> (not an <a href="#...">) so it is structurally
   outside the scrollspy's targets — it can be clicked, never "arrived at" by scrolling. Pinned to
   the right on wide screens, where the other items sit left; on the phone-wrap layout there is no
   spare row width to push into, so it just falls in line as the last chip. */
.fn-jump-top { margin-left: auto; font: inherit; background: none; border: none; cursor: pointer; display: inline-flex; align-items: center; gap: 0.35rem; padding: 0.35rem 0.75rem; border-radius: var(--radius-small); font-size: 0.88rem; font-weight: 600; color: var(--clr-text-muted); white-space: nowrap; min-height: 36px; }
.fn-jump-top:hover { background: var(--clr-surface-alt); color: var(--clr-text); }
@media (max-width: 767px) { .fn-jump-top { margin-left: 0; } }
.op-jump span { font-size: 0.72rem; font-weight: 700; padding: 0 0.4em; border-radius: 999px; background: var(--clr-surface-alt); border: 1px solid var(--clr-border); }
/* --sticky-nav-height is kept live by mod-layouts.js (ResizeObserver on the [data-scrollspy]
   bar itself — it wraps to two rows on a narrow phone, so a fixed guess would undershoot there
   and leave a gap everywhere else). The fallback only covers the instant before that JS runs. */
:root { --sticky-nav-height: 3rem; }
.op-section { padding-top: 1.5rem; scroll-margin-top: calc(1rem + var(--header-height) + var(--sticky-nav-height)); }
.op-h { margin: 0 0 0.6rem; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.07em; color: var(--clr-text-muted); }
@media (prefers-reduced-motion: no-preference) {
	@keyframes mod-drawer-in { from { transform: translateX(24px); opacity: 0.4; } to { transform: none; opacity: 1; }}}

/* ── The ⚙ menu: findable, never a primary action ────────────────────────
   A bare icon in a corner was too easy to miss; a filled button competed with Install. A
   bordered, labelled control at the top of the action column sits between the two. */
.mod-cog-menu > summary .cog-label { font-size: 0.85rem; font-weight: 600; }
/* style.css pins the bare cog to a card corner; here it is an in-flow control. */
.mod-actions-col > .mod-cog-menu { position: relative; top: auto; right: auto; }
.mod-actions-col > .mod-cog-menu > summary,
.fn-top .mod-cog-menu > summary,
.wk-infobox .mod-cog-menu > summary { display: inline-flex; align-items: center; gap: 0.35rem; width: auto; height: auto; min-height: 34px; padding: 0.25rem 0.7rem; border: 1px solid var(--clr-border); border-radius: var(--radius-small); background: none; color: var(--clr-text-muted); }
.mod-actions-col > .mod-cog-menu > summary:hover,
.fn-top .mod-cog-menu > summary:hover,
.wk-infobox .mod-cog-menu > summary:hover { border-color: var(--clr-link); color: var(--clr-link); }
@media (max-width: 480px) { .mod-cog-menu > summary .cog-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }}

/* Three rules the page keeps to:
   1. SURFACE. The site paints an animated hex canvas behind everything, so anything with text
      sits on a surface.
   2. HEADING. One section-heading treatment.
   3. ACTION. Three fixed tiers, so a control's weight says what it does: primary filled,
      secondary outlined, tertiary small, then quiet text links. */

/* ── 1. Surface ──────────────────────────────────────────────────────────── */
.modl-surface, .modl-card,
.modl .mod-readme--plain,
.modl .mod-shots,
.modl-panel-card, .st-band, .mn-contents, .sc-fold, .rl-notes-card { background: var(--clr-surface); border: 1px solid var(--clr-border); border-radius: var(--radius-large); box-shadow: var(--shadow-sm); }

/* Layouts whose sections were bare now get the surface back. */
.doc-section > .mod-readme--plain,
.op-section > .mod-readme--plain,
.lf-section > .mod-readme--plain,
.sp-block > .mod-readme--plain,
.bf-block > .mod-readme--plain,
.ed-band-inner > .mod-readme--plain,
.rl-readme > .mod-readme--plain,
.fc-readme > .mod-readme--plain,
.sc-readme > .mod-readme--plain,
.cp-block > .mod-readme--plain { padding: 1rem; }
@media (min-width: 768px) {
	.doc-section > .mod-readme--plain,
	.op-section > .mod-readme--plain,
	.lf-section > .mod-readme--plain,
	.sp-block > .mod-readme--plain,
	.bf-block > .mod-readme--plain,
	.ed-band-inner > .mod-readme--plain,
	.rl-readme > .mod-readme--plain,
	.fc-readme > .mod-readme--plain,
	.sc-readme > .mod-readme--plain,
	.cp-block > .mod-readme--plain { padding: 1.5rem 1.8rem; }}

/* ── 2. Heading ──────────────────────────────────────────────────────────── */
.modl-h, .doc-h, .lf-h, .op-h, .cp-h, .st-h, .bf-h, .ch-h,
.rg-block > h3, .ts-categories h3, .fg-categories h3, .rp-about h2,
.mn-contents h2, .mod-media-head h3, .st-tags-label, .nx-tagrow-label { margin: 0 0 0.7rem; font-size: 0.76rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em; color: var(--clr-text-muted); border-bottom: none; padding-bottom: 0; }

/* ── 3. Action tiers ─────────────────────────────────────────────────────── */
.mod-actions-col { display: flex; flex-direction: column; gap: 0.5rem; position: relative; min-width: 0; }
.act-tier { display: flex; flex-direction: column; gap: 0.4rem; min-width: 0; }
.act-tier--tertiary { flex-direction: row; flex-wrap: wrap; gap: 0.4rem; margin: auto; }
.act { display: flex; align-items: center; justify-content: center; gap: 0.45rem; padding: 0.5rem 0.9rem; margin: 0; background: var(--clr-surface-alt); border: 1px solid var(--clr-border); border-radius: var(--radius-small); font: inherit; font-size: 0.88rem; font-weight: 600; color: var(--clr-text); cursor: pointer; text-decoration: none; text-align: center; min-height: 40px; white-space: nowrap; }
.act:hover { border-color: var(--clr-link); color: var(--clr-link); background: var(--clr-surface-alt); text-decoration: none; }
.act--primary { background: var(--clr-link); border-color: var(--clr-link); color: var(--clr-on-link); }
.act--primary:hover { background: var(--clr-link-hover); border-color: var(--clr-link-hover); color: var(--clr-on-link); }
.act--primary img { height: 1.3em; }
.act--sm { flex: 1 1 0; min-width: 5.5rem; padding: 0.3rem 0.5rem; font-size: 0.82rem; font-weight: 500; min-height: 34px; }
.act-quiet { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem 0.55rem; margin: 0.3rem 0 0; font-size: 0.82rem; color: var(--clr-text-muted); }
/* --clr-border is a hairline colour: on the dark surface the dots vanished entirely. */
.act-quiet-sep { color: var(--clr-text-muted); }
.act-link { background: none; border: none; padding: 0; margin: 0; font: inherit; font-size: 0.82rem; color: var(--clr-link); cursor: pointer; }
.act-link:hover { background: none; text-decoration: underline; color: var(--clr-link-hover); }
.act-warning { margin: 0; font-size: 0.85rem; }

/* Horizontal variant — same three tiers, laid on their side. */
.mod-actions-col--row { flex-direction: row; flex-wrap: wrap; align-items: flex-start; gap: 0.5rem; }
.mod-actions-col--row .act-tier { flex-direction: row; flex-wrap: wrap; }
.mod-actions-col--row .act--sm { flex: 0 0 auto; }
.mod-actions-col--row .act-quiet { flex: 1 1 100%; margin-top: 0.15rem; order: 100; }
.mod-actions-col--row > .mod-cog-menu { order: 99; }

/* The ⚙ sits above the tiers in a column, and last in a row. */
.mod-actions-col > .mod-cog-menu { align-self: flex-end; }
.mod-actions-col--row > .mod-cog-menu { align-self: center; }

/* ── Consistent empty state ──────────────────────────────────────────────── */
.mod-empty { margin: 0; padding: 1.25rem; text-align: center; color: var(--clr-text-muted); font-size: 0.9rem; }

/* ── Fixes from reviewing the unified pass ──────────────────────────────── */

/* Anything with text sits on a surface, or the animated background shows through. */
.dc-nav, .dc-toc, .lf-nav, .op-jump, .rp-subnav, .ch-list, .mn-contents, .fc-chips { background: var(--clr-surface); border: 1px solid var(--clr-border); border-radius: var(--radius-large); padding: 0.6rem; }

/* Below 640 the icon takes its own row: sharing ~230px wrapped the byline to five lines. */
.mod-header { grid-template-columns: minmax(0, 1fr); grid-template-areas: 'icon' 'main' 'actions' 'meta'; }

/* A tertiary row of one item should not stretch to full width and read as a primary button. */
.act-tier--tertiary:has(.act--sm:only-child) .act--sm { flex: 0 0 auto; }

/* Header: no grid item spans rows any more — the text block is one box, the actions another. */
.mod-header-body { display: contents; }

/* One selector rather than a list of components, which kept missing one. */
.doc-section > *:not(h2):not(h3),
.op-section > *:not(h2),
.lf-section > *:not(h2),
.sp-block > *:not(h2),
.bf-block > *:not(h2),
.cp-block > *:not(h2),
.rl-media > *:not(h2),
.rl-threads > *:not(h2),
.ed-band-inner > *,
.fc-readme > *,
.sc-readme > * { background: var(--clr-surface); border: 1px solid var(--clr-border); border-radius: var(--radius-large); box-shadow: var(--shadow-sm); padding: 1rem; }
@media (min-width: 768px) {
	.doc-section > *:not(h2):not(h3),
	.op-section > *:not(h2),
	.lf-section > *:not(h2),
	.sp-block > *:not(h2),
	.bf-block > *:not(h2),
	.cp-block > *:not(h2),
	.rl-media > *:not(h2),
	.rl-threads > *:not(h2),
	.ed-band-inner > *,
	.fc-readme > *,
	.sc-readme > * { padding: 1.25rem 1.4rem; }
	.doc-section > .mod-readme--plain,
	.op-section > .mod-readme--plain,
	.lf-section > .mod-readme--plain,
	.sp-block > .mod-readme--plain,
	.bf-block > .mod-readme--plain,
	.ed-band-inner > .mod-readme--plain,
	.fc-readme > .mod-readme--plain,
	.sc-readme > .mod-readme--plain { padding: 0.9rem 1.4rem; }}
/* Two stacked surfaces in one section (screenshots + community shots) need a gap, not a seam. */
.doc-section > * + *, .sp-block > * + *, .bf-block > * + *, .rl-media > * + * { margin-top: 0.75rem; }

/* ═══ Layout 21 — Final ══════════════════════════════════════════════════
   The working draft: One page's full-width README and sticky section bar, with the bar moved above
   the screenshots; Nexus's quiet-links row and labelled fact strip closing the header card; the
   buttons still a column on the right; one image band for the author's and the community's shots,
   every thumbnail opening the lightbox; and Gale's per-requirement install button. */
.fn-head { background: var(--clr-surface); border: 1px solid var(--clr-border); border-radius: var(--radius-large); box-shadow: var(--shadow-sm); padding: 1rem; }
@media (min-width: 768px) { .fn-head { padding: 1.25rem 1.4rem; }}
.fn-head { padding-bottom: 0; }

/* Phone order: icon, name, buttons, then the description and the tag pile — the download button is
   never something you scroll a paragraph and eleven tags to reach. `display: contents` keeps the
   desktop grouping (icon beside a single text block) out of the way until 900px. */
.fn-idrow { display: grid; grid-template-columns: minmax(0, 1fr); grid-template-areas: 'icon' 'title' 'actions' 'meta' 'quiet'; gap: 0.9rem 1.25rem; }
/* The ⚙ sits above the card, not in it — style.css pins a bare gear to a corner, so reset that the
   same way the action column does. */
.fn-top { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 0.7rem; }
.fn-top .modl-crumb { margin: 0; }
.fn-top .mod-cog-menu { position: relative; top: auto; right: auto; }
/* Outside the card it sits on the page background, where an unfilled outline all but disappears —
   give it the same surface the action buttons have. */
.fn-top .mod-cog-menu > summary { background: var(--clr-surface-alt); color: var(--clr-text); }
.fn-top .mod-cog-menu > summary:hover { background: var(--clr-surface); }
/* #site-header is z-index 100 and sticky, so the panel needs to outrank it — the menu is the
   positioned ancestor, so the z-index belongs there, not on the panel. */
.fn-top .mod-cog-menu[open] { z-index: 150; }
.fn-icon { width: 64px; height: 64px; aspect-ratio: 1 / 1; object-fit: cover; border-radius: var(--radius-large); background: var(--clr-surface-alt); }
.fn-title { grid-area: title; min-width: 0; align-self: center; }
.fn-title h1 { margin: 0; font-size: 1.25rem; line-height: 1.25; overflow-wrap: anywhere; }
.fn-meta { grid-area: meta; min-width: 0; }
.fn-meta .tag-list { margin-top: 0.7rem; }
.fn-actions { grid-area: actions; min-width: 0; }
@media (min-width: 640px) {
	.fn-idrow { grid-template-columns: auto minmax(0, 1fr); grid-template-areas: 'icon title' 'actions actions' 'meta meta' 'quiet quiet'; }
	.fn-icon { width: 96px; height: 96px; }
	.fn-title h1 { font-size: 1.5rem; }}
@media (min-width: 900px) {
	/* The name belongs with the description, not in a row of its own: a title row sized by the
	   110px icon left a band of dead space between the two. Icon and text are one flex block
	   instead, the icon centred against it, so the gap is a line-height rather than an icon. */
	.fn-idrow {
		/* A fixed action column (rather than a percentage) so the quiet row can offset itself by
		   exactly that width and land centred on the card, not on the identity column. */
		--fn-actions-w: 220px;
		grid-template-columns: auto minmax(0, 1fr) var(--fn-actions-w);
		grid-template-areas: 'icon main  actions' 'icon quiet actions';
		grid-template-rows: 1fr auto;
		align-items: start;
	}
	/* The button column is taller than the identity on most mods, so centre the identity against it
	   rather than leaving the slack in one lump under the tags. */
	.fn-idmain { align-self: center; }
	.fn-icon { width: 200px; height: 200px; flex-shrink: 0; }
	.fn-title h1 { font-size: 1.65rem; }
	.fn-meta { margin-top: 0.5rem; }}

/* Nexus's foot: the quiet links as a row of their own, then the facts. Lifting the links out of
   the action column is also what stops the column running two buttons taller than the identity. */
.fn-quiet { grid-area: quiet; min-width: 0; }
.fn-quiet .act-quiet { justify-content: center; margin: 0; }
@media (max-width: 900px) {
	.fn-quiet { margin-top: -1.5em; }
}
.fn-foot { margin-top: 1.25rem; }
.fn-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(115px, 1fr)); gap: 0.9rem 1.25rem; margin: 0; padding: 0.5rem 0; border-top: 1px solid var(--clr-border); }
.fn-stats > div { min-width: 0; }
.fn-stats dt { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--clr-text-muted); }
.fn-stats dd { margin: 0.2rem 0 0; font-size: 0.95rem; font-weight: 600; overflow-wrap: anywhere; }
.fn-stats .mod-stats { gap: 0; }
/* The star sits in a strip of plain values, so it matches their size and weight — but it is the one
   thing on the strip you can click, and stripping it to plain text said nothing about that. A quiet
   outline plus a gold star at rest reads as a control without going back to a filled button; hover
   and the starred state both warm the whole chip. */
.star-toggle--bare { padding: 0.1rem 0.6rem 0.1rem 0.5rem; border: 1px solid var(--clr-border); border-radius: 999px; background: none; font-size: 0.95rem; font-weight: 600; line-height: 1.5; color: var(--clr-text); gap: 0.35rem; transition: border-color 0.12s, color 0.12s, background 0.12s; }
.star-toggle--bare .star-icon { color: var(--clr-star); transition: color 0.12s; }
.star-toggle--bare:hover,
.star-toggle--bare:focus-visible { border-color: var(--clr-star); color: var(--clr-star); background: color-mix(in srgb, var(--clr-star) 10%, transparent); text-decoration: none; }
/* Starred sits a step warmer than hover, and the icon itself goes solid (stats.php swaps it), so
   "you can star this" and "you have starred this" never look the same. */
.star-toggle--bare.is-starred { border-color: var(--clr-star); color: var(--clr-star); background: color-mix(in srgb, var(--clr-star) 24%, transparent); }

/* The section bar leads the content, so the first thing under it is the images. */
.fn-jump { margin-top: 1rem; }
.fn-images { padding-top: 1rem; }

/* ── One image band ──────────────────────────────────────────────────────── */
/* Two containers, one strip: `display: contents` lets both sets lay out as siblings, while the
   author's gallery keeps sole ownership of #image-gallery for drag-to-reorder. */
.fn-media-strip { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 0.6rem; }
.fn-media-strip > .mod-image-gallery { display: contents; }
/* Both sets in one band means twice the thumbnails, so they tile at a uniform size instead of
   running at their natural widths — a ragged right edge with two-per-row was a wall to scroll past,
   not a band to glance at. The full image is one click away in the lightbox. */
.fn-media .gallery-item { height: clamp(94px, 11vw, 128px); width: auto; border-radius: var(--radius-small); overflow: hidden; position: relative; }
/* The author's own tiles are draggable — say so with the cursor, since nothing else does. */
.fn-media .mod-image-gallery[data-can-reorder="true"] .gallery-item { cursor: grab; }
.fn-media .mod-image-gallery[data-can-reorder="true"] .gallery-item.dragging { cursor: grabbing; opacity: 0.5; }
.fn-media-hint { display: flex; align-items: center; gap: 0.35rem; margin: 0.55rem 0 0; font-size: 0.8rem; color: var(--clr-text-muted); }
.fn-media .gallery-thumb { width: 100%; height: 100%; max-width: none; max-height: none; object-fit: cover; border-radius: var(--radius-small); cursor: zoom-in; }
/* Credit on the tile rather than in a hover tooltip, but as a caption on a scrim — legible over
   any screenshot without competing with it. */
.fn-media-credit { position: absolute; inset: auto 0 0 0; display: flex; align-items: center; gap: 0.3rem; padding: 0.9rem 0.5rem 0.3rem; background: linear-gradient(to top, rgba(0, 0, 0, 0.72), transparent); font-size: 0.72rem; font-weight: 600; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; pointer-events: none; }
.fn-media-credit svg { flex-shrink: 0; opacity: 0.85; }
/* On a phone the tiled band became ~1900px of screenshots to scroll past before the README, so it
   turns into one swipeable row — the same treatment the tab bar and thread filters get. */
@media (max-width: 767px) {
	.fn-media-strip { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: 72%; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; padding-bottom: 0.2rem; }
	.fn-media-strip::-webkit-scrollbar { display: none; }
	.fn-media .gallery-item { height: clamp(140px, 42vw, 200px); scroll-snap-align: start; }}
/* The last tile of a capped band carries the overflow count, and clicking it expands the band in
   place — it reads as "there is more here", not as that particular image. */
.fn-media .gallery-item.is-more { cursor: pointer; }
.fn-media .gallery-item.is-more::after { content: '+' attr(data-more); position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: color-mix(in srgb, var(--clr-bg) 72%, transparent); color: #fff; font-size: 1.35rem; font-weight: 700; letter-spacing: 0.02em; border-radius: var(--radius-small); pointer-events: none; }
.fn-media .gallery-item.is-more .fn-media-credit { display: none; }
.fn-media-uploads { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }
.fn-media .user-images-pending { margin-top: 1rem; }

#fn-compat .modl-card { padding: 0; }
/* ── Requirement rows, with Gale's one-click install ─────────────────────── */
.rr-group + .rr-group { border-top: 1px solid var(--clr-border); }
/* Each group is a collapsed <details>. The whole summary row is the hit target — a heading that
   only responds on the word itself is a control people miss. */
.rr-sum { display: flex; align-items: center; gap: 0.5rem; padding: 1rem 0.4rem; border-top: 1px solid var(--clr-border); margin-top: -1px; border-radius: var(--radius-large); cursor: pointer; list-style: none; }
.rr-group + .rr-group .rr-sum { border-radius: 0; }
.rr-sum::-webkit-details-marker { display: none; }
.rr-sum:hover { background: var(--clr-surface-alt); }
.rr-sum:focus-visible { outline: 2px solid var(--clr-link); outline-offset: 2px; }
.rr-chev { display: flex; flex-shrink: 0; color: var(--clr-text-muted); transition: transform 0.15s ease; }
.rr-group[open] > .rr-sum .rr-chev { transform: rotate(90deg); }
.rr-h { display: flex; align-items: center; gap: 0.4rem; margin: 0; flex-shrink: 0; font-size: 0.76rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em; color: var(--clr-text-muted); }
.rr-count { font-size: 0.72rem; padding: 0 0.4em; border-radius: 999px; background: var(--clr-surface-alt); border: 1px solid var(--clr-border); letter-spacing: normal; min-width: 1.7em; text-align: center; }
/* The note rides in the summary rather than under it, so a collapsed group still says what it is. */
.rr-note { margin: 0; min-width: 0; font-size: 0.85rem; color: var(--clr-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Under ~560px the label and count alone fill the row; the sentence would clip to two words. */
@media (max-width: 559px) { .rr-note { display: none; }}
.rr-group > .rr-rows { margin: 0 1.4rem 1.4rem; }
.rr-group:last-child:not([open]) > .rr-sum { border-bottom-left-radius: var(--radius-large); border-bottom-right-radius: var(--radius-large); }
.rr-rows { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.4rem; }
@media (min-width: 900px) { .rr-rows { grid-template-columns: repeat(auto-fill, minmax(22rem, 1fr)); gap: 0.4rem 1rem; }}
.rr-row { display: flex; align-items: center; gap: 0.7rem; min-width: 0; padding: 0.5rem; border: 1px solid var(--clr-border); border-radius: var(--radius-large); background: var(--clr-surface-alt); }
.rr-icon { width: 40px; height: 40px; aspect-ratio: 1/1; object-fit: cover; border-radius: var(--radius-small); flex-shrink: 0; background: var(--clr-surface); }
.rr-icon--none { display: flex; align-items: center; justify-content: center; color: var(--clr-text-muted); }
/* mod-layouts.js's broken-image fallback (any .rr-icon/.md-icon image that fails to load) swaps
   the <img> for a "?" <span> carrying its original class plus this one — kept from the removed
   Gale layout because the fallback script itself is still live and shared across layouts. */
.gl-rowicon--none { display: flex; align-items: center; justify-content: center; color: var(--clr-text-muted); font-size: 1.4rem; }
.rr-text { min-width: 0; flex: 1; display: flex; flex-direction: column; }
.rr-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rr-meta { font-size: 0.8rem; color: var(--clr-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rr-sep { color: var(--clr-border); margin: 0 0.25rem; }
.rr-group--conflict .rr-row { border-color: color-mix(in srgb, var(--clr-warning) 45%, var(--clr-border)); }
.rr-group--conflict .rr-name a { color: var(--clr-warning); }

/* ── Layout 21: the section bar on a phone ───────────────────────────────────
   A swipeable strip hid half its entries behind a gesture nothing announced, and the last chip was
   always clipped mid-word. It wraps instead: every section visible, nothing to scroll sideways,
   two short rows at 390px. */
@media (max-width: 767px) {
	.fn-jump { flex-wrap: wrap; gap: 0.3rem; overflow-x: visible; padding: 0.4rem; }
	.fn-jump a { flex: 1 1 auto; justify-content: center; padding: 0.4rem 0.55rem; font-size: 0.82rem; min-height: 38px; }}

/* ── Layout 21: a modpack's dependency list ──────────────────────────────────
   Ten rows is a section; a hundred is a page nobody scrolls past. Past the threshold the list gets
   a filter box and its own scroll area, inside the group's <details>. */
.rr-filter { position: relative; display: flex; margin-bottom: 0.6rem; max-width: 22rem; margin-left: 1.4rem; }
.rr-filter-ico { position: absolute; left: 0.6rem; top: 50%; transform: translateY(-50%); display: flex; color: var(--clr-text-muted); pointer-events: none; }
/* input[type=search] in style.css is (0,1,1) and was overriding the padding that keeps the text
   clear of the icon, so this has to match its specificity. */
input.rr-filter-input { width: 100%; min-width: 0; min-height: 38px; margin: 0; padding: 0.35rem 0.6rem 0.35rem 2.1rem; background: var(--clr-bg); border: 1px solid var(--clr-border); border-radius: var(--radius-small); color: var(--clr-text); font: inherit; font-size: 0.88rem; }
input.rr-filter-input::placeholder { color: var(--clr-text-muted); }
.rr-group--long .rr-rows {
	max-height: 24rem;
	overflow-y: auto;
	padding-right: 0.4rem;
	/* A scroll area needs an edge, or it reads as the section simply ending mid-row. */
	border: 1px solid var(--clr-border);
	border-radius: var(--radius-large);
	padding: 0.5rem;
	background: color-mix(in srgb, var(--clr-bg) 55%, transparent);
}
.rr-group--long .rr-row { background: var(--clr-surface); }
.rr-empty { margin: 0.6rem 0 0; color: var(--clr-text-muted); font-size: 0.88rem; }

/* ── Layout 21: optional decorative frame around the mod icon ────────────────
   Off unless a mod opts in. The frame is a separate layer sized larger than the icon and pinned
   behind nothing — it never covers the artwork, and it is inert to the pointer. */
/* The wrapper is the grid item, not the icon inside it — without the area (and without opting out
   of `stretch`) it auto-placed on a phone and the frame smeared across the whole column. */
.fn-iconwrap { grid-area: icon; justify-self: start; position: relative; display: inline-flex; flex-shrink: 0; line-height: 0; }
/* The frame sits tightly on the icon's edge, and the framed block keeps the same footprint as an
   unframed icon — growing the wrapper instead made a modpack's card a good 150px taller than every
   other page. So the wrapper is the icon's usual size, its padding is the overhang, and the icon
   fills what is left. An absolutely positioned child measures against the padding box, so the frame
   lands on that outer edge and its opening lands on the icon. --fn-frame-scale is measured off the
   art (see mod.php). */
.fn-iconwrap--framed { box-sizing: border-box; width: var(--fn-icon-size); height: var(--fn-icon-size); padding: calc((1 - 1 / var(--fn-frame-scale, 1.52)) / 2 * var(--fn-icon-size)); }
.fn-iconwrap--framed .fn-icon { width: 100%; height: 100%; }
.fn-iconwrap { --fn-icon-size: 64px; }
@media (min-width: 640px) { .fn-iconwrap { --fn-icon-size: 96px; }}
@media (min-width: 900px) { .fn-iconwrap { --fn-icon-size: 200px; }}
.fn-iconframe { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; pointer-events: none; z-index: 1; }
.fn-iconwrap--framed .fn-icon { border-radius: var(--radius-small); }

/* ── Stats / Source / Decompile as bare links rather than small buttons ────── */
.act-tier--links { flex-direction: row; flex-wrap: wrap; gap: 0.3rem 0.9rem; justify-content: center; padding-top: 0.15rem; }
.act-link--tertiary { display: inline-flex; align-items: center; gap: 0.3rem; padding: 0; margin: 0; min-height: 0; background: none; border: none; font: inherit; font-size: 0.85rem; font-weight: 500; color: var(--clr-link); cursor: pointer; text-decoration: none; }
.act-link--tertiary:hover { color: var(--clr-link-hover); text-decoration: underline; background: none; }

/* The optional half of "Client (& Server)", quieter so the line reads as one thing. */
.fn-loc-opt { color: var(--clr-text-muted); font-weight: 500; }

/* ── Colour, only where it carries meaning ────────────────────────────────────
   A marker per section heading, and the three compatibility groups in their own semantic
   colours — install these / optional / do not run these. */
.modl--final .op-h { display: flex; align-items: center; gap: 0.5rem; }
.modl--final .op-h::before { content: ''; width: 3px; height: 0.85rem; border-radius: 2px; background: var(--clr-link); opacity: 0.85; }
.modl--final #fn-compat .op-h::before { background: var(--clr-success); }
.modl--final #fn-changelog .op-h::before { background: var(--clr-accent-2, #0891b2); }
.modl--final #fn-faq .op-h::before { background: var(--clr-accent-1, #b45309); }
.modl--final #fn-threads .op-h::before { background: var(--clr-accent-3, #be185d); }
.modl--final #fn-images .op-h::before { background: var(--clr-accent-4, #1d4ed8); }

.modl--final .rr-group--required .rr-h { color: var(--clr-success); }
.modl--final .rr-group--required .rr-count { border-color: color-mix(in srgb, var(--clr-success) 45%, var(--clr-border)); }
.modl--final .rr-group--optional .rr-h { color: var(--clr-link); }
.modl--final .rr-group--optional .rr-count { border-color: color-mix(in srgb, var(--clr-link) 45%, var(--clr-border)); }
.modl--final .rr-group--conflict .rr-h { color: var(--clr-warning); }
.modl--final .rr-group--conflict .rr-count { border-color: color-mix(in srgb, var(--clr-warning) 45%, var(--clr-border)); }
/* A hairline of the group's colour rather than a full tint — enough to tell the three apart while
   scrolling, not enough to turn the section into a paint chart. */
.modl--final .rr-group--required .rr-row { border-left: 3px solid color-mix(in srgb, var(--clr-success) 55%, transparent); }
.modl--final .rr-group--optional .rr-row { border-left: 3px solid color-mix(in srgb, var(--clr-link) 55%, transparent); }
.modl--final .rr-group--conflict .rr-row { border-left: 3px solid color-mix(in srgb, var(--clr-warning) 60%, transparent); }

/* The fact strip picks up a faint wash so the card has a base rather than fading out. */
.modl--final .fn-foot { background: linear-gradient(to bottom, transparent, color-mix(in srgb, var(--clr-link) 5%, transparent)); border-radius: 0 0 var(--radius-large) var(--radius-large); margin-inline: -1rem; padding-inline: 1rem; padding-bottom: 0.35rem; }
@media (min-width: 768px) { .modl--final .fn-foot { margin-inline: -1.25rem; padding-inline: 1.25rem; }}

/* ── Manual download: this mod, or this mod and its requirements ─────────────
   The Gale button installs the whole tree in one click; this is the same coverage for someone
   downloading by hand, which is why the requirement rows no longer carry their own install button.
   Shaped after Gale's dialogs (Kesomannen/gale): choices first, then an info box with a coloured
   left bar for what the download cannot cover, then the file list — collapsed, because a modpack's
   is thirty rows and anything below it is never read. */
.md-dialog { max-width: 36rem; width: calc(100vw - 2rem); }
.md-body { padding: 1rem; display: flex; flex-direction: column; gap: 0.75rem; max-height: 70vh; overflow-y: auto; }
.md-choices { display: flex; flex-direction: column; gap: 0.5rem; }
.md-choice { display: flex; flex-direction: column; gap: 0.15rem; width: 100%; padding: 0.75rem 0.9rem; text-align: left; border: 1px solid var(--clr-border); border-radius: var(--radius-large); background: var(--clr-surface-alt); color: var(--clr-text); cursor: pointer; font: inherit; }
.md-choice:hover { border-color: var(--clr-link); text-decoration: none; }
.md-choice-head { display: flex; align-items: center; gap: 0.45rem; font-weight: 600; }
.md-choice-sub { font-size: 0.85rem; color: var(--clr-text-muted); }
.md-choice--all { border-color: var(--clr-link); }
.md-choice--all .md-choice-head { color: var(--clr-link); }

/* Gale's InfoBox: a bar of the severity's colour down the left edge, icon, then the text. */
.md-info { position: relative; display: flex; align-items: flex-start; gap: 0.55rem; padding: 0.7rem 0.8rem 0.7rem 1.1rem; overflow: hidden; border: 1px solid var(--clr-border); border-radius: var(--radius-large); background: var(--clr-surface-alt); font-size: 0.85rem; }
.md-info::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 5px; background: var(--clr-warning); }
.md-info-icon { display: flex; flex-shrink: 0; margin-top: 0.05rem; color: var(--clr-warning); }
.md-info-text { min-width: 0; }
.md-info-text strong { display: block; color: var(--clr-text); }
.md-missing code { font-size: 0.8rem; word-break: break-word; }

/* The file list, collapsed. Same summary idiom as the compatibility groups. */
.md-files { border: 1px solid var(--clr-border); border-radius: var(--radius-large); }
.md-files-sum { display: flex; align-items: center; gap: 0.5rem; padding: 0.6rem 0.7rem; cursor: pointer; list-style: none; font-weight: 600; font-size: 0.9rem; }
.md-files-sum::-webkit-details-marker { display: none; }
.md-files-sum:hover { color: var(--clr-link); }
.md-files-sum:focus-visible { outline: 2px solid var(--clr-link); outline-offset: -2px; }
.md-files[open] > .md-files-sum .rr-chev { transform: rotate(90deg); }
.md-files[open] > .md-files-sum { border-bottom: 1px solid var(--clr-border); }
/* No scroll area of its own — the dialog body is the one scroll container, or an expanded list
   leaves you dragging a 6-line viewport inside another scrollbar. */
.md-list { list-style: none; margin: 0; padding: 0.5rem; display: flex; flex-direction: column; gap: 0.4rem; }
/* Gale's ModCard: 48px icon, name with the version muted beside it, author underneath. */
.md-item { display: flex; align-items: center; gap: 0.7rem; min-width: 0; padding: 0.3rem 0.2rem; }
.md-icon { width: 48px; height: 48px; aspect-ratio: 1/1; object-fit: cover; border-radius: var(--radius-small); flex-shrink: 0; background: var(--clr-surface); }
.md-text { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 0.1rem; }
.md-name { display: flex; align-items: baseline; gap: 0.4rem; min-width: 0; font-weight: 600; }
.md-name > a, .md-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.md-ver { flex-shrink: 0; font-weight: 500; color: var(--clr-text-muted); }
.md-author { font-size: 0.8rem; color: var(--clr-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.md-self-tag { margin-left: 0.35rem; padding: 0 0.4em; border-radius: 999px; background: color-mix(in srgb, var(--clr-link) 15%, transparent); color: var(--clr-link); font-size: 0.72rem; font-weight: 600; }
/* Said out loud rather than silently substituted: the manifest asked for a version we do not have. */
.md-swap { margin-left: 0.35rem; padding: 0 0.35em; border-radius: 999px; border: 1px solid var(--clr-border); font-size: 0.72rem; }
.md-get { flex-shrink: 0; padding: 0.3rem 0.75rem; min-height: 32px; display: inline-flex; align-items: center; border: 1px solid var(--clr-border); border-radius: var(--radius-small); font-size: 0.8rem; font-weight: 600; color: var(--clr-link); }
.md-get:hover { border-color: var(--clr-link); background: var(--clr-link); color: var(--clr-on-link); text-decoration: none; }
.md-note { margin: 0; font-size: 0.82rem; color: var(--clr-text-muted); }
/* The fallback tile the JS swaps in keeps the row's icon footprint. */
.md-icon.gl-rowicon--none { border: 1px solid var(--clr-border); font-size: 1.2rem; }
/* Paired with the "+N" tile: the way back out of an expanded band. */
.fn-media-less { display: inline-flex; align-items: center; margin-top: 0.6rem; padding: 0.3rem 0.7rem; min-height: 32px; background: none; border: 1px solid var(--clr-border); border-radius: var(--radius-small); color: var(--clr-text-muted); font: inherit; font-size: 0.82rem; font-weight: 600; cursor: pointer; }
.fn-media-less:hover { border-color: var(--clr-link); color: var(--clr-link); }

#mod-new-thread-dialog { width: 96vw; }
#mod-new-thread-dialog .source-url-hint { margin-bottom: 0; }
#mod-new-thread-dialog textarea {
	max-height: calc(100vh - 16rem);
	/* Height is set from JS (mod-layouts.js) to match content as it's typed, up to the max-height
	   above — past that, it scrolls internally. A drag handle would fight the autogrow: the next
	   keystroke's height snaps straight back over any manual resize. */
	resize: none;
}
