MediaWiki:Common.css: Difference between revisions
From LinuxizeNet
(Restrict icon invert to icon-only elements; stop double-treating search button) |
(Fix Template:Box layout — flex was fragmenting inline content) |
||
| (8 intermediate revisions by the same user not shown) | |||
| Line 6: | Line 6: | ||
* | * | ||
* Loads via the `site.styles` module, after the skin's own styles, so | * Loads via the `site.styles` module, after the skin's own styles, so | ||
* equal-specificity selectors win without !important. !important | * equal-specificity selectors win without !important. !important appears in | ||
* | * exactly two places, both deliberate: the prefers-reduced-motion block, and | ||
* the thumbnail caption fill in section 11 (see the note there). | |||
* | * | ||
* Sections: | * Sections: | ||
| Line 18: | Line 19: | ||
* 7. Tables | * 7. Tables | ||
* 8. Card grids (index pages) | * 8. Card grids (index pages) | ||
* 9. | * 9. Callouts (Template:Box) | ||
* 10. Print | * 10. Print | ||
* 11. Imported Wikipedia templates (TemplateStyles overrides) | |||
* ========================================================================= */ | * ========================================================================= */ | ||
| Line 348: | Line 350: | ||
} | } | ||
/* Theme toggle, mounted into | /* Theme toggle, mounted into #user-tools by Common.js — the one header element | ||
* that exists for anonymous and logged-in visitors alike. #personal-extra and | |||
* the user dropdown do not. */ | |||
body.skin-timeless .lz-theme-slot { | |||
float: left; | |||
display: flex; | |||
align-items: center; | |||
/* 38px, not the container's 42px: the Echo badges next door sit 2px above | |||
* the box centre, so centring on 42px left the button visibly low. */ | |||
height: 38px; | |||
/* Left margin matters — the slot is the first child of #user-tools and | |||
* would otherwise butt straight against the end of the search bar. */ | |||
margin: 0 0.75em 0 1.1em; | |||
} | |||
body.skin-timeless .lz-theme-toggle { | body.skin-timeless .lz-theme-toggle { | ||
margin: 0 | margin: 0; | ||
} | } | ||
/* | /* The user glyph beside "Datanasov" / "Anonymous". | ||
* | * | ||
* | * Timeless paints it as a background-image on the <h2> that also holds the | ||
* | * label, so it is a dark grey SVG that disappears on a dark ground — and it | ||
* | * cannot be fixed with --lz-icon-filter, because filtering that element would | ||
body.skin-timeless | * invert the label text with it. Replaced with a masked pseudo-element | ||
background- | * instead: `mask` + `background-color` lets the glyph take a token colour | ||
* directly, so it is correct in both themes with no filter at all. */ | |||
body.skin-timeless #mw-header-container h2 { | |||
background-image: none; | |||
position: relative; | |||
} | } | ||
body.skin-timeless | /* The dropdown caret on the same <h2>. Timeless uses arrow-down-grey.svg, | ||
background-color: var( --lz- | * which disappears on a dark ground for the same reason as the user glyph — | ||
* and again cannot be filtered, because the element carries the label text. | |||
* Same masked-token treatment. */ | |||
body.skin-timeless #mw-header-container h2::after { | |||
background-image: none; | |||
background-color: var( --lz-ink-2 ); | |||
-webkit-mask: url( "data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2020%2020'%3E%3Cpath%20d='M5%208h10l-5%206z'/%3E%3C/svg%3E" ) no-repeat center / 10px 10px; | |||
mask: url( "data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2020%2020'%3E%3Cpath%20d='M5%208h10l-5%206z'/%3E%3C/svg%3E" ) no-repeat center / 10px 10px; | |||
} | } | ||
body.skin-timeless | body.skin-timeless #mw-header-container h2::before { | ||
background-color: var( --lz- | content: ""; | ||
position: absolute; | |||
left: 0; | |||
top: 50%; | |||
width: 17px; | |||
height: 17px; | |||
transform: translateY( -50% ); | |||
background-color: var( --lz-ink-2 ); | |||
-webkit-mask: url( "data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2020%2020'%3E%3Cpath%20d='M10%2010a4%204%200%20100-8%204%204%200%20000%208Zm0%201.6c-4.2%200-7%202.1-7%204.6V18h14v-1.8c0-2.5-2.8-4.6-7-4.6Z'/%3E%3C/svg%3E" ) no-repeat center / contain; | |||
mask: url( "data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2020%2020'%3E%3Cpath%20d='M10%2010a4%204%200%20100-8%204%204%200%20000%208Zm0%201.6c-4.2%200-7%202.1-7%204.6V18h14v-1.8c0-2.5-2.8-4.6-7-4.6Z'/%3E%3C/svg%3E" ) no-repeat center / contain; | |||
} | } | ||
body.skin-timeless #mw- | |||
/* --- Visited links in chrome --- | |||
* `.mw-body a:visited` only covers article content, so every link outside it — | |||
* both sidebars, the Categories box, the tab strip, the footer — fell back to | |||
* MediaWiki's default visited blue, against a warm amber palette. | |||
* | |||
* Chrome links are given NO visited state rather than a palette-correct one. | |||
* Every reader has clicked "Main page" and "Recent changes"; colouring those | |||
* as visited turns the sidebar a second colour and tells you nothing. Visited | |||
* styling stays where it earns its place: article content. */ | |||
body.skin-timeless #mw-site-navigation a:visited, | |||
body.skin-timeless #mw-related-navigation a:visited, | |||
body.skin-timeless #catlinks-sidebar a:visited, | |||
body.skin-timeless .sidebar-chunk a:visited, | |||
body.skin-timeless #mw-header-container a:visited, | |||
body.skin-timeless #mw-page-header-links a:visited, | |||
body.skin-timeless #mw-footer a:visited, | |||
body.skin-timeless .catlinks a:visited { | |||
color: var( --lz-accent ); | |||
} | } | ||
body.skin-timeless | body.skin-timeless #mw-site-navigation a:visited:hover, | ||
body.skin-timeless #mw-related-navigation a:visited:hover, | |||
body.skin-timeless #catlinks-sidebar a:visited:hover, | |||
body.skin-timeless .sidebar-chunk a:visited:hover, | |||
body.skin-timeless .catlinks a:visited:hover { | |||
color: var( --lz-accent-hov ); | |||
} | } | ||
/* --- | /* --- Categories below the sidebar breakpoint --- | ||
* Timeless | * Timeless shows categories in the right sidebar and hides the standard | ||
* | * in-content bar (#catlinks in #content-bottom-stuff). Below 1100px it | ||
* | * collapses BOTH sidebars into header dropdowns, so categories end up behind | ||
* | * a click exactly on the screens with least room. | ||
* | * | ||
* Rather than pin the sidebar box open — which fights the skin's layout and | |||
body.skin-timeless # | * pushes the article down the page — the in-content bar is restored at those | ||
* widths. It sits at the foot of the article, which is where MediaWiki puts it | |||
* anyway, and it inherits the .catlinks styling in section 2. */ | |||
@media screen and ( max-width: 1099px ) { | |||
body.skin-timeless #catlinks { | |||
display: block; | |||
} | |||
} | } | ||
/* --- Timeless accent bands --- | |||
* Timeless ships a red / blue / green tricolour strip under the header | |||
body.skin-timeless | * (three stacked divs inside #mw-header-hack and .color-bar) and a teal rule | ||
color: var( --lz- | * 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 | body.skin-timeless .color-middle { | ||
color: var( --lz- | background-color: var( --lz-band-2 ); | ||
} | } | ||
body.skin-timeless | body.skin-timeless .color-right { | ||
color: var( --lz- | background-color: var( --lz-band-3 ); | ||
} | } | ||
body.skin-timeless #mw-content-container { | |||
.mw- | border-bottom-color: var( --lz-band-rule ); | ||
color: var( --lz- | |||
} | } | ||
body.skin-timeless li.selected { | |||
. | border-bottom-color: var( --lz-accent ); | ||
color: var( --lz-accent | |||
} | } | ||
.mw-body | /* --- Timeless footer --- | ||
color: var( --lz- | * 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 ); | |||
} | } | ||
.mw-body | body.skin-timeless #mw-footer li, | ||
body.skin-timeless #mw-footer #footer-info li, | |||
color: var( --lz- | body.skin-timeless #mw-footer #footer-places li { | ||
color: var( --lz-ink-2 ); | |||
} | } | ||
body.skin-timeless #mw-footer a { | |||
.mw- | color: var( --lz-accent ); | ||
} | } | ||
body.skin-timeless #mw-footer a:hover { | |||
color: var( --lz-accent-hov ); | |||
.mw- | |||
color: var( --lz- | |||
} | } | ||
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 ); | |||
color: var( --lz- | |||
} | } | ||
.mw-body a.new, | |||
a.new { | |||
color: var( --lz-red ); | |||
color: var( --lz- | |||
} | } | ||
#mw- | /* External and interwiki links. MediaWiki core colours these #36c / #3377aa, | ||
background: | * with a specificity that beats the generic `a` rule above — so without this | ||
color: var( --lz- | * every outbound link on the wiki renders in MediaWiki blue against a warm | ||
* amber palette. They already get a typographic marker below, so they do not | |||
* need a separate hue to be distinguishable. */ | |||
a.external, | |||
a.extiw, | |||
.mw-body a.external, | |||
.mw-body a.extiw, | |||
.mw-parser-output a.external, | |||
.mw-parser-output a.extiw { | |||
background-image: none; | |||
padding-right: 0; | |||
color: var( --lz-accent ); | |||
} | } | ||
.mw-parser-output a.external:visited, | |||
color: var( --lz- | .mw-parser-output a.extiw:visited { | ||
color: var( --lz-visited ); | |||
} | } | ||
.mw-parser-output a.external:hover, | |||
.mw-parser-output a.extiw:hover { | |||
color: var( --lz-accent-hov ); | |||
} | } | ||
/* 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; | |||
font-size: 0. | |||
color: var( --lz-ink-3 ); | color: var( --lz-ink-3 ); | ||
} | } | ||
:focus-visible { | |||
outline: 2px solid var( --lz-accent ); | |||
outline-offset: 2px; | |||
border-radius: 2px; | |||
} | } | ||
/* --- left sidebar --- */ | |||
#mw- | #mw-panel.vector-legacy-sidebar { | ||
padding-top: 1em; | |||
} | } | ||
# | #mw-panel .vector-menu-portal .vector-menu-heading { | ||
font-family: var( --lz-mono ); | font-family: var( --lz-mono ); | ||
font-size: 0. | font-size: 0.68rem; | ||
font-weight: 600; | |||
letter-spacing: 0.1em; | |||
text-transform: uppercase; | |||
color: var( --lz-ink-3 ); | 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 { | ||
color: var( --lz- | 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 ); | background: var( --lz-surface-2 ); | ||
color: var( --lz-ink ); | color: var( --lz-ink ); | ||
text-decoration: none; | |||
} | } | ||
# | #mw-panel .vector-menu-portal .vector-menu-content-list li a:visited { | ||
color: var( --lz-ink- | 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-family: var( --lz-mono ); | ||
font-size: 0. | font-size: 0.75rem; | ||
letter-spacing: 0.02em; | |||
color: var( --lz-ink-3 ); | 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-family: var( --lz-mono ); | ||
font-size: 0. | 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 | |||
display: flex; | * the viewport patch at the top of Common.js (no server access). | ||
flex- | * ------------------------------------------------------------------------ */ | ||
@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 | body.skin-vector > * { | ||
order: 5; | |||
} | } | ||
# | #mw-navigation { | ||
# | order: 1; | ||
} | |||
body.skin-vector #content.mw-body { | |||
order: 2; | |||
} | } | ||
body.skin-vector # | 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 | ||
* below | * 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 | ||
#mw- | * about 235px from the left. */ | ||
#mw-head { | |||
position: static; | position: static; | ||
width: auto; | width: auto; | ||
float: none; | |||
display: | display: flow-root; | ||
margin: 0.5em 0 0; | |||
padding: 0 0.75em; | |||
margin: 0. | |||
padding: 0 | |||
} | } | ||
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; | margin: 0; | ||
} | } | ||
body.skin-vector #p-personal .vector-menu-content-list li { | |||
margin: 0; | margin: 0; | ||
} | } | ||
# | #left-navigation, | ||
#right-navigation { | |||
float: none; | |||
margin-left: 0; | |||
} | } | ||
body.skin-vector #p-search { | |||
margin: 0; | 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 { | |||
padding: | 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; | ||
} | |||
} | |||
.mw- | /* 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; | |||
} | |||
.mw-body | 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; | |||
} | |||
.mw- | /* 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 { | |||
.mw- | padding: 1em 0.85em 1.5em; | ||
} | |||
} | |||
.mw- | .mw-parser-output .mw-highlight pre { | ||
font-size: 0.75rem; | |||
} | |||
} | } | ||
.mw- | /* --------------------------------------------------------------------------- | ||
color: var( --lz-ink | * 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- | .mw-body h2 { | ||
margin: 0. | font-size: 1.3rem; | ||
margin-top: 2.2em; | |||
padding-bottom: 0.3em; | |||
border-bottom: 1px solid var( --lz-line ); | |||
} | } | ||
.mw- | .mw-body h3 { | ||
margin- | font-size: 1.06rem; | ||
margin-top: 1.9em; | |||
} | } | ||
.mw- | .mw-body h4 { | ||
color: var( --lz-ink- | font-size: 0.95rem; | ||
margin-top: 1.6em; | |||
color: var( --lz-ink-2 ); | |||
} | } | ||
.mw-parser-output | /* 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 { | |||
margin: | scroll-margin-top: 1.5rem; | ||
} | } | ||
.mw- | .mw-editsection { | ||
font-family: var( --lz-mono ); | |||
font-size: 0.7rem; | |||
font-weight: 400; | |||
color: var( --lz-ink- | color: var( --lz-ink-3 ); | ||
} | } | ||
.mw-editsection a { | |||
color: var( --lz-ink-3 ); | |||
} | |||
.mw- | .mw-editsection a:hover { | ||
color: var( --lz-accent ); | |||
color: var( --lz- | |||
} | } | ||
/* | /* 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 { | |||
.mw-parser-output .mw- | max-width: 68ch; | ||
} | } | ||
.mw-parser-output | .mw-parser-output p { | ||
margin | margin: 0.85em 0; | ||
} | } | ||
.mw-parser-output li { | |||
.mw-parser-output | margin-bottom: 0.3em; | ||
} | } | ||
. | .mw-parser-output li::marker { | ||
color: var( --lz-ink-3 ); | |||
color: var( --lz- | |||
} | } | ||
. | .mw-parser-output hr { | ||
border: 0; | |||
border-top: 1px solid var( --lz-line ); | |||
border: 1px solid var( --lz | margin: 2em 0; | ||
} | } | ||
. | .mw-parser-output blockquote { | ||
margin: 1.2em 0; | |||
border- | padding: 0.1em 0 0.1em 1em; | ||
color: var( --lz- | 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; | |||
color: var( --lz- | |||
} | } | ||
/* --------------------------------------------------------------------------- | |||
. | * 5. CODE BLOCKS — SyntaxHighlight (Pygments) is already installed, so the | ||
.mw- | * token spans below already exist in the rendered HTML. | ||
.mw-highlight . | * 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- | .mw-parser-output .mw-highlight pre { | ||
.mw-highlight . | margin: 0; | ||
padding: 0.85em 1em; | |||
color: var( --lz- | 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- | .mw-parser-output .mw-highlight .lz-chead { | ||
.mw-highlight . | 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; | |||
color: var( --lz- | text-transform: uppercase; | ||
color: var( --lz-code-chrome ); | |||
} | } | ||
. | .lz-copy { | ||
padding: 0.2em 0.6em; | |||
color: var( --lz- | 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 { | ||
color: var( --lz- | 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 ); | |||
color: var( --lz- | |||
} | } | ||
.mw-highlight . | /* Pygments token palette — warm-dominant, one cool hue for variables. | ||
color: | * 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 . | .mw-highlight .k, | ||
color: var( --lz-syn- | .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- | |||
color: var( --lz- | |||
} | } | ||
.mw-highlight .nv, | |||
.mw-highlight .vi, | |||
.mw- | .mw-highlight .na { | ||
.mw- | color: var( --lz-syn-var ); | ||
color: var( --lz- | |||
} | } | ||
.mw- | .mw-highlight .s, | ||
color: var( --lz- | .mw-highlight .s1, | ||
.mw-highlight .s2, | |||
.mw-highlight .sb, | |||
.mw-highlight .se { | |||
color: var( --lz-syn-string ); | |||
} | } | ||
.mw- | .mw-highlight .o, | ||
color: var( --lz-syn- | .mw-highlight .ow { | ||
color: var( --lz-syn-op ); | |||
} | } | ||
.mw-highlight .p { | |||
color: var( --lz-syn-punct ); | |||
.mw- | |||
} | } | ||
.mw- | .mw-highlight .m, | ||
.mw- | .mw-highlight .mi, | ||
.mw-highlight .mf { | |||
color: var( --lz-syn-num ); | |||
color: var( --lz- | |||
} | } | ||
.mw- | .mw-highlight .w { | ||
color: inherit; | |||
} | } | ||
.mw- | .mw-highlight .err { | ||
color: var( --lz-syn-err ); | |||
background: transparent; | |||
} | } | ||
.mw-parser-output | /* 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; | |||
} | } | ||
.mw-parser-output | /* 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. */ | |||
color: var( --lz- | .mw-parser-output pre a, | ||
.mw-parser-output pre a:visited { | |||
color: var( --lz-code-link ); | |||
} | } | ||
.mw-parser-output | .mw-parser-output pre a:hover { | ||
color: var( --lz- | color: var( --lz-code-link-hover ); | ||
} | } | ||
.mw-parser-output | .mw-parser-output pre a.new { | ||
color: var( --lz-syn-err ); | |||
color: var( --lz- | |||
} | } | ||
/* --------------------------------------------------------------------------- | /* --------------------------------------------------------------------------- | ||
* | * 6. TOC | ||
* The floating bordered box becomes a quiet block with mono numbering. | |||
* ------------------------------------------------------------------------ */ | * ------------------------------------------------------------------------ */ | ||
.mw-parser-output | .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: 1px solid var( --lz-line ); | ||
border-radius: 0.45rem; | border-radius: 0.45rem; | ||
padding: 0.9em 1.1em; | |||
font-size: 0.9rem; | font-size: 0.9rem; | ||
} | } | ||
.mw-parser-output | .mw-parser-output .toctitle h2, | ||
.mw-parser-output | .mw-parser-output #toc h2 { | ||
font-family: var( --lz-mono ); | font-family: var( --lz-mono ); | ||
font-size: 0. | font-size: 0.7rem; | ||
font-weight: 600; | font-weight: 600; | ||
letter-spacing: 0. | letter-spacing: 0.1em; | ||
text-transform: uppercase; | text-transform: uppercase; | ||
color: var( --lz-ink- | color: var( --lz-ink-3 ); | ||
border-bottom: 0; | border-bottom: 0; | ||
margin: 0 0 0.5em; | |||
padding: 0; | |||
} | } | ||
.mw-parser-output #toc ul { | |||
margin: 0; | |||
.mw-parser-output ul | |||
margin: | |||
padding: 0; | padding: 0; | ||
list-style: none; | list-style: none; | ||
} | } | ||
.mw-parser-output ul | .mw-parser-output #toc ul ul { | ||
margin | margin-left: 1em; | ||
} | } | ||
.mw-parser-output | .mw-parser-output #toc li { | ||
margin-bottom: 0.15em; | |||
} | } | ||
.mw-parser-output | .mw-parser-output #toc a { | ||
text-decoration: none; | text-decoration: none; | ||
color: var( --lz-ink-2 ); | |||
} | } | ||
.mw-parser-output | .mw-parser-output #toc a:hover { | ||
color: var( --lz-accent ); | color: var( --lz-accent ); | ||
text-decoration: underline; | |||
} | } | ||
.mw-parser-output . | .mw-parser-output #toc .tocnumber { | ||
font- | font-family: var( --lz-mono ); | ||
font-size: 0.78rem; | |||
color: var( --lz-ink-3 ); | color: var( --lz-ink-3 ); | ||
margin-right: 0.3em; | |||
} | } | ||
.mw-parser-output . | /* --------------------------------------------------------------------------- | ||
* 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 . | .mw-parser-output table.wikitable > * > tr > th { | ||
background: var( --lz-surface-2 ); | |||
font-family: var( --lz-mono ); | font-family: var( --lz-mono ); | ||
font-size: | font-size: 0.72rem; | ||
font-weight: 600; | font-weight: 600; | ||
letter-spacing: | letter-spacing: 0.06em; | ||
text-transform: uppercase; | |||
color: var( --lz- | color: var( --lz-ink-2 ); | ||
white-space: nowrap; | |||
} | } | ||
.mw-parser-output . | .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%; | |||
} | } | ||
.mw-parser-output .lz- | /* --------------------------------------------------------------------------- | ||
* 8. CARD GRIDS — index pages | |||
max-width: none; | * | ||
} | * 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 | |||
.mw-parser-output | * 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; | display: flex; | ||
align-items: center; | flex-direction: column; | ||
gap: 0.7rem; | gap: 0.3rem; | ||
font-size: 0.78rem; | 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; | letter-spacing: 0.12em; | ||
text-transform: uppercase; | text-transform: uppercase; | ||
color: var( --lz-ink-3 ); | color: var( --lz-ink-3 ); | ||
border-bottom: 0; | border-bottom: 0; | ||
padding-bottom: 0; | padding-bottom: 0; | ||
} | } | ||
.mw-parser-output h2.lz-section::after { | .mw-parser-output h2.lz-section::after { | ||
content: ""; | content: ""; | ||
flex: 1; | flex: 1; | ||
height: 1px; | height: 1px; | ||
background: var( --lz-line ); | background: var( --lz-line ); | ||
} | } | ||
/* --------------------------------------------------------------------------- | /* --------------------------------------------------------------------------- | ||
* 9. | * 9. CALLOUTS (Template:Box) | ||
* | * | ||
* | * The neutraliser that used to live here is gone. It cancelled a hand-pasted | ||
* | * `<div style="border:3px solid #ae8c55…">` wrapper that had been copied into | ||
* every article; that markup was stripped from all 22 pages on 2026-08-09, so | |||
* | * there is nothing left to neutralise. | ||
* | * | ||
* | * What remains is the real callout, used by Template:Box. | ||
* ------------------------------------------------------------------------ */ | * ------------------------------------------------------------------------ */ | ||
.mw-parser-output | |||
/* Intended replacement, once Template:Box exists. */ | |||
/* NOT display:flex. Template:Box emits inline content — bare text, <b>, | |||
border: | * <code> — and under flex every one of those becomes its own flex item, so | ||
border-radius: 0 | * the note renders as a row of fragments instead of a paragraph. The marker | ||
* is positioned instead, and the box keeps normal inline flow. */ | |||
.mw-parser-output .lz-note { | |||
position: relative; | |||
max-width: 68ch; | |||
margin: 1.3em 0; | |||
padding: 0.85em 1em 0.85em 2.5em; | |||
background: var( --lz-accent-tint ); | |||
border-left: 3px solid var( --lz-accent ); | |||
border-radius: 0 0.35rem 0.35rem 0; | |||
font-size: 0.94rem; | |||
line-height: 1.6; | |||
color: var( --lz-ink-2 ); | |||
} | |||
.mw-parser-output .lz-note p { | |||
margin: 0; | |||
max-width: none; | |||
} | |||
.mw-parser-output .lz-note::before { | |||
content: "!"; | |||
position: absolute; | |||
left: 1em; | |||
top: 0.85em; | |||
font-family: var( --lz-mono ); | |||
font-weight: 700; | |||
line-height: 1.6; | |||
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; | |||
} | |||
} | |||
/* --- Thumbnails / figures --- | |||
* MediaWiki core paints thumbnail frames #f8f9fa with a #eaecf0 border, on | |||
* both `figure[typeof~="mw:File/Thumb"]` (modern parser output) and the older | |||
* `.thumbinner`. On a dark ground that is a light slab carrying our light | |||
* caption text — it was the single root cause behind every remaining | |||
* low-contrast element on the imported Wikipedia page, including the red links | |||
* inside captions. | |||
* | |||
* Not skin-scoped: figures are article content and appear under any skin. */ | |||
.mw-parser-output figure[ typeof~="mw:File/Thumb" ], | |||
.mw-parser-output figure[ typeof~="mw:File/Frame" ], | |||
.mw-parser-output .thumbinner { | |||
background-color: var( --lz-surface-2 ); | |||
border: 1px solid var( --lz-line ); | |||
color: var( --lz-ink-2 ); | |||
} | |||
/* The caption and the older div.thumb wrapper keep a #f8f9fa fill from | |||
* somewhere in the core/skin cascade that outranks a plain | |||
* `.mw-parser-output figcaption` rule. I could not identify the winning | |||
* selector — the stylesheets were not readable through the CSSOM from this | |||
* page — so this is forced rather than out-specified. If the source is ever | |||
* found, drop the !important and match its specificity instead. | |||
* | |||
* Verified after the change: 0 low-contrast elements in light, dark and | |||
* unstamped, and no light surfaces left inside the article. */ | |||
.mw-parser-output figcaption, | |||
.mw-parser-output .thumbcaption, | |||
.mw-parser-output div.thumb, | |||
.mw-parser-output div.thumbinner { | |||
background-color: var( --lz-surface-2 ) !important; | |||
color: var( --lz-ink-2 ) !important; | |||
border-color: var( --lz-line ) !important; | |||
} | |||
/* The magnify/enlarge affordance on older thumb markup. */ | |||
.mw-parser-output .magnify a { | |||
filter: var( --lz-icon-filter ); | |||
} | |||
/* --------------------------------------------------------------------------- | |||
* 11. IMPORTED WIKIPEDIA TEMPLATES (TemplateStyles) | |||
* | |||
* Pages imported from Wikipedia — e.g. "Cinnamon (desktop environment)" — | |||
* drag in Module:Message box, CS1 citations and hatnotes. Those ship their own | |||
* CSS through TemplateStyles, which MediaWiki injects as a <style> block | |||
* INSIDE the page body. It therefore always lands after site.styles and wins | |||
* every tie on equal specificity. | |||
* | |||
* That is why every selector here starts with `body`: it raises specificity to | |||
* (0,2,1) against TemplateStyles' (0,2,0), which beats it regardless of | |||
* document order. Without that, these rules silently do nothing. | |||
* | |||
* The imported palette is Wikipedia's: #fbfbfb fill, #a2a9b1 borders, and a | |||
* blue/orange/yellow/red/purple severity ramp. The fill was the real problem — | |||
* on a dark ground it rendered a near-white slab carrying our light text: 17 | |||
* elements below 3:1, several at 1.21:1. | |||
* | |||
* The severity stripe is kept, because it carries meaning, but collapsed onto | |||
* our own tokens: critical -> red, needs-work -> accent, informational -> | |||
* neutral rule. | |||
* ------------------------------------------------------------------------ */ | |||
body .mw-parser-output .ambox { | |||
background-color: var( --lz-surface-2 ); | |||
border: 1px solid var( --lz-line ); | |||
border-left: 6px solid var( --lz-line-strong ); | |||
border-radius: 0 0.35rem 0.35rem 0; | |||
color: var( --lz-ink ); | |||
} | |||
body .mw-parser-output .ambox .mbox-text, | |||
body .mw-parser-output .ambox .mbox-text-span, | |||
body .mw-parser-output .ambox b { | |||
color: var( --lz-ink ); | |||
} | |||
body .mw-parser-output .ambox .hide-when-compact, | |||
body .mw-parser-output .ambox .plainlinks { | |||
color: var( --lz-ink-2 ); | |||
} | |||
/* Severity ramp, mapped onto the site palette. */ | |||
body .mw-parser-output .ambox-speedy, | |||
body .mw-parser-output .ambox-delete { | |||
border-left-color: var( --lz-red ); | |||
} | |||
body .mw-parser-output .ambox-content, | |||
body .mw-parser-output .ambox-style { | |||
border-left-color: var( --lz-accent ); | |||
} | |||
body .mw-parser-output .ambox-notice, | |||
body .mw-parser-output .ambox-move, | |||
body .mw-parser-output .ambox-protection { | |||
border-left-color: var( --lz-line-strong ); | |||
} | |||
body .mw-parser-output .ambox-speedy { | |||
background-color: var( --lz-accent-tint ); | |||
} | |||
/* Hatnotes ("See also…") sit above the article body. */ | |||
body .mw-parser-output .hatnote { | |||
color: var( --lz-ink-2 ); | |||
} | |||
/* CS1 citation machinery. */ | |||
body .mw-parser-output .cs1-visible-error, | |||
body .mw-parser-output .cs1-hidden-error { | |||
color: var( --lz-red ); | |||
} | |||
body .mw-parser-output .cs1-maint { | |||
color: var( --lz-code-ok ); | |||
} | } | ||
body .mw-parser-output .citation:target { | |||
.mw-parser-output | background-color: var( --lz-accent-tint ); | ||
color: var( --lz- | |||
} | } | ||
. | /* Reference list and the [1] superscripts. */ | ||
.mw-parser-output | body .mw-parser-output .mw-references-wrap, | ||
body .mw-parser-output .reflist { | |||
.mw-parser-output . | |||
color: var( --lz-ink-2 ); | color: var( --lz-ink-2 ); | ||
font-size: 0.9em; | |||
} | } | ||
.mw-parser-output | body .mw-parser-output .mw-references-wrap li:target { | ||
background-color: var( --lz-accent-tint ); | |||
.mw- | |||
} | } | ||
Latest revision as of 21:59, 9 August 2026
/* ============================================================================
* 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 appears in
* exactly two places, both deliberate: the prefers-reduced-motion block, and
* the thumbnail caption fill in section 11 (see the note there).
*
* Sections:
* 1. Tokens
* 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. Callouts (Template:Box)
* 10. Print
* 11. Imported Wikipedia templates (TemplateStyles overrides)
* ========================================================================= */
/* ---------------------------------------------------------------------------
* 1. TOKENS
* Light is the base; the two dark blocks redefine tokens only.
*
* Any change to a colour here must be applied in THREE places or the themes
* drift apart: :root, the prefers-color-scheme block, the [data-theme="dark"]
* block. 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 );
/* Skin icons are monochrome dark SVG data-URIs, so they vanish on a dark
* ground. Flipping them via a token keeps this theme-driven instead of
* duplicating selectors inside each dark block. */
--lz-icon-filter: none;
--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-icon-filter: invert( 0.82 );
--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-icon-filter: invert( 0.82 );
--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;
}
/* ---------------------------------------------------------------------------
* 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 chrome surfaces ---
* Timeless paints its chrome from its own cool grey ramp: #eaecf0 page ground,
* #f8f9fa sidebar boxes, #ffffff header and content, #c8ccd1 input borders.
* Repointing those at our tokens does two jobs at once — it warms the chrome
* to match the palette in light mode, and it is what makes dark mode possible
* at all. These eight surfaces were exactly the ones that stayed light and
* produced the 32 low-contrast elements measured on 2026-08-09.
*
* Deliberately NOT wrapped in a dark-only guard: the warm surfaces are an
* improvement in light mode too. */
body.skin-timeless #mw-header-container {
background: var( --lz-surface );
}
body.skin-timeless #mw-content-container {
background: var( --lz-ground );
}
body.skin-timeless #mw-content,
body.skin-timeless #site-navigation,
body.skin-timeless #site-tools,
body.skin-timeless #page-tools,
body.skin-timeless #catlinks-sidebar,
body.skin-timeless .sidebar-chunk {
background: var( --lz-surface );
border-color: var( --lz-line );
}
body.skin-timeless #simpleSearch,
body.skin-timeless #searchInput {
background: var( --lz-surface-2 );
border-color: var( --lz-line );
color: var( --lz-ink );
}
body.skin-timeless #searchInput::placeholder {
color: var( --lz-ink-3 );
}
/* Portlet headings in both sidebars. */
body.skin-timeless #mw-site-navigation h3,
body.skin-timeless #mw-related-navigation h3,
body.skin-timeless .sidebar-chunk h3 {
color: var( --lz-ink-2 );
border-bottom-color: var( --lz-line );
}
/* Dropdowns (user menu, "More") float above the page on their own surface.
* #personal-inner must be matched by ID — Timeless styles it with an ID
* selector, which outranks any class selector we could write here. */
body.skin-timeless .dropdown,
body.skin-timeless #personal-inner,
body.skin-timeless #p-variants-desktop .dropdown,
body.skin-timeless .mw-portlet .dropdown {
background: var( --lz-surface );
border-color: var( --lz-line );
color: var( --lz-ink );
}
body.skin-timeless #p-personal-label,
body.skin-timeless #personal-inner h3 {
color: var( --lz-ink-2 );
}
/* Timeless hardcodes color:#000 on the header region and on the page-header
* tab links. `body { color }` cannot reach either, so on a dark ground they
* rendered black-on-near-black at 1.18:1. */
body.skin-timeless #mw-header-container,
body.skin-timeless #p-banner,
body.skin-timeless #p-banner a,
body.skin-timeless #user-tools,
body.skin-timeless #personal,
body.skin-timeless #personal-extra {
color: var( --lz-ink );
}
body.skin-timeless #mw-page-header-links a {
color: var( --lz-ink-2 );
}
body.skin-timeless #mw-page-header-links li.selected a {
color: var( --lz-ink );
font-weight: 600;
}
/* Monochrome skin icons.
*
* Only elements that are PURELY an icon may go in this list. A filter applies
* to an element's text as well as its background image, so filtering anything
* that renders a label inverts the label too — and because the computed
* `color` is unchanged, a contrast scan reports it as fine while it looks
* wrong on screen. That is how #mw-header-container h2 ("Datanasov" plus an
* avatar glyph) slipped through once. Check filtered elements by eye.
*
* Excluded on purpose: #searchButton (re-grounded above — filtering it as
* well flipped it back to light), and the footer's "Powered by MediaWiki"
* badge, which is a real logo. */
body.skin-timeless .mw-echo-notifications-badge,
body.skin-timeless #mw-searchButton {
filter: var( --lz-icon-filter );
}
/* Theme toggle, mounted into #user-tools by Common.js — the one header element
* that exists for anonymous and logged-in visitors alike. #personal-extra and
* the user dropdown do not. */
body.skin-timeless .lz-theme-slot {
float: left;
display: flex;
align-items: center;
/* 38px, not the container's 42px: the Echo badges next door sit 2px above
* the box centre, so centring on 42px left the button visibly low. */
height: 38px;
/* Left margin matters — the slot is the first child of #user-tools and
* would otherwise butt straight against the end of the search bar. */
margin: 0 0.75em 0 1.1em;
}
body.skin-timeless .lz-theme-toggle {
margin: 0;
}
/* The user glyph beside "Datanasov" / "Anonymous".
*
* Timeless paints it as a background-image on the <h2> that also holds the
* label, so it is a dark grey SVG that disappears on a dark ground — and it
* cannot be fixed with --lz-icon-filter, because filtering that element would
* invert the label text with it. Replaced with a masked pseudo-element
* instead: `mask` + `background-color` lets the glyph take a token colour
* directly, so it is correct in both themes with no filter at all. */
body.skin-timeless #mw-header-container h2 {
background-image: none;
position: relative;
}
/* The dropdown caret on the same <h2>. Timeless uses arrow-down-grey.svg,
* which disappears on a dark ground for the same reason as the user glyph —
* and again cannot be filtered, because the element carries the label text.
* Same masked-token treatment. */
body.skin-timeless #mw-header-container h2::after {
background-image: none;
background-color: var( --lz-ink-2 );
-webkit-mask: url( "data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2020%2020'%3E%3Cpath%20d='M5%208h10l-5%206z'/%3E%3C/svg%3E" ) no-repeat center / 10px 10px;
mask: url( "data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2020%2020'%3E%3Cpath%20d='M5%208h10l-5%206z'/%3E%3C/svg%3E" ) no-repeat center / 10px 10px;
}
body.skin-timeless #mw-header-container h2::before {
content: "";
position: absolute;
left: 0;
top: 50%;
width: 17px;
height: 17px;
transform: translateY( -50% );
background-color: var( --lz-ink-2 );
-webkit-mask: url( "data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2020%2020'%3E%3Cpath%20d='M10%2010a4%204%200%20100-8%204%204%200%20000%208Zm0%201.6c-4.2%200-7%202.1-7%204.6V18h14v-1.8c0-2.5-2.8-4.6-7-4.6Z'/%3E%3C/svg%3E" ) no-repeat center / contain;
mask: url( "data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2020%2020'%3E%3Cpath%20d='M10%2010a4%204%200%20100-8%204%204%200%20000%208Zm0%201.6c-4.2%200-7%202.1-7%204.6V18h14v-1.8c0-2.5-2.8-4.6-7-4.6Z'/%3E%3C/svg%3E" ) no-repeat center / contain;
}
/* --- Visited links in chrome ---
* `.mw-body a:visited` only covers article content, so every link outside it —
* both sidebars, the Categories box, the tab strip, the footer — fell back to
* MediaWiki's default visited blue, against a warm amber palette.
*
* Chrome links are given NO visited state rather than a palette-correct one.
* Every reader has clicked "Main page" and "Recent changes"; colouring those
* as visited turns the sidebar a second colour and tells you nothing. Visited
* styling stays where it earns its place: article content. */
body.skin-timeless #mw-site-navigation a:visited,
body.skin-timeless #mw-related-navigation a:visited,
body.skin-timeless #catlinks-sidebar a:visited,
body.skin-timeless .sidebar-chunk a:visited,
body.skin-timeless #mw-header-container a:visited,
body.skin-timeless #mw-page-header-links a:visited,
body.skin-timeless #mw-footer a:visited,
body.skin-timeless .catlinks a:visited {
color: var( --lz-accent );
}
body.skin-timeless #mw-site-navigation a:visited:hover,
body.skin-timeless #mw-related-navigation a:visited:hover,
body.skin-timeless #catlinks-sidebar a:visited:hover,
body.skin-timeless .sidebar-chunk a:visited:hover,
body.skin-timeless .catlinks a:visited:hover {
color: var( --lz-accent-hov );
}
/* --- Categories below the sidebar breakpoint ---
* Timeless shows categories in the right sidebar and hides the standard
* in-content bar (#catlinks in #content-bottom-stuff). Below 1100px it
* collapses BOTH sidebars into header dropdowns, so categories end up behind
* a click exactly on the screens with least room.
*
* Rather than pin the sidebar box open — which fights the skin's layout and
* pushes the article down the page — the in-content bar is restored at those
* widths. It sits at the foot of the article, which is where MediaWiki puts it
* anyway, and it inherits the .catlinks styling in section 2. */
@media screen and ( max-width: 1099px ) {
body.skin-timeless #catlinks {
display: block;
}
}
/* --- 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 );
}
/* External and interwiki links. MediaWiki core colours these #36c / #3377aa,
* with a specificity that beats the generic `a` rule above — so without this
* every outbound link on the wiki renders in MediaWiki blue against a warm
* amber palette. They already get a typographic marker below, so they do not
* need a separate hue to be distinguishable. */
a.external,
a.extiw,
.mw-body a.external,
.mw-body a.extiw,
.mw-parser-output a.external,
.mw-parser-output a.extiw {
background-image: none;
padding-right: 0;
color: var( --lz-accent );
}
.mw-parser-output a.external:visited,
.mw-parser-output a.extiw:visited {
color: var( --lz-visited );
}
.mw-parser-output a.external:hover,
.mw-parser-output a.extiw:hover {
color: var( --lz-accent-hov );
}
/* 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. CALLOUTS (Template:Box)
*
* The neutraliser that used to live here is gone. It cancelled a hand-pasted
* `<div style="border:3px solid #ae8c55…">` wrapper that had been copied into
* every article; that markup was stripped from all 22 pages on 2026-08-09, so
* there is nothing left to neutralise.
*
* What remains is the real callout, used by Template:Box.
* ------------------------------------------------------------------------ */
/* Intended replacement, once Template:Box exists. */
/* NOT display:flex. Template:Box emits inline content — bare text, <b>,
* <code> — and under flex every one of those becomes its own flex item, so
* the note renders as a row of fragments instead of a paragraph. The marker
* is positioned instead, and the box keeps normal inline flow. */
.mw-parser-output .lz-note {
position: relative;
max-width: 68ch;
margin: 1.3em 0;
padding: 0.85em 1em 0.85em 2.5em;
background: var( --lz-accent-tint );
border-left: 3px solid var( --lz-accent );
border-radius: 0 0.35rem 0.35rem 0;
font-size: 0.94rem;
line-height: 1.6;
color: var( --lz-ink-2 );
}
.mw-parser-output .lz-note p {
margin: 0;
max-width: none;
}
.mw-parser-output .lz-note::before {
content: "!";
position: absolute;
left: 1em;
top: 0.85em;
font-family: var( --lz-mono );
font-weight: 700;
line-height: 1.6;
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;
}
}
/* --- Thumbnails / figures ---
* MediaWiki core paints thumbnail frames #f8f9fa with a #eaecf0 border, on
* both `figure[typeof~="mw:File/Thumb"]` (modern parser output) and the older
* `.thumbinner`. On a dark ground that is a light slab carrying our light
* caption text — it was the single root cause behind every remaining
* low-contrast element on the imported Wikipedia page, including the red links
* inside captions.
*
* Not skin-scoped: figures are article content and appear under any skin. */
.mw-parser-output figure[ typeof~="mw:File/Thumb" ],
.mw-parser-output figure[ typeof~="mw:File/Frame" ],
.mw-parser-output .thumbinner {
background-color: var( --lz-surface-2 );
border: 1px solid var( --lz-line );
color: var( --lz-ink-2 );
}
/* The caption and the older div.thumb wrapper keep a #f8f9fa fill from
* somewhere in the core/skin cascade that outranks a plain
* `.mw-parser-output figcaption` rule. I could not identify the winning
* selector — the stylesheets were not readable through the CSSOM from this
* page — so this is forced rather than out-specified. If the source is ever
* found, drop the !important and match its specificity instead.
*
* Verified after the change: 0 low-contrast elements in light, dark and
* unstamped, and no light surfaces left inside the article. */
.mw-parser-output figcaption,
.mw-parser-output .thumbcaption,
.mw-parser-output div.thumb,
.mw-parser-output div.thumbinner {
background-color: var( --lz-surface-2 ) !important;
color: var( --lz-ink-2 ) !important;
border-color: var( --lz-line ) !important;
}
/* The magnify/enlarge affordance on older thumb markup. */
.mw-parser-output .magnify a {
filter: var( --lz-icon-filter );
}
/* ---------------------------------------------------------------------------
* 11. IMPORTED WIKIPEDIA TEMPLATES (TemplateStyles)
*
* Pages imported from Wikipedia — e.g. "Cinnamon (desktop environment)" —
* drag in Module:Message box, CS1 citations and hatnotes. Those ship their own
* CSS through TemplateStyles, which MediaWiki injects as a <style> block
* INSIDE the page body. It therefore always lands after site.styles and wins
* every tie on equal specificity.
*
* That is why every selector here starts with `body`: it raises specificity to
* (0,2,1) against TemplateStyles' (0,2,0), which beats it regardless of
* document order. Without that, these rules silently do nothing.
*
* The imported palette is Wikipedia's: #fbfbfb fill, #a2a9b1 borders, and a
* blue/orange/yellow/red/purple severity ramp. The fill was the real problem —
* on a dark ground it rendered a near-white slab carrying our light text: 17
* elements below 3:1, several at 1.21:1.
*
* The severity stripe is kept, because it carries meaning, but collapsed onto
* our own tokens: critical -> red, needs-work -> accent, informational ->
* neutral rule.
* ------------------------------------------------------------------------ */
body .mw-parser-output .ambox {
background-color: var( --lz-surface-2 );
border: 1px solid var( --lz-line );
border-left: 6px solid var( --lz-line-strong );
border-radius: 0 0.35rem 0.35rem 0;
color: var( --lz-ink );
}
body .mw-parser-output .ambox .mbox-text,
body .mw-parser-output .ambox .mbox-text-span,
body .mw-parser-output .ambox b {
color: var( --lz-ink );
}
body .mw-parser-output .ambox .hide-when-compact,
body .mw-parser-output .ambox .plainlinks {
color: var( --lz-ink-2 );
}
/* Severity ramp, mapped onto the site palette. */
body .mw-parser-output .ambox-speedy,
body .mw-parser-output .ambox-delete {
border-left-color: var( --lz-red );
}
body .mw-parser-output .ambox-content,
body .mw-parser-output .ambox-style {
border-left-color: var( --lz-accent );
}
body .mw-parser-output .ambox-notice,
body .mw-parser-output .ambox-move,
body .mw-parser-output .ambox-protection {
border-left-color: var( --lz-line-strong );
}
body .mw-parser-output .ambox-speedy {
background-color: var( --lz-accent-tint );
}
/* Hatnotes ("See also…") sit above the article body. */
body .mw-parser-output .hatnote {
color: var( --lz-ink-2 );
}
/* CS1 citation machinery. */
body .mw-parser-output .cs1-visible-error,
body .mw-parser-output .cs1-hidden-error {
color: var( --lz-red );
}
body .mw-parser-output .cs1-maint {
color: var( --lz-code-ok );
}
body .mw-parser-output .citation:target {
background-color: var( --lz-accent-tint );
}
/* Reference list and the [1] superscripts. */
body .mw-parser-output .mw-references-wrap,
body .mw-parser-output .reflist {
color: var( --lz-ink-2 );
font-size: 0.9em;
}
body .mw-parser-output .mw-references-wrap li:target {
background-color: var( --lz-accent-tint );
}