|
/* CSSAll placedJavaScript here will be appliedloaded tofor allusers skinsof the mobile site */
/* Note, there is no corresponding User:Username/mobile.js; however users may use User:Username/minerva.js */
/*
function addPortletLink() {
* This is the CSS common to all desktop skins on en.Wikipedia.
mw.log.warn(
* Styling inside .mw-parser-output should generally use TemplateStyles.
'addPortletLink is deprecated on desktop and never implemented on mobile',
*/
'More information on https://www.mediawiki.org/wiki/ResourceLoader/Migration_guide_(users)#addPortletLink'
/* Reset italic styling set by user agent */
);
cite,
dfn {
font-style: inherit;
}
/* CapSach — Mobile TOC overlay (all skins; phone widths) */
/* Straight quote marks for <q> */
(function () {
q {
// Detect MobileFrontend site (works across mobile skins)
quotes: '"' '"' "'" "'";
function isMobileSite() {
}
return document.body && document.body.classList.contains('mw-mf');
}
function once(id) {
/* Avoid collision of blockquote with floating elements by swapping margin and padding */
// Avoid duplicates across hook re-runs
blockquote {
return !document.getElementById(id);
overflow: hidden;
}
margin: 1em 0;
padding: 0 40px;
}
function ready(fn) {
/* Consistent size for <small>, <sub> and <sup> */
if (document.readyState === 'loading') {
small {
document.addEventListener('DOMContentLoaded', fn);
font-size: 85%;
} else {
}
fn();
}
}
function runInit() {
.mw-body-content sub,
// Don’t run on very wide screens (tablet/desktop have native TOC)
.mw-body-content sup {
if (window.matchMedia('(min-width: 768px)').matches) return;
font-size: 80%;
}
// Only on normal content pages
/* Same spacing for indented and unindented paragraphs on talk pages */
if (window.mw && mw.config && mw.config.get) {
.ns-talk .mw-body-content dd {
if (!mw.config.get('wgIsArticle')) return;
margin-top: 0.4em;
}
margin-bottom: 0.4em;
}
// Prevent duplicate UI
/* Reduce page jumps by hiding collapsed/dismissed content */
if (!once('cps-open-toc')) return;
.client-js .collapsible:not( .mw-made-collapsible).collapsed > tbody > tr:not(:first-child),
// Find the content root; MobileFrontend restructures DOM, so be flexible
/* Avoid FOUC/reflows on collapsed elements. */
var root =
/* This copies MediaWiki's solution for T42812 to apply to innercollapse/outercollapse (T325115). */
document.querySelector('#mw-content-text .mw-parser-output') ||
/* TODO: Use :is() selector at some reasonable future when support is good for Most Clients */
document.querySelector('.mw-parser-output') ||
/* Reference: https://gerrit.wikimedia.org/g/mediawiki/core/+/ecda06cb2aef55b77c4b4d7ecda492d634419ead/resources/src/jquery/jquery.makeCollapsible.styles.less#75 */
document.getElementById('mw-content-text') ||
.client-js .outercollapse .innercollapse.mw-collapsible:not( .mw-made-collapsible ) > p,
document.querySelector('#content') ||
.client-js .outercollapse .innercollapse.mw-collapsible:not( .mw-made-collapsible ) > table,
document.body;
.client-js .outercollapse .innercollapse.mw-collapsible:not( .mw-made-collapsible ) > thead + tbody,
.client-js .outercollapse .innercollapse.mw-collapsible:not( .mw-made-collapsible ) tr:not( :first-child ),
.client-js .outercollapse .innercollapse.mw-collapsible:not( .mw-made-collapsible ) .mw-collapsible-content,
// Collect headings (H2–H6). Prefer spans with .mw-headline (stable anchor ids)
/* Hide charinsert base for those not using the gadget */
var items = [];
#editpage-specialchars {
var indexById = Object.create(null);
display: none;
var headingElById = Object.create(null);
}
var headings = root.querySelectorAll('h2, h3, h4, h5, h6');
/* Different margin on references */
headings.forEach(function (h) {
.references {
var level = parseInt(h.tagName.slice(1), 10);
margin-bottom: 0.5em;
if (level < 2 || level > 6) return;
}
var headline = h.querySelector('.mw-headline') || h;
var id = headline.id || h.id;
var text = (headline.textContent || h.textContent || '').trim();
if (!id || !text) return;
items.push({ id: id, text: text, level: level });
/* Cite customizations */
indexById[id] = items.length - 1;
span[ rel="mw:referencedBy" ] {
headingElById[id] = h; // keep the <h2..h6> for collapse checks
counter-reset: mw-ref-linkback 0;
});
}
// Show only if there are enough headings to be useful (match core default)
span[ rel='mw:referencedBy' ] > a::before {
if (items.length < 3) return;
content: counter( mw-ref-linkback, lower-alpha );
font-size: 80%;
font-weight: bold;
font-style: italic;
}
// Create trigger button (bottom-left; avoids “Back to top” on bottom-right)
a[ rel="mw:referencedBy" ]::before {
var btn = document.createElement('button');
font-weight: bold;
btn.id = 'cps-open-toc';
content: "^";
btn.type = 'button';
}
btn.setAttribute('aria-label', 'Open table of contents');
btn.innerHTML = '<span class="icon" aria-hidden="true">≡</span><span class="label">TOC</span>';
document.body.appendChild(btn);
// Overlay + panel
span[ rel="mw:referencedBy" ]::before {
var overlay = document.createElement('div');
content: "^ ";
overlay.id = 'cps-toc-overlay';
}
overlay.setAttribute('aria-hidden', 'true');
var panel = document.createElement('div');
/* Styling for jQuery makeCollapsible, matching that of collapseButton */
panel.id = 'cps-toc-panel';
.mw-parser-output .mw-collapsible-toggle:not(.mw-ui-button) {
panel.setAttribute('role', 'dialog');
font-weight: normal;
panel.setAttribute('aria-modal', 'true');
padding-right: 0.2em;
panel.setAttribute('aria-label', 'Table of contents');
padding-left: 0.2em;
}
var header = document.createElement('div');
.mw-collapsible-leftside-toggle .mw-collapsible-toggle {
header.id = 'cps-toc-header';
/* @noflip */
header.innerHTML =
float: left;
'<h2 id="cps-toc-title">Contents</h2>' +
}
'<button id="cps-toc-close" type="button" aria-label="Close">×</button>';
var list = document.createElement('ul');
/* Lists in wikitable data cells are always left-aligned */
list.id = 'cps-toc-list';
.wikitable td ul,
.wikitable td ol,
.wikitable td dl {
/* @noflip */
text-align: left;
}
items.forEach(function (it) {
/* Change the external link icon to a PDF icon for all PDF files */
var li = document.createElement('li');
.mw-parser-output a[href$=".pdf"].external,
li.setAttribute('data-level', String(it.level));
.mw-parser-output a[href*=".pdf?"].external,
var a = document.createElement('a');
.mw-parser-output a[href*=".pdf#"].external,
a.href = '#' + it.id;
.mw-parser-output a[href$=".PDF"].external,
a.textContent = it.text;
.mw-parser-output a[href*=".PDF?"].external,
li.appendChild(a);
.mw-parser-output a[href*=".PDF#"].external {
list.appendChild(li);
background: url("//upload.wikimedia.org/wikipedia/commons/4/4d/Icon_pdf_file.png") no-repeat right;
});
/* @noflip */
padding: 8px 18px 8px 0;
}
panel.appendChild(header);
/* System messages styled similarly to fmbox */
panel.appendChild(list);
/* for .mw-warning-with-logexcerpt, behavior of this line differs between
overlay.appendChild(panel);
* the edit-protected notice and the special:Contribs for blocked users
document.body.appendChild(overlay);
* The latter has specificity of 3 classes so we have to triple up here.
*/
.mw-warning-with-logexcerpt.mw-warning-with-logexcerpt.mw-warning-with-logexcerpt,
div.mw-lag-warn-high,
div.mw-cascadeprotectedwarning,
div#mw-protect-cascadeon {
clear: both;
margin: 0.2em 0;
border: 1px solid #bb7070;
background-color: var(--background-color-error-subtle, #ffdbdb);
padding: 0.25em 0.9em;
box-sizing: border-box;
}
// Focus handling
/* default colors for partial block message */
var lastFocus = null;
/* gotta get over the hump introduced by the triple class above */
function openOverlay() {
.mw-contributions-blocked-notice-partial .mw-warning-with-logexcerpt.mw-warning-with-logexcerpt {
lastFocus = document.activeElement;
border-color: #fc3;
overlay.classList.add('is-open');
background-color: var(--background-color-warning-subtle, #fef6e7);
overlay.setAttribute('aria-hidden', 'false');
}
document.body.style.overflow = 'hidden';
var firstLink = list.querySelector('a');
if (firstLink) firstLink.focus({ preventScroll: true });
}
function closeOverlay() {
overlay.classList.remove('is-open');
overlay.setAttribute('aria-hidden', 'true');
document.body.style.overflow = '';
if (lastFocus && lastFocus.focus) lastFocus.focus({ preventScroll: true });
}
btn.style.display = 'flex'; // reveal trigger now that we know we have headings
/* Minimum thumb width */
btn.addEventListener('click', openOverlay);
@media (min-width: 640px) {
figure[typeof~='mw:File/Thumb'],
figure[typeof~='mw:File/Frame'],
.thumbinner {
min-width: 100px;
}
}
overlay.addEventListener('click', function (e) {
/* Prevent floating boxes from overlapping any category listings,
// Click outside the bottom sheet closes
file histories, edit previews, and edit [Show changes] views. */
if (e.target === overlay) closeOverlay();
#mw-subcategories,
});
#mw-pages,
overlay.querySelector('#cps-toc-close').addEventListener('click', closeOverlay);
#mw-category-media,
#filehistory,
#wikiPreview,
#wikiDiff {
clear: both;
}
overlay.addEventListener('keydown', function (e) {
/* Hide stuff meant for accounts with special permissions. Made visible again in
if (e.key === 'Escape') closeOverlay();
[[MediaWiki:Group-checkuser.css]], [[MediaWiki:Group-sysop.css]], [[MediaWiki:Group-abusefilter.css]],
});
[[MediaWiki:Group-abusefilter-helper.css]], [[MediaWiki:Group-patroller.css]],
[[MediaWiki:Group-templateeditor.css]], [[MediaWiki:Group-extendedmover.css]],
[[MediaWiki:Group-extendedconfirmed.css]], [[Mediawiki:Group-autoconfirmed.css]], and [[MediaWiki:Group-user.css]] */
.checkuser-show,
.sysop-show,
.abusefilter-show,
.abusefilter-helper-show,
.patroller-show,
.templateeditor-show,
.extendedmover-show,
.extendedconfirmed-show,
.autoconfirmed-show,
.user-show {
display: none;
}
// ---------- Helpers for collapsed/parent detection ----------
/* Hide the redlink generated by {{Editnotice}},
function findParentH2Item(id) {
this overrides the ".sysop-show { display: none; }" above that applies
var idx = indexById[id];
to the same link as well. See [[phab:T45013]]
if (typeof idx !== 'number') return null;
for (var i = idx - 1; i >= 0; i--) {
if (items[i].level === 2) return items[i];
}
return null;
}
function isH2Collapsed(h2El) {
Hide the images in editnotices to keep them readable in VE view.
if (!h2El) return false;
Long term, editnotices should become a core feature so that they can be designed responsive. */
.ve-ui-mwNoticesPopupTool-item .editnotice-redlink,
.ve-ui-mwNoticesPopupTool-item .mbox-image,
.ve-ui-mwNoticesPopupTool-item .mbox-imageright {
display: none !important;
}
// Preferred: ARIA state on the heading
/* Remove bullets when there are multiple edit page warnings */
var ae = h2El.getAttribute('aria-expanded');
ul.permissions-errors {
if (ae === 'false') return true;
margin: 0;
if (ae === 'true') return false;
}
// Newer markup: <section aria-expanded="…"> wrapping the H2 and content
ul.permissions-errors > li {
var section = h2El.closest && h2El.closest('section');
list-style: none;
if (section && section.hasAttribute('aria-expanded')) {
}
return section.getAttribute('aria-expanded') === 'false';
}
// Older MobileFrontend markup: .collapsible-block following the H2
/* larger inline math */
var next = h2El.nextElementSibling;
span.mwe-math-mathml-inline {
if (next && next.classList.contains('collapsible-block')) {
font-size: 118%;
return !next.classList.contains('open-block');
}
}
// Last resort: hidden attribute on content block
/* Make <math display="block"> be left aligned with one space indent for
if (next && (next.hidden || next.getAttribute('hidden') !== null)) return true;
* compatibility with style conventions
*/
.mwe-math-fallback-image-display,
.mwe-math-mathml-display {
margin-left: 1.6em !important;
margin-top: 0.6em;
margin-bottom: 0.6em;
}
return false;
.mwe-math-mathml-display math {
}
display: inline;
}
function findAnchorForHeadingEl(hEl) {
@media screen {
if (!hEl) return null;
/* Put a chequered background behind images, only visible if they have transparency,
var span = hEl.querySelector && hEl.querySelector('.mw-headline[id]');
* except on main, user, and portal namespaces
if (span) return span;
*/
return hEl.id ? hEl : null;
body:not(.ns-0):not(.ns-2):not(.ns-100) .gallerybox .thumb img {
}
background: #fff url(//upload.wikimedia.org/wikipedia/commons/5/5d/Checker-16x16.png) repeat;
}
function scrollToElement(el) {
/* Display "From Wikipedia, the free encyclopedia" in skins that support it,
do not apply totry print mode */{
el.scrollIntoView({ behavior: 'smooth', block: 'start' });
#siteSub {
} catch (_) {
display: block;
el.scrollIntoView(true);
}
}
/* Make the list of references smaller
* Keep in sync with Template:Refbegin/styles.css
* And Template:Reflist/styles.css
*/
.references {
font-size: 90%;
}
}
/* Hide FlaggedRevs notice UI when there are no pending changes */
.flaggedrevs_draft_synced,
.flaggedrevs_stable_synced,
/* "Temporary" to remove links in sidebar T255381 */
#t-upload,
/* Hide broken download box on Special:Book pending T285400 */
.mw-special-Book #coll-downloadbox {
display: none;
}
/*
* BELOW HERE THERE BE SOONTOBE TEMPLATESTYLES THINGS;
* SEE [[MediaWiki talk:Common.css/to do]]
* CSS is separated by component (which is why media queries are not joined)
*/
/* Infoboxes */
.infobox {
border: 1px solid #a2a9b1;
color: black;
padding: 0.2em;
font-size: 88%;
line-height: 1.5em;
border-spacing: 3px;
}
@media screen {
.infobox {
background-color: #f8f9fa;
}
}
// ---------- TOC click behavior ----------
@media (max-width: 640px) {
list.addEventListener('click', function (e) {
.infobox {
var a = e.target && e.target.closest('a');
width: 100%;
if (!a) return;
}
.infobox .nowrap {
white-space: normal;
}
}
e.preventDefault();
@media (min-width: 640px) {
var targetId = a.getAttribute('href').slice(1);
.infobox {
var target = document.getElementById(targetId);
/* @noflip */
closeOverlay();
margin: 0.5em 0 0.5em 1em;
/* @noflip */
float: right;
/* @noflip */
clear: right;
width: 22em;
}
}
var li = a.closest('li');
.infobox-header,
var level = li ? parseInt(li.getAttribute('data-level') || '0', 10) : 0;
.infobox-label,
.infobox-above,
.infobox-full-data,
.infobox-data,
.infobox-below,
.infobox-subheader,
.infobox-image,
.infobox-navbar,
/* Remove element selector when every .infobox thing is using the standard module/templates */
.infobox th,
.infobox td {
vertical-align: top;
}
// If user tapped H3+ and its parent H2 is collapsed → go to that H2 instead
.infobox-label,
if (level >= 3) {
.infobox-data,
var parentH2Item = findParentH2Item(targetId);
/* Remove element selector when every .infobox thing is using the standard module/templates */
if (parentH2Item) {
.infobox th,
var h2El = headingElById[parentH2Item.id] || null;
.infobox td {
var anchorEl = findAnchorForHeadingEl(h2El) || h2El;
/* @noflip */
text-align: left;
}
// Route to H2 if it's collapsed, or if for any reason the H3 anchor isn’t reachable
/* Remove .infobox when element selectors above are removed */
if ((h2El && isH2Collapsed(h2El)) || !target) {
.infobox .infobox-above,
if (anchorEl) {
.infobox .infobox-title,
scrollToElement(anchorEl);
/* Remove element selector when every .infobox thing is using the standard module/templates */
if (anchorEl.id) {
.infobox caption {
setTimeout(function () {
font-size: 125%;
if (history && history.replaceState) {
font-weight: bold;
history.replaceState(null, '', '#' + anchorEl.id);
text-align: center;
} else {
}
location.hash = anchorEl.id;
}
}, 200);
}
return;
}
}
}
}
// Default behavior: go to the requested target (H2 or H3) when not inside a collapsed section
.infobox-title,
if (target) {
/* Remove element selector when every .infobox thing is using the standard module/templates */
scrollToElement(target);
.infobox caption {
setTimeout(function () {
padding: 0.2em;
if (history && history.replaceState) {
}
history.replaceState(null, '', '#' + targetId);
} else {
location.hash = targetId;
}
}, 200);
}
});
// Re-hide on rotation/resize to tablet/desktop
/* Remove .infobox when element selectors above are removed */
window.addEventListener(
.infobox .infobox-header,
'resize',
.infobox .infobox-subheader,
function () {
.infobox .infobox-image,
if (window.matchMedia('(min-width: 768px)').matches) {
.infobox .infobox-full-data,
btn.style.display = 'none';
.infobox .infobox-below {
closeOverlay();
text-align: center;
} else {
}
btn.style.display = 'flex';
}
/* Remove .infobox when element selectors above are removed */
},
.infobox .infobox-navbar {
{ passive: true }
/* @noflip */
);
text-align: right;
}
/* Normal font styling for wikitable row headers with scope="row" tag */
.wikitable.plainrowheaders th[scope=row],
.wikitable.plainrowheaders th[scope=rowgroup] {
font-weight: normal;
/* @noflip */
text-align: left;
}
/* Remove underlines from certain links */
.nounderlines a,
.IPA a:link,
.IPA a:visited {
text-decoration: none !important;
}
/* Prevent line breaks in silly places where desired (nowrap)
and links when we don't want them to (nowraplinks a) */
.nowrap,
.nowraplinks a {
white-space: nowrap;
}
/* But allow wrapping where desired: */
.wrap,
.wraplinks a {
white-space: normal;
}
/* texhtml class for inline math (based on generic times-serif class) */
/* remove spans when this is TemplateStyled */
span.texhtml {
font-family: "Nimbus Roman No9 L", "Times New Roman", Times, serif;
font-size: 118%;
line-height: 1;
/* Force tabular and lining display for texhtml */
font-variant-numeric: lining-nums tabular-nums;
font-kerning: none;
}
span.texhtml span.texhtml {
font-size: 100%;
}
@media (min-width: 640px) {
span.texhtml {
white-space: nowrap;
}
}
/* Prevent flags in tables from collapsing: Fix for T116318
* TODO: Remove when [[phab:T368469]] merges [[phab:T367463]] for the other skins
*/
@media (max-width: 640px) {
.flagicon a > img,
.flagicon noscript > img {
max-width: none !important;
}
}
@media screen {
.nochecker .gallerybox .thumb img {
background-image: none;
}
}
/* CapSach — Mobile TOC overlay (all skins) */
#cps-open-toc {
position: fixed;
left: 16px;
bottom: calc(16px + env(safe-area-inset-bottom, 0px));
width: 48px; height: 48px;
border: 0; border-radius: 999px;
display: none; /* shown by JS when headings exist */
align-items: center; justify-content: center;
font-size: 14px; font-weight: 600;
color: #fff; background: rgba(0,0,0,.65);
box-shadow: 0 2px 8px rgba(0,0,0,.15);
z-index: 1000; cursor: pointer;
-webkit-tap-highlight-color: transparent;
}
#cps-open-toc:focus { outline: 2px solid #36c; outline-offset: 2px; }
#cps-open-toc .label { display: none; } /* icon-only by default */
#cps-open-toc .icon { font-size: 20px; line-height: 1; }
/* Full-screen scrim */
#cps-toc-overlay {
position: fixed; inset: 0;
background: rgba(0,0,0,.35);
display: none; z-index: 1001;
}
#cps-toc-overlay.is-open { display: block; }
/* Bottom sheet panel */
#cps-toc-panel {
position: fixed; left: 0; right: 0; bottom: 0;
max-height: 85vh;
border-radius: 12px 12px 0 0;
background: #fff; color: #202122;
box-shadow: 0 -8px 20px rgba(0,0,0,.2);
padding: 12px 12px calc(12px + env(safe-area-inset-bottom, 0px)) 12px;
}
/* Header row */
#cps-toc-header {
display: flex; align-items: center; justify-content: space-between;
margin-bottom: 6px;
}
#cps-toc-title { font-size: 16px; font-weight: 600; margin: 0; }
#cps-toc-close {
background: transparent; border: 0; font-size: 22px; line-height: 1;
}
/* List */
#cps-toc-list {
list-style: none; margin: 0; padding: 4px 2px 6px;
max-height: 70vh; overflow-y: auto; -webkit-overflow-scrolling: touch;
}
#cps-toc-list li { margin: 2px 0; }
#cps-toc-list a {
display: block; padding: 8px 10px; border-radius: 8px;
text-decoration: none; color: inherit;
}
#cps-toc-list a:focus, #cps-toc-list a:active {
outline: 2px solid #36c; background: #f5f6f7;
}
/* Indentation by heading level */
#cps-toc-list li[data-level="3"] { padding-left: 12px; }
#cps-toc-list li[data-level="4"] { padding-left: 24px; }
#cps-toc-list li[data-level="5"] { padding-left: 36px; }
#cps-toc-list li[data-level="6"] { padding-left: 48px; }
/* Only show on phone-ish widths; tablet/desktop keep native TOC */
@media (min-width: 768px) {
#cps-open-toc, #cps-toc-overlay { display: none !important; }
}
/* Respect reduced motion preference */
@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto; }
}
/* Make <youtube> embeds fluid and capped on large screens */
.mw-parser-output iframe[src*="youtube.com"],
.mw-parser-output iframe[src*="youtube-nocookie.com"] {
width: 100% !important; /* fills the content width on phones */
max-width: 320px; /* "typical" max width on desktops (tweak as needed) */
height: auto !important;
aspect-ratio: 16 / 9; /* keeps 16:9 without extra markup */
display: block;
margin: 0 auto; /* center when narrower than the content column */
}
// Orchestrate timing: wait for MobileFrontend to be present and re-run on dynamic updates
/*
if (window.mw && mw.loader) {
* Put anything you mean to be a sitewide addition above the TemplateStyles
mw.loader.using('mobile.startup').then(function () {
* comment above.
// Initial run
*/
ready(function () {
if (isMobileSite()) runInit();
});
// Run again when content is replaced (edit preview, post-edit, etc.)
if (mw.hook) {
mw.hook('wikipage.content').add(function () {
if (isMobileSite()) runInit();
});
}
});
} else {
// Extremely defensive fallback (shouldn’t happen on MobileFrontend)
ready(function () {
if (isMobileSite()) runInit();
});
}
})();
|