MediaWiki:Common.css

From LinuxizeNet
Revision as of 20:25, 9 August 2026 by Datanasov (talk | contribs) (Timeless: recolour tricolour band and footer rule to the site palette)

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/* ============================================================================
 * MediaWiki:Common.css  —  wiki.linuxize.net
 * MediaWiki 1.41.5. Default skin: Timeless (since 2026-08-09).
 * Vector legacy is still selectable, so its rules are kept and scoped to
 * `body.skin-vector`.
 *
 * Loads via the `site.styles` module, after the skin's own styles, so
 * equal-specificity selectors win without !important. !important is used only
 * where it overrides an inline style attribute in page wikitext (section 9).
 *
 * Sections:
 *   1.  Tokens
 *   1b. TEMPORARY light-lock for Timeless (delete when dark chrome exists)
 *   2.  Vector legacy chrome            <- inert under Timeless
 *   3.  Vector legacy responsive layout <- scoped to body.skin-vector
 *   4.  Content typography
 *   5.  Code blocks (SyntaxHighlight / Pygments)
 *   6.  TOC
 *   7.  Tables
 *   8.  Card grids (index pages)
 *   9.  Legacy inline-style box neutraliser
 *  10.  Print
 * ========================================================================= */

/* ---------------------------------------------------------------------------
 * 1. TOKENS
 * Light is the base; the two dark blocks redefine tokens only.
 *
 * Any change to a colour here must be applied in FOUR places or the themes
 * drift apart: :root, the prefers-color-scheme block, the [data-theme="dark"]
 * block, and the Timeless light-lock in 1b. There is a parity check for this
 * in the README.
 * ------------------------------------------------------------------------ */
:root {
	--lz-ground:      #faf7f1;
	--lz-surface:     #ffffff;
	--lz-surface-2:   #f2ebdf;
	--lz-ink:         #201b14;
	--lz-ink-2:       #574d40;
	--lz-ink-3:       #8b7f6d;
	--lz-line:        #e4dbc9;
	--lz-line-strong: #cfc2aa;
	--lz-accent:      #8a5b12;
	--lz-accent-hov:  #6d4709;
	--lz-accent-tint: #f3e7ce;
	--lz-visited:     #6b4a7a;
	--lz-red:         #a12f2f;

	/* Timeless draws a red/blue/green tricolour under the header and a teal
	 * rule above the footer. Recoloured here into a warm ramp from the site
	 * palette — the device is kept, the clashing hues are not. */
	--lz-band-1: #7a4e0e;
	--lz-band-2: #a9752a;
	--lz-band-3: #c9a45c;
	--lz-band-rule: #a9752a;

	/* Code panel — a warm tint that belongs to the page, not a black slab
	 * dropped onto it. Sits just below the white content surface so the panel
	 * reads as inset without fighting the cream ground. */
	--lz-code-bg:      #f6f0e5;
	--lz-code-bg-2:    #ebe1cd;
	--lz-code-ink:     #2a2318;
	--lz-code-line:    #e0d5be;
	--lz-code-chrome:  #665d4d;
	--lz-code-chrome-hover-bg:  #e3d8c2;
	--lz-code-chrome-hover-ink: #2a2318;
	--lz-code-ok:      #4a6a1f;
	--lz-code-ok-line: #8fa565;
	--lz-code-link:       #8a5b12;
	--lz-code-link-hover: #6d4709;

	/* Syntax inks. Dark on light here; the dark blocks below invert them.
	 * Contrast against --lz-code-bg is measured in the browser after any
	 * change to these — see the note above section 5. */
	--lz-syn-comment: #6f6552;
	--lz-syn-keyword: #96540a;
	--lz-syn-builtin: #7a520f;
	--lz-syn-var:     #1a5570;
	--lz-syn-string:  #46661d;
	--lz-syn-op:      #a04a18;
	--lz-syn-punct:   #6b6152;
	--lz-syn-num:     #a04a18;
	--lz-syn-err:     #a12f2f;

	--lz-shadow: 0 1px 2px rgba( 32, 27, 20, 0.05 ), 0 8px 24px -12px rgba( 32, 27, 20, 0.18 );

	--lz-mono: ui-monospace, "SF Mono", SFMono-Regular, "JetBrains Mono", Menlo, Consolas, "Liberation Mono", monospace;
	--lz-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

@media ( prefers-color-scheme: dark ) {
	:root:not( [ data-theme="light" ] ) {
		--lz-ground:      #14110c;
		--lz-surface:     #1b1711;
		--lz-surface-2:   #231e16;
		--lz-ink:         #ece5d8;
		--lz-ink-2:       #b3a894;
		--lz-ink-3:       #877c6a;
		--lz-line:        #322b21;
		--lz-line-strong: #4a4133;
		--lz-accent:      #dda94d;
		--lz-accent-hov:  #f0c273;
		--lz-accent-tint: #2c2417;
		--lz-visited:     #c3a0d4;
		--lz-red:         #e08585;
		--lz-shadow: 0 1px 2px rgba( 0, 0, 0, 0.4 ), 0 8px 24px -12px rgba( 0, 0, 0, 0.7 );

		--lz-band-1: #e0b45e;
		--lz-band-2: #b78a35;
		--lz-band-3: #7d5f22;
		--lz-band-rule: #b78a35;

		/* The code panel sinks BELOW the surface here. Two dark surfaces this
		 * close together only separate by ~1.1:1, so the border and the
		 * header strip carry the delineation, not the fill.
		 * Keep every value here identical to the [data-theme="dark"] block
		 * below — a viewer on system-dark never stamps the attribute. */
		--lz-code-bg:      #0c0a06;
		--lz-code-bg-2:    #171208;
		--lz-code-ink:     #e9e1d2;
		--lz-code-line:    #3d3323;
		--lz-code-chrome:  #9c8f79;
		--lz-code-chrome-hover-bg:  #2e281d;
		--lz-code-chrome-hover-ink: #e9e1d2;
		--lz-code-ok:      #b8c98a;
		--lz-code-ok-line: #4d5a35;
		--lz-code-link:       #e6bd6d;
		--lz-code-link-hover: #f5d79b;

		--lz-syn-comment: #7d7263;
		--lz-syn-keyword: #dda94d;
		--lz-syn-builtin: #e6bd6d;
		--lz-syn-var:     #8fc0d6;
		--lz-syn-string:  #b8c98a;
		--lz-syn-op:      #d98e5a;
		--lz-syn-punct:   #a2947e;
		--lz-syn-num:     #d98e5a;
		--lz-syn-err:     #e08585;
	}
}

/* Explicit choice, set by the toggle in Common.js. Wins over the OS in both
 * directions because it is stamped on <html> and matches on attribute. */
:root[ data-theme="dark" ] {
	--lz-ground:      #14110c;
	--lz-surface:     #1b1711;
	--lz-surface-2:   #231e16;
	--lz-ink:         #ece5d8;
	--lz-ink-2:       #b3a894;
	--lz-ink-3:       #877c6a;
	--lz-line:        #322b21;
	--lz-line-strong: #4a4133;
	--lz-accent:      #dda94d;
	--lz-accent-hov:  #f0c273;
	--lz-accent-tint: #2c2417;
	--lz-visited:     #c3a0d4;
	--lz-red:         #e08585;
	--lz-shadow: 0 1px 2px rgba( 0, 0, 0, 0.4 ), 0 8px 24px -12px rgba( 0, 0, 0, 0.7 );
	--lz-band-1: #e0b45e;
	--lz-band-2: #b78a35;
	--lz-band-3: #7d5f22;
	--lz-band-rule: #b78a35;

	/* Must stay identical to the prefers-color-scheme block above. */
	--lz-code-bg:      #0c0a06;
	--lz-code-bg-2:    #171208;
	--lz-code-ink:     #e9e1d2;
	--lz-code-line:    #3d3323;
	--lz-code-chrome:  #9c8f79;
	--lz-code-chrome-hover-bg:  #2e281d;
	--lz-code-chrome-hover-ink: #e9e1d2;
	--lz-code-ok:      #b8c98a;
	--lz-code-ok-line: #4d5a35;
	--lz-code-link:       #e6bd6d;
	--lz-code-link-hover: #f5d79b;

	--lz-syn-comment: #7d7263;
	--lz-syn-keyword: #dda94d;
	--lz-syn-builtin: #e6bd6d;
	--lz-syn-var:     #8fc0d6;
	--lz-syn-string:  #b8c98a;
	--lz-syn-op:      #d98e5a;
	--lz-syn-punct:   #a2947e;
	--lz-syn-num:     #d98e5a;
	--lz-syn-err:     #e08585;
}

/* ---------------------------------------------------------------------------
 * 1b. TEMPORARY: force the light palette under Timeless.
 *
 * Timeless's chrome (header bar, tab strip, both sidebars, portlet headings)
 * carries its own hardcoded light palette. The dark tokens above only ever
 * covered content and the footer, so under Timeless dark mode produced 32
 * elements below 3:1 — measured 2026-08-09, several at 1.18:1.
 *
 * That is not opt-in: the theme toggle in Common.js attaches to a Vector-only
 * element and never renders under Timeless, so dark was reachable ONLY via
 * prefers-color-scheme — automatic, and with no way for a visitor to escape it.
 *
 * Custom properties inherit, so redeclaring them on <body> beats the :root
 * definitions for everything inside. Vector keeps working dark.
 *
 * DELETE THIS BLOCK once the Timeless dark chrome is written.
 * ------------------------------------------------------------------------ */
body.skin-timeless {
	--lz-ground:      #faf7f1;
	--lz-surface:     #ffffff;
	--lz-surface-2:   #f2ebdf;
	--lz-ink:         #201b14;
	--lz-ink-2:       #574d40;
	--lz-ink-3:       #8b7f6d;
	--lz-line:        #e4dbc9;
	--lz-line-strong: #cfc2aa;
	--lz-accent:      #8a5b12;
	--lz-accent-hov:  #6d4709;
	--lz-accent-tint: #f3e7ce;
	--lz-visited:     #6b4a7a;
	--lz-red:         #a12f2f;

	--lz-band-1: #7a4e0e;
	--lz-band-2: #a9752a;
	--lz-band-3: #c9a45c;
	--lz-band-rule: #a9752a;

	--lz-code-bg:      #f6f0e5;
	--lz-code-bg-2:    #ebe1cd;
	--lz-code-ink:     #2a2318;
	--lz-code-line:    #e0d5be;
	--lz-code-chrome:  #665d4d;
	--lz-code-chrome-hover-bg:  #e3d8c2;
	--lz-code-chrome-hover-ink: #2a2318;
	--lz-code-ok:      #4a6a1f;
	--lz-code-ok-line: #8fa565;
	--lz-code-link:       #8a5b12;
	--lz-code-link-hover: #6d4709;

	--lz-syn-comment: #6f6552;
	--lz-syn-keyword: #96540a;
	--lz-syn-builtin: #7a520f;
	--lz-syn-var:     #1a5570;
	--lz-syn-string:  #46661d;
	--lz-syn-op:      #a04a18;
	--lz-syn-punct:   #6b6152;
	--lz-syn-num:     #a04a18;
	--lz-syn-err:     #a12f2f;

	--lz-shadow: 0 1px 2px rgba( 32, 27, 20, 0.05 ), 0 8px 24px -12px rgba( 32, 27, 20, 0.18 );
}

/* ---------------------------------------------------------------------------
 * 2. VECTOR LEGACY CHROME
 * Vector 2010 hardcodes a blue/grey palette and positions #mw-panel
 * absolutely at 10em. Re-ground it, then unpick the fixed widths in §3.
 * ------------------------------------------------------------------------ */
body {
	background-color: var( --lz-ground );
	color: var( --lz-ink );
	font-family: var( --lz-sans );
	font-size: 0.9375rem;
	line-height: 1.65;
}

/* The gradient strip behind the tab row. */
#mw-page-base {
	background-color: var( --lz-ground );
	background-image: none;
	height: 3.5em;
}

#mw-head-base {
	background: transparent;
}

/* Main content column — colours only, safe under any skin. */
#content.mw-body {
	background: var( --lz-surface );
	color: var( --lz-ink );
	font-size: 1rem;
}

/* Layout below is Vector-legacy-specific and must stay scoped to it.
 * Vector legacy pins #content at margin-left:10em and lets it run to the
 * viewport edge, so code blocks stretch past 1400px on a wide monitor; the
 * max() caps the measure and centres it without encroaching on the sidebar
 * rail. Timeless lays out its own content container, so applying this there
 * nests a second bordered box inside the first and double-indents it. */
body.skin-vector #content.mw-body {
	border: 1px solid var( --lz-line );
	border-radius: 0.5rem;
	padding: 1.75em 2em 2em;
	margin-top: 0;
	margin-left: max( 10em, calc( ( 100% - 64rem ) / 2 ) );
	margin-right: 1em;
	max-width: 64rem;
}

body.skin-vector #footer {
	margin-left: max( 10em, calc( ( 100% - 64rem ) / 2 ) );
	margin-right: 1em;
	max-width: 64rem;
}

/* --- Timeless accent bands ---
 * Timeless ships a red / blue / green tricolour strip under the header
 * (three stacked divs inside #mw-header-hack and .color-bar) and a teal rule
 * above the footer on #mw-content-container. Against a warm amber palette
 * those three hues read as someone else's brand. Recoloured into a warm ramp,
 * deep to light, left to right: the structural device survives, the clash
 * does not.
 *
 * Only border-*-color is set on the tab underline, never border-width, so the
 * broad `li.selected` selector cannot accidentally draw a border on a list
 * item in article content. */
body.skin-timeless .color-left {
	background-color: var( --lz-band-1 );
}

body.skin-timeless .color-middle {
	background-color: var( --lz-band-2 );
}

body.skin-timeless .color-right {
	background-color: var( --lz-band-3 );
}

body.skin-timeless #mw-content-container {
	border-bottom-color: var( --lz-band-rule );
}

body.skin-timeless li.selected {
	border-bottom-color: var( --lz-accent );
}

/* --- Timeless footer ---
 * Timeless paints its footer as white text on its own dark ground. The `body`
 * background token above replaces that ground with cream, which left white on
 * cream at 1.07:1 — invisible. Repaint the whole footer from our tokens.
 * Measured after the fix: body text 6.98:1, links 4.94:1 — both pass AA.
 * (Provisional — the proper Timeless port lands with the rest of the chrome.) */
body.skin-timeless #mw-footer,
body.skin-timeless #mw-footer-container {
	background: var( --lz-surface-2 );
	color: var( --lz-ink-2 );
	border-top: 1px solid var( --lz-line );
}

body.skin-timeless #mw-footer li,
body.skin-timeless #mw-footer #footer-info li,
body.skin-timeless #mw-footer #footer-places li {
	color: var( --lz-ink-2 );
}

body.skin-timeless #mw-footer a {
	color: var( --lz-accent );
}

body.skin-timeless #mw-footer a:hover {
	color: var( --lz-accent-hov );
}

a,
.mw-body a {
	color: var( --lz-accent );
	text-decoration-color: rgba( 138, 91, 18, 0.35 );
	text-underline-offset: 0.15em;
}

a:hover,
.mw-body a:hover {
	color: var( --lz-accent-hov );
	text-decoration-color: currentColor;
}

.mw-body a:visited {
	color: var( --lz-visited );
}

.mw-body a.new,
a.new {
	color: var( --lz-red );
}

a.external,
.mw-body a.external {
	background-image: none;
	padding-right: 0;
}

/* External links get a typographic marker instead of the sprite, which does
 * not exist in a dark palette. */
.mw-parser-output a.external::after {
	content: " \2197";
	font-size: 0.85em;
	color: var( --lz-ink-3 );
}

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

/* --- left sidebar --- */
#mw-panel.vector-legacy-sidebar {
	padding-top: 1em;
}

#mw-panel .vector-menu-portal .vector-menu-heading {
	font-family: var( --lz-mono );
	font-size: 0.68rem;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var( --lz-ink-3 );
	background: none;
	border-bottom: 0;
	padding-bottom: 0.4em;
}

#mw-panel .vector-menu-portal .vector-menu-content-list li a {
	display: block;
	padding: 0.25em 0.6em;
	border-left: 2px solid transparent;
	border-radius: 0.3rem;
	color: var( --lz-ink-2 );
	font-size: 0.8125rem;
}

#mw-panel .vector-menu-portal .vector-menu-content-list li a:hover {
	background: var( --lz-surface-2 );
	color: var( --lz-ink );
	text-decoration: none;
}

#mw-panel .vector-menu-portal .vector-menu-content-list li a:visited {
	color: var( --lz-ink-2 );
}

/* --- top tabs (Page / Discussion / Read / Edit / History) --- */
/* Vector legacy draws these with a sprite; replace with flat shapes so they
 * survive a dark ground. */
#mw-head .vector-menu-tabs,
#mw-head .vector-menu-tabs ul,
#mw-head .vector-menu-tabs li,
#mw-head .vector-menu-tabs li.selected {
	background-image: none;
}

#mw-head .vector-menu-tabs li {
	background: transparent;
}

#mw-head .vector-menu-tabs li a,
#mw-head .vector-menu-tabs li.selected a {
	font-family: var( --lz-mono );
	font-size: 0.75rem;
	letter-spacing: 0.02em;
	color: var( --lz-ink-3 );
	background: transparent;
	padding: 0 0.9em;
}

#mw-head .vector-menu-tabs li a:hover {
	color: var( --lz-accent );
}

#mw-head .vector-menu-tabs li.selected a,
#mw-head .vector-menu-tabs li.selected a:visited {
	color: var( --lz-ink );
	font-weight: 600;
	box-shadow: inset 0 -2px 0 var( --lz-accent );
}

#p-personal .vector-menu-content-list li a {
	font-family: var( --lz-mono );
	font-size: 0.72rem;
	color: var( --lz-ink-3 );
}

#p-personal .vector-menu-content-list li a:hover {
	color: var( --lz-accent );
}

/* --- search --- */
#p-search .vector-search-box-inner input,
#simpleSearch #searchInput {
	background: var( --lz-surface-2 );
	border: 1px solid var( --lz-line );
	border-radius: 0.35rem;
	color: var( --lz-ink );
	font-family: var( --lz-mono );
	font-size: 0.8rem;
	padding: 0.35em 0.6em;
}

#simpleSearch #searchInput::placeholder {
	color: var( --lz-ink-3 );
}

/* --- theme toggle, injected by Common.js --- */
.lz-theme-toggle {
	display: inline-flex;
	align-items: center;
	gap: 0.35em;
	padding: 0.15em 0.55em;
	background: transparent;
	border: 1px solid var( --lz-line );
	border-radius: 0.3rem;
	color: var( --lz-ink-2 );
	font-family: var( --lz-mono );
	font-size: 0.72rem;
	cursor: pointer;
}

.lz-theme-toggle:hover {
	color: var( --lz-accent );
	border-color: var( --lz-line-strong );
}

/* --- footer --- */
#footer {
	border-top: 1px solid var( --lz-line );
	margin-top: 2rem;
	padding-top: 1rem;
}

#footer li,
#footer a {
	font-family: var( --lz-mono );
	font-size: 0.72rem;
	color: var( --lz-ink-3 );
}

#footer #footer-icons {
	filter: grayscale( 1 ) opacity( 0.6 );
}

/* --- category links --- */
.catlinks {
	background: var( --lz-surface-2 );
	border: 1px solid var( --lz-line );
	border-radius: 0.4rem;
	padding: 0.6em 0.9em;
	font-size: 0.85rem;
}

.catlinks a {
	font-family: var( --lz-mono );
	font-size: 0.8rem;
}

/* ---------------------------------------------------------------------------
 * 3. RESPONSIVE LAYOUT
 *
 * NOTE: these queries do nothing on phones until the skin stops emitting
 * <meta name="viewport" content="width=1000">. Fix that with either
 *   $wgVectorResponsive = true;   in LocalSettings.php   (preferred), or
 *   the viewport patch at the top of Common.js            (no server access).
 * ------------------------------------------------------------------------ */
@media screen and ( max-width: 850px ) {
	/* SCOPED TO VECTOR LEGACY. Timeless is responsive on its own; turning its
	 * <body> into a flex column and reassigning order to every child would
	 * wreck its layout. Selectors below that exist only in Vector legacy
	 * (#mw-navigation, #mw-panel, #mw-head, #mw-page-base, #left-navigation,
	 * #right-navigation) are inert under Timeless and left unscoped; the ones
	 * that also match in Timeless are scoped explicitly.
	 *
	 * Vector legacy's source order is #content, then #mw-navigation, then
	 * #footer, and it positions the nav absolutely on top. Unpinning alone
	 * drops the whole navigation below the article and leaves #p-personal
	 * overlapping the page title. Make <body> a flex column instead and
	 * reorder, which is the only way to get nav above content without
	 * touching the skin's HTML. */
	body.skin-vector {
		display: flex;
		flex-direction: column;
	}

	body.skin-vector > * {
		order: 5;
	}

	#mw-navigation {
		order: 1;
	}

	body.skin-vector #content.mw-body {
		order: 2;
	}

	body.skin-vector #footer {
		order: 3;
	}

	/* Decorative strips that only exist to sit behind the absolute header. */
	#mw-page-base,
	#mw-head-base {
		display: none;
	}

	/* Unpin the header and the personal bar.
	 * flow-root is load-bearing: #left-navigation and #right-navigation are
	 * floats, and #mw-panel below becomes a flex container — i.e. a new block
	 * formatting context — so it shifts sideways to dodge those floats unless
	 * #mw-head contains them. Without this the whole sidebar renders inset
	 * about 235px from the left. */
	#mw-head {
		position: static;
		width: auto;
		float: none;
		display: flow-root;
		margin: 0.5em 0 0;
		padding: 0 0.75em;
	}

	body.skin-vector #p-personal {
		position: static;
		width: auto;
	}

	body.skin-vector #p-personal .vector-menu-content-list {
		display: flex;
		flex-wrap: wrap;
		gap: 0 0.9em;
		padding: 0;
		margin: 0;
	}

	body.skin-vector #p-personal .vector-menu-content-list li {
		margin: 0;
	}

	#left-navigation,
	#right-navigation {
		float: none;
		margin-left: 0;
	}

	body.skin-vector #p-search {
		float: none;
		margin: 0.5em 0;
	}

	body.skin-vector #simpleSearch,
	body.skin-vector #p-search .vector-search-box-inner input {
		width: 100%;
	}

	/* Sidebar collapses to one compact row of links under the header.
	 * At 375px tall the full desktop sidebar pushed the article entirely
	 * below the fold, so Tools is dropped here — it is editor plumbing
	 * (What links here, Upload file, Cite this page), not reader navigation,
	 * and it stays available on desktop. */
	#mw-panel.vector-legacy-sidebar {
		position: static;
		width: auto;
		clear: both;
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		gap: 0 1rem;
		margin: 0.4em 0 0;
		padding: 0.5em 0.75em 0.6em;
		border-top: 1px solid var( --lz-line );
	}

	#mw-panel #p-tb {
		display: none;
	}

	#mw-panel .vector-menu-portal {
		margin: 0;
		flex: 0 1 auto;
	}

	#mw-panel .vector-menu-portal .vector-menu-heading {
		display: none;
	}

	#mw-panel .vector-menu-portal .vector-menu-content {
		margin: 0;
		padding: 0;
	}

	#mw-panel .vector-menu-content-list {
		display: flex;
		flex-wrap: wrap;
		gap: 0 0.25rem;
		margin: 0;
		padding: 0;
	}

	#mw-panel .vector-menu-portal .vector-menu-content-list li {
		margin: 0;
	}

	/* The 160px Tux is a desktop luxury; keep a small mark as the home link. */
	#mw-panel #p-logo,
	#mw-panel #p-logo a {
		width: 2rem;
		height: 2rem;
		min-height: 0;
		margin: 0;
		background-size: contain;
		background-repeat: no-repeat;
		background-position: left center;
	}

	body.skin-vector #content.mw-body,
	body.skin-vector #footer {
		margin-left: 0.75em;
		margin-right: 0.75em;
		max-width: none;
		border-radius: 0.5rem;
		padding: 1.25em 1.1em 1.75em;
	}

	/* Long unbreakable paths and commands must not widen the page. */
	.mw-parser-output {
		overflow-wrap: break-word;
	}
}

@media screen and ( max-width: 550px ) {
	#content.mw-body {
		padding: 1em 0.85em 1.5em;
	}

	.mw-parser-output .mw-highlight pre {
		font-size: 0.75rem;
	}
}

/* ---------------------------------------------------------------------------
 * 4. CONTENT TYPOGRAPHY
 * Monospace for headings — this wiki's subject matter is commands, and the
 * mono display voice ties the page to the code blocks it is wrapped around.
 * ------------------------------------------------------------------------ */
#firstHeading,
.mw-body h1,
.mw-body h2,
.mw-body h3,
.mw-body h4 {
	font-family: var( --lz-mono );
	font-weight: 600;
	letter-spacing: -0.015em;
	line-height: 1.25;
	text-wrap: balance;
	color: var( --lz-ink );
}

#firstHeading {
	font-size: clamp( 1.6rem, 1.2rem + 1.6vw, 2.2rem );
	border-bottom: 0;
	padding-bottom: 0;
	margin-bottom: 0.15em;
}

/* Vector legacy puts the tagline directly under the title. */
#siteSub {
	display: block;
	font-family: var( --lz-mono );
	font-size: 0.72rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var( --lz-ink-3 );
	margin-bottom: 1.5em;
	padding-bottom: 1em;
	border-bottom: 1px solid var( --lz-line );
}

.mw-body h2 {
	font-size: 1.3rem;
	margin-top: 2.2em;
	padding-bottom: 0.3em;
	border-bottom: 1px solid var( --lz-line );
}

.mw-body h3 {
	font-size: 1.06rem;
	margin-top: 1.9em;
}

.mw-body h4 {
	font-size: 0.95rem;
	margin-top: 1.6em;
	color: var( --lz-ink-2 );
}

/* Headings need to clear the sticky-ish header when jumped to from the TOC. */
.mw-parser-output :is( h2, h3, h4 )[ id ],
.mw-parser-output .mw-headline {
	scroll-margin-top: 1.5rem;
}

.mw-editsection {
	font-family: var( --lz-mono );
	font-size: 0.7rem;
	font-weight: 400;
	color: var( --lz-ink-3 );
}

.mw-editsection a {
	color: var( --lz-ink-3 );
}

.mw-editsection a:hover {
	color: var( --lz-accent );
}

/* Hold running prose near a 68ch measure. Code, tables and card grids opt
 * out below so they can use the full column. */
.mw-parser-output > p,
.mw-parser-output > ul,
.mw-parser-output > ol,
.mw-parser-output > dl {
	max-width: 68ch;
}

.mw-parser-output p {
	margin: 0.85em 0;
}

.mw-parser-output li {
	margin-bottom: 0.3em;
}

.mw-parser-output li::marker {
	color: var( --lz-ink-3 );
}

.mw-parser-output hr {
	border: 0;
	border-top: 1px solid var( --lz-line );
	margin: 2em 0;
}

.mw-parser-output blockquote {
	margin: 1.2em 0;
	padding: 0.1em 0 0.1em 1em;
	border-left: 3px solid var( --lz-line-strong );
	color: var( --lz-ink-2 );
}

/* Inline code — distinct from the dark block panels. */
.mw-parser-output code,
.mw-parser-output tt,
.mw-parser-output kbd,
.mw-parser-output samp {
	font-family: var( --lz-mono );
	font-size: 0.875em;
	padding: 0.12em 0.35em;
	background: var( --lz-surface-2 );
	border: 1px solid var( --lz-line );
	border-radius: 0.25rem;
	color: var( --lz-ink );
	overflow-wrap: break-word;
}

/* ---------------------------------------------------------------------------
 * 5. CODE BLOCKS — SyntaxHighlight (Pygments) is already installed, so the
 * token spans below already exist in the rendered HTML.
 * Panels are dark in both themes; commands are the most scannable thing on
 * the page and the palette does not have to be maintained twice.
 * ------------------------------------------------------------------------ */
.mw-parser-output .mw-highlight {
	position: relative;
	margin: 1.2em 0;
	background: var( --lz-code-bg );
	border: 1px solid var( --lz-code-line );
	border-radius: 0.45rem;
	overflow: hidden;
}

.mw-parser-output .mw-highlight pre {
	margin: 0;
	padding: 0.85em 1em;
	overflow-x: auto;
	background: transparent;
	border: 0;
	color: var( --lz-code-ink );
	font-family: var( --lz-mono );
	font-size: 0.82rem;
	line-height: 1.65;
	tab-size: 4;
}

/* Language chip + copy button are injected by Common.js. */
.mw-parser-output .mw-highlight .lz-chead {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: 0.35em 0.4em 0.35em 0.8em;
	background: var( --lz-code-bg-2 );
	border-bottom: 1px solid var( --lz-code-line );
}

.lz-lang {
	font-family: var( --lz-mono );
	font-size: 0.68rem;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var( --lz-code-chrome );
}

.lz-copy {
	padding: 0.2em 0.6em;
	background: transparent;
	border: 1px solid var( --lz-code-line );
	border-radius: 0.25rem;
	color: var( --lz-code-chrome );
	font-family: var( --lz-mono );
	font-size: 0.68rem;
	letter-spacing: 0.04em;
	cursor: pointer;
}

.lz-copy:hover {
	background: var( --lz-code-chrome-hover-bg );
	border-color: var( --lz-line-strong );
	color: var( --lz-code-chrome-hover-ink );
}

.lz-copy.lz-done {
	color: var( --lz-code-ok );
	border-color: var( --lz-code-ok-line );
}

/* Pygments token palette — warm-dominant, one cool hue for variables.
 * Theme-aware: these were hardcoded for a dark ground back when the panel was
 * dark in both themes. Now the light theme uses a warm tint that belongs to
 * the page, so the inks invert with it. Measured contrast against the panel
 * ground is recorded in the README; re-measure after changing any of them. */
.mw-highlight .c,
.mw-highlight .c1,
.mw-highlight .cm,
.mw-highlight .cp {
	color: var( --lz-syn-comment );
	font-style: italic;
}

.mw-highlight .k,
.mw-highlight .kd,
.mw-highlight .kn,
.mw-highlight .kt {
	color: var( --lz-syn-keyword );
}

.mw-highlight .nb,
.mw-highlight .nf,
.mw-highlight .nc {
	color: var( --lz-syn-builtin );
}

.mw-highlight .nv,
.mw-highlight .vi,
.mw-highlight .na {
	color: var( --lz-syn-var );
}

.mw-highlight .s,
.mw-highlight .s1,
.mw-highlight .s2,
.mw-highlight .sb,
.mw-highlight .se {
	color: var( --lz-syn-string );
}

.mw-highlight .o,
.mw-highlight .ow {
	color: var( --lz-syn-op );
}

.mw-highlight .p {
	color: var( --lz-syn-punct );
}

.mw-highlight .m,
.mw-highlight .mi,
.mw-highlight .mf {
	color: var( --lz-syn-num );
}

.mw-highlight .w {
	color: inherit;
}

.mw-highlight .err {
	color: var( --lz-syn-err );
	background: transparent;
}

/* Unhighlighted <pre> (no lang= given, or a leading-space block in wikitext)
 * gets the same panel treatment. Deliberately a descendant selector, not a
 * child one — several pages nest these inside a wrapper div. The
 * .mw-parser-output .mw-highlight pre rule above is more specific, so
 * highlighted blocks keep their transparent inner background. */
.mw-parser-output pre {
	background: var( --lz-code-bg );
	border: 1px solid var( --lz-code-line );
	border-radius: 0.45rem;
	color: var( --lz-code-ink );
	font-family: var( --lz-mono );
	font-size: 0.82rem;
	line-height: 1.65;
	padding: 0.85em 1em;
	overflow-x: auto;
}

/* Some index pages use a leading-space block as a link container, so links
 * have to stay legible against the dark panel in both themes. */
.mw-parser-output pre a,
.mw-parser-output pre a:visited {
	color: var( --lz-code-link );
}

.mw-parser-output pre a:hover {
	color: var( --lz-code-link-hover );
}

.mw-parser-output pre a.new {
	color: var( --lz-syn-err );
}

/* ---------------------------------------------------------------------------
 * 6. TOC
 * The floating bordered box becomes a quiet block with mono numbering.
 * ------------------------------------------------------------------------ */
.mw-parser-output #toc,
.mw-parser-output .toc {
	display: block;
	max-width: 68ch;
	background: var( --lz-surface-2 );
	border: 1px solid var( --lz-line );
	border-radius: 0.45rem;
	padding: 0.9em 1.1em;
	font-size: 0.9rem;
}

.mw-parser-output .toctitle h2,
.mw-parser-output #toc h2 {
	font-family: var( --lz-mono );
	font-size: 0.7rem;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var( --lz-ink-3 );
	border-bottom: 0;
	margin: 0 0 0.5em;
	padding: 0;
}

.mw-parser-output #toc ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

.mw-parser-output #toc ul ul {
	margin-left: 1em;
}

.mw-parser-output #toc li {
	margin-bottom: 0.15em;
}

.mw-parser-output #toc a {
	text-decoration: none;
	color: var( --lz-ink-2 );
}

.mw-parser-output #toc a:hover {
	color: var( --lz-accent );
	text-decoration: underline;
}

.mw-parser-output #toc .tocnumber {
	font-family: var( --lz-mono );
	font-size: 0.78rem;
	color: var( --lz-ink-3 );
	margin-right: 0.3em;
}

/* ---------------------------------------------------------------------------
 * 7. TABLES
 * ------------------------------------------------------------------------ */
.mw-parser-output table.wikitable {
	background: var( --lz-surface );
	color: var( --lz-ink );
	border: 1px solid var( --lz-line );
	border-collapse: collapse;
	border-radius: 0.45rem;
	margin: 1.2em 0;
	font-size: 0.9rem;
	font-variant-numeric: tabular-nums;
	overflow: hidden;
}

.mw-parser-output table.wikitable > * > tr > th,
.mw-parser-output table.wikitable > * > tr > td {
	border: 0;
	border-bottom: 1px solid var( --lz-line );
	padding: 0.5em 0.85em;
	text-align: left;
}

.mw-parser-output table.wikitable > * > tr > th {
	background: var( --lz-surface-2 );
	font-family: var( --lz-mono );
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var( --lz-ink-2 );
	white-space: nowrap;
}

.mw-parser-output table.wikitable > * > tr:last-child > td {
	border-bottom: 0;
}

/* Wide tables scroll inside their own container, never the page body.
 * Wrap the table in <div class="lz-scroll"> ... </div> in wikitext. */
.lz-scroll {
	overflow-x: auto;
	max-width: 100%;
}

/* ---------------------------------------------------------------------------
 * 8. CARD GRIDS — index pages
 *
 * Two levels of adoption:
 *   (a) Template:Card  ->  .lz-card with a description and a command chip.
 *   (b) Zero content edits: add  class="lz-cards"  to an existing bullet list
 *       and each <li> becomes a title-only card.
 * ------------------------------------------------------------------------ */
.mw-parser-output .lz-cardgrid,
.mw-parser-output ul.lz-cards {
	display: grid;
	grid-template-columns: repeat( auto-fill, minmax( 15rem, 1fr ) );
	gap: 0.7rem;
	max-width: none;
	margin: 1em 0 2em;
	padding: 0;
	list-style: none;
}

.mw-parser-output ul.lz-cards li {
	margin: 0;
	list-style: none;
}

.mw-parser-output .lz-card,
.mw-parser-output ul.lz-cards > li {
	display: flex;
	flex-direction: column;
	gap: 0.3rem;
	padding: 0.8rem 0.95rem;
	background: var( --lz-surface );
	border: 1px solid var( --lz-line );
	border-radius: 0.45rem;
}

.mw-parser-output .lz-card:hover,
.mw-parser-output ul.lz-cards > li:hover {
	border-color: var( --lz-accent );
	box-shadow: var( --lz-shadow );
}

.mw-parser-output .lz-card a,
.mw-parser-output ul.lz-cards > li > a {
	font-weight: 600;
	font-size: 0.93rem;
	line-height: 1.3;
	color: var( --lz-ink );
	text-decoration: none;
}

.mw-parser-output .lz-card:hover a,
.mw-parser-output ul.lz-cards > li:hover > a {
	color: var( --lz-accent );
}

.mw-parser-output .lz-card-desc {
	font-size: 0.8rem;
	line-height: 1.45;
	color: var( --lz-ink-3 );
}

.mw-parser-output .lz-card-cmd {
	font-family: var( --lz-mono );
	font-size: 0.74rem;
	color: var( --lz-accent );
	overflow-wrap: break-word;
}

/* Template:Card always emits both slots; collapse the unused ones so the
 * flex gap does not leave a hole. Avoids needing ParserFunctions #if. */
.mw-parser-output .lz-card-desc:empty,
.mw-parser-output .lz-card-cmd:empty {
	display: none;
}

/* --- Main Page hero ---
 * "Main Page" is a useless <h1>, so it is hidden and the hero carries its own
 * real <h1> instead — hiding the skin's title without replacing it would leave
 * the document with no top-level heading. */
body.page-Main_Page #firstHeading,
body.page-Main_Page #siteSub {
	display: none;
}

.mw-parser-output .lz-hero {
	margin: 0 0 2.25rem;
	padding: 0 0 1.5rem;
	border-bottom: 1px solid var( --lz-line );
}

.mw-parser-output .lz-hero h1 {
	margin: 0 0 0.5rem;
	font-family: var( --lz-mono );
	font-size: clamp( 1.5rem, 1.1rem + 1.7vw, 2.2rem );
	font-weight: 600;
	letter-spacing: -0.02em;
	line-height: 1.15;
	color: var( --lz-accent );
	border-bottom: 0;
	text-wrap: balance;
}

.mw-parser-output .lz-hero p {
	max-width: 62ch;
	margin: 0;
	color: var( --lz-ink-2 );
	font-size: 1.02rem;
}

/* Quiet footnote block — the contribute line at the foot of the Main Page. */
.mw-parser-output .lz-footnote {
	max-width: 62ch;
	margin: 2.5rem 0 0;
	padding-top: 1.25rem;
	border-top: 1px solid var( --lz-line );
	font-size: 0.9rem;
	color: var( --lz-ink-3 );
}

.mw-parser-output .lz-footnote p {
	margin: 0;
	max-width: none;
}

/* Section rules above each card group. */
.mw-parser-output h2.lz-section {
	display: flex;
	align-items: center;
	gap: 0.7rem;
	font-size: 0.78rem;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var( --lz-ink-3 );
	border-bottom: 0;
	padding-bottom: 0;
}

.mw-parser-output h2.lz-section::after {
	content: "";
	flex: 1;
	height: 1px;
	background: var( --lz-line );
}

/* ---------------------------------------------------------------------------
 * 9. LEGACY INLINE-STYLE BOX
 *
 * Every article's wikitext currently hardcodes:
 *   <div style="margin-top:1.5em; border:3px solid #ae8c55; border-radius:.5em;
 *               padding:1em 1.5em; font-size:1.2em">
 * Inline styles outrank the cascade, so !important is required here. This is
 * a bridge — the real fix is migrating those pages to Template:Box, after
 * which this block can be deleted.
 * ------------------------------------------------------------------------ */
.mw-parser-output div[ style*="#ae8c55" ] {
	margin-top: 0 !important;
	padding: 0 !important;
	border: 0 !important;
	border-radius: 0 !important;
	font-size: 1em !important;
}

/* The Copperplate banner on Main Page. */
.mw-parser-output div[ style*="#936c29" ] {
	color: var( --lz-ink ) !important;
	font-family: var( --lz-mono ) !important;
	font-size: 1.75rem !important;
	letter-spacing: -0.02em;
}

.mw-parser-output div[ style*="Copperplate" ] span,
.mw-parser-output span[ style*="Copperplate" ] {
	font-family: var( --lz-mono ) !important;
}

/* Intended replacement, once Template:Box exists. */
.mw-parser-output .lz-note {
	display: flex;
	gap: 0.75rem;
	max-width: 68ch;
	margin: 1.3em 0;
	padding: 0.85em 1em;
	background: var( --lz-accent-tint );
	border-left: 3px solid var( --lz-accent );
	border-radius: 0 0.35rem 0.35rem 0;
	font-size: 0.94rem;
	color: var( --lz-ink-2 );
}

.mw-parser-output .lz-note p {
	margin: 0;
	max-width: none;
}

.mw-parser-output .lz-note::before {
	content: "!";
	flex: none;
	font-family: var( --lz-mono );
	font-weight: 700;
	color: var( --lz-accent );
}

.mw-parser-output .lz-note.lz-warn {
	background: rgba( 161, 47, 47, 0.08 );
	border-left-color: var( --lz-red );
}

.mw-parser-output .lz-note.lz-warn::before {
	content: "\26A0";
	color: var( --lz-red );
}

/* ---------------------------------------------------------------------------
 * 10. PRINT & MOTION
 * ------------------------------------------------------------------------ */
@media print {
	.mw-parser-output .mw-highlight,
	.mw-parser-output > pre {
		background: #fff;
		border: 1px solid #999;
		color: #000;
	}

	.mw-parser-output .mw-highlight pre {
		color: #000;
	}

	.lz-chead,
	.lz-theme-toggle {
		display: none;
	}
}

@media ( prefers-reduced-motion: reduce ) {
	* {
		transition: none !important;
		animation: none !important;
		scroll-behavior: auto !important;
	}
}