Template:UI/hero/styles.css

From Miniscope
Jump to: navigation, search
/* TemplateStyles for {{UI/hero}}.
 *
 * Two layout variants share the same DOM:
 *   * .wiki-hero--background — full-bleed image with overlay, centered
 *     text. Lab-wiki style. Pairs with theme=dark by default.
 *   * .wiki-hero--product    — light gradient with image floated right
 *     and text on the left. Miniscope.org style. Pairs with theme=light.
 *
 * Stacking inside the hero box (z-index from back to front):
 *   0. .wiki-hero background — fallback gradient (visible if no image
 *      or if the image fails to load)
 *   1. .wiki-hero__media     — the [[File:...]] image, object-fit: cover
 *   2. .wiki-hero::before    — readability overlay (variant-specific)
 *   3. .wiki-hero__content   — text and actions
 *
 * Theme tokens via var(--labki-*, literal). Geometry stays literal —
 * MW 1.44.5 / css-sanitizer 5.5.0 accepts var() in `background`,
 * `color`, and `border` shorthand, but rejects it in `border-radius`,
 * `box-shadow`, `padding`, `margin`, `transition`, `transform`,
 * `inset`, `top/right/bottom/left`, `width`, `height`, `z-index`, and
 * most other numeric properties. The hero's geometry rarely needs to
 * vary by theme anyway.
 *
 * Page-shell concerns DO NOT live here — TemplateStyles auto-scopes
 * selectors under .mw-parser-output, so body- and html-scoped rules
 * can't migrate into this file. The wiki's MediaWiki:Common.css must
 * still carry:
 *   * body.page-Main_Page / body.mainpage padding neutralizers (so
 *     the negative horizontal margins reach the content card edge)
 *   * .hero-btn-anon / .hero-btn-user visibility against
 *     body.tweeki-user-anon
 * See Template:UI/hero docstring for the exact CSS to keep on the wiki.
 */

/* ============================================================
   BASE
   ============================================================ */

.wiki-hero {
	position: relative;
	overflow: hidden;
	margin: -32px -40px 32px;
	padding: 72px 40px 60px;
	border-radius: 8px 8px 0 0;
	z-index: 0;
}

.wiki-hero__media {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 1;
}

.wiki-hero__media img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Readability overlay sits above the image, below the content. The
   actual gradient stack is set per variant below.
   No `pointer-events: none` even though the overlay covers the hero —
   the css-sanitizer 5.5.0 used by TemplateStyles rejects that property
   (templatestyles-error-unrecognized-property). It's not needed here
   anyway: the overlay has no event handler, the image below it
   renders without an <a> wrapper (link= empty), and content sits
   above on z-index 3, so nothing interactive is being intercepted. */
.wiki-hero::before {
	content: "";
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 2;
}

.wiki-hero__content {
	position: relative;
	z-index: 3;
	max-width: 720px;
}

.wiki-hero__eyebrow {
	font-size: 0.85rem;
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: 0.18em;
	margin: 0 0 12px;
}

.wiki-hero__title {
	font-size: 3.25rem;
	font-weight: 800;
	line-height: 1.05;
	margin: 0 0 18px;
	letter-spacing: -0.02em;
}

.wiki-hero__tagline {
	font-size: 1.1rem;
	line-height: 1.55;
	margin: 0 0 24px;
	max-width: 580px;
}

.wiki-hero__actions {
	margin-top: 8px;
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
}

/* ============================================================
   THEME: dark
   White text on a dimmed image. The fallback gradient on
   .wiki-hero shows through if no image is provided. The overlay
   on ::before guarantees text contrast on any image.
   ============================================================ */

.wiki-hero--dark {
	color: #ffffff;
	background: linear-gradient(135deg, #000000 0%, #0e1c2e 50%, var(--labki-primary, #003B5C) 100%);
}

.wiki-hero--dark::before {
	background:
		radial-gradient(ellipse 640px 280px at center,
			rgba(0, 0, 0, 0.55) 0%,
			rgba(0, 0, 0, 0.20) 70%,
			rgba(0, 0, 0, 0) 100%),
		linear-gradient(rgba(0, 0, 0, 0.35), rgba(0, 0, 0, 0.50));
}

.wiki-hero--dark .wiki-hero__eyebrow {
	color: rgba(255, 255, 255, 0.85);
	text-shadow: 0 1px 8px rgba(0, 0, 0, 0.6);
}

.wiki-hero--dark .wiki-hero__title {
	color: #ffffff;
}

.wiki-hero--dark .wiki-hero__tagline {
	color: rgba(255, 255, 255, 0.82);
}

/* The platform's labki-tweeki.css recolors links inside
   .mw-parser-output; the hero sits on dark and needs to override
   that with !important. Same pattern the pre-template Common.css
   used.
   Plain `text-decoration: underline` only — the css-sanitizer 5.5.0
   used by TemplateStyles rejects the CSS Text Decoration Level 4
   properties (`text-underline-offset`, `text-decoration-thickness`,
   `text-decoration-color` as a transition target) with
   templatestyles-error-unrecognized-property. Default browser
   underline placement and weight are acceptable. */
.wiki-hero--dark .wiki-hero__tagline a,
.wiki-hero--dark .wiki-hero__tagline a:visited {
	color: #ffffff !important;
	text-decoration: underline;
	transition: color 0.15s;
}

.wiki-hero--dark .wiki-hero__tagline a:hover {
	color: rgba(255, 255, 255, 0.78) !important;
}

/* ============================================================
   THEME: light
   Dark text on a light gradient. Used by the product variant
   most often, but theme is independent of variant.
   ============================================================ */

.wiki-hero--light {
	color: var(--labki-heading, #003B5C);
	background:
		linear-gradient(90deg,
			rgba(246, 248, 250, 1) 0%,
			rgba(248, 249, 250, 0.95) 38%,
			rgba(238, 241, 244, 1) 100%);
}

.wiki-hero--light .wiki-hero__eyebrow {
	color: var(--labki-accent, #2774AE);
}

.wiki-hero--light .wiki-hero__title {
	color: var(--labki-heading, #003B5C);
}

.wiki-hero--light .wiki-hero__tagline {
	color: var(--labki-text-muted, #5a6a7a);
}

/* ============================================================
   VARIANT: product
   Image anchored right; readability fade gives the left half a
   safe text zone. Pairs naturally with align=left.
   ============================================================ */

.wiki-hero--product .wiki-hero__media img {
	object-position: right center;
}

/* The fade ends at 70% of the hero's width so the rightmost ~30%
   shows the image untouched — that's the product showcase zone.
   Stops at 0/25/45/70% give a soft curve that keeps the text
   readable in the left half without abruptly cutting off. */
.wiki-hero--product.wiki-hero--light::before {
	background:
		linear-gradient(90deg,
			rgba(248, 249, 250, 0.96) 0%,
			rgba(248, 249, 250, 0.82) 25%,
			rgba(248, 249, 250, 0.20) 45%,
			rgba(248, 249, 250, 0.00) 70%);
}

/* Dark counterpart — same stop positions for a consistent curve,
   black instead of off-white. Without this, .wiki-hero--dark::before
   (the centered spotlight from the background variant) would apply
   to product+dark and dim the image globally, defeating the
   right-side showcase. Higher specificity than .wiki-hero--dark::before
   so this one wins for the product+dark combination. */
.wiki-hero--product.wiki-hero--dark::before {
	background:
		linear-gradient(90deg,
			rgba(0, 0, 0, 0.92) 0%,
			rgba(0, 0, 0, 0.78) 25%,
			rgba(0, 0, 0, 0.18) 45%,
			rgba(0, 0, 0, 0.00) 70%);
}

/* ============================================================
   ALIGNMENT
   Drives content block position, text-align, and action-row
   justification together so a single param flips all three.
   ============================================================ */

.wiki-hero--align-center .wiki-hero__content {
	margin-left: auto;
	margin-right: auto;
	text-align: center;
}

.wiki-hero--align-center .wiki-hero__tagline {
	margin-left: auto;
	margin-right: auto;
}

.wiki-hero--align-center .wiki-hero__actions {
	justify-content: center;
}

.wiki-hero--align-left .wiki-hero__content {
	margin-left: 0;
	margin-right: auto;
	text-align: left;
}

.wiki-hero--align-left .wiki-hero__actions {
	justify-content: flex-start;
}

.wiki-hero--align-right .wiki-hero__content {
	margin-left: auto;
	margin-right: 0;
	text-align: right;
}

.wiki-hero--align-right .wiki-hero__actions {
	justify-content: flex-end;
}

/* ============================================================
   RESPONSIVE
   Tighter padding and smaller type below 768px. Border radius
   drops to 0 because on narrow screens the content card is
   already edge-to-edge and rounded corners look broken.
   ============================================================ */

@media (max-width: 768px) {
	.wiki-hero {
		margin: -20px -18px 24px;
		padding: 48px 20px 44px;
		border-radius: 0;
	}
	.wiki-hero__title {
		font-size: 2.25rem;
	}
	.wiki-hero__tagline {
		font-size: 1rem;
	}
}