Template:Category/Workshop/styles.css

From Miniscope
Jump to: navigation, search
/* TemplateStyles for the Workshop page idiom — shared between
 * {{Category/Workshop}} (public landing) and
 * {{Category/Workshop internal hub}} (participant-only hub).
 *
 * Covers:
 *   * .workshop-banner-wrap — image with overlay text (title + dates +
 *     location across the bottom)
 *   * .workshop-meta — fallback inline meta row (when no banner image
 *     is set)
 *   * .workshop-status-block — full-block tinted by state, with a big
 *     heading; replaces the small-chip treatment from the first cut
 *   * .workshop-description, .workshop-details-list, .workshop-flyer
 *     — public-page specific
 *   * .workshop-hub-* — internal-hub specific
 *
 * Theme tokens via var(--labki-*, literal). MW 1.44.5 / css-sanitizer
 * 5.5.0 accepts var() in `background`, `color`, and `border` shorthand,
 * but rejects it in `border-radius`, `border-color` longhand, padding,
 * margin, etc. Status-state colors stay literal because they're
 * discrete state signals, not theme tokens.
 *
 * No aspect-ratio, no -webkit-* properties (both rejected by the
 * labki-platform sanitizer). Image proportions come from the natural
 * size of Has banner (3:1) or Has card image (4:3); the latter is
 * capped via max-height to avoid dominating the page header.
 */

/* ================================================================
   Banner with overlay text
   z-index stack:
     1. .workshop-banner-img — the [[File:...]] image
     2. .workshop-banner-wrap::after — dark gradient for legibility
     3. .workshop-banner-content — title + meta on top
   ================================================================ */

.workshop-banner-wrap {
	position: relative;
	margin: 0 0 24px;
	border-radius: 8px;
	overflow: hidden;
	border: 1px solid var(--labki-border, #d8dde3);
}

.workshop-banner-img {
	position: relative;
	z-index: 1;
	line-height: 0;
}

.workshop-banner-img img {
	display: block;
	width: 100%;
	height: auto;
}

/* When falling back to Has card image (4:3) instead of Has banner
 * (3:1), the image is taller. Cap max-height so the banner doesn't
 * dominate the page header. object-fit: cover crops to the visible
 * region centered. */
.workshop-banner-img--fallback img {
	max-height: 360px;
	object-fit: cover;
}

/* Readability overlay — dark gradient fading from opaque at the
 * bottom (where the title sits) to transparent at the top. Same idiom
 * as {{UI/upcoming_events_featured}}'s overlay; tuned slightly more
 * subtle here since the banner image is shorter (3:1 vs 4:3) and the
 * text band is narrower. */
.workshop-banner-wrap::after {
	content: "";
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 2;
	background: linear-gradient(to top,
		rgba(0, 0, 0, 0.75) 0%,
		rgba(0, 0, 0, 0.45) 35%,
		rgba(0, 0, 0, 0.05) 75%,
		rgba(0, 0, 0, 0.00) 100%);
}

.workshop-banner-content {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	padding: 20px 28px 24px;
	z-index: 3;
	color: #ffffff;
}

.workshop-banner-title {
	font-size: 2em;
	font-weight: 700;
	line-height: 1.15;
	margin: 0 0 6px;
	text-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
}

.workshop-banner-meta {
	display: flex;
	flex-wrap: wrap;
	gap: 0 12px;
	font-size: 1em;
	color: rgba(255, 255, 255, 0.92);
	line-height: 1.4;
}

.workshop-banner-meta > span:not(:last-child)::after {
	content: "·";
	margin-left: 12px;
	color: rgba(255, 255, 255, 0.55);
}

/* ================================================================
   Fallback meta line — used when no banner image is set
   ================================================================ */

.workshop-meta {
	display: flex;
	flex-wrap: wrap;
	gap: 0 12px;
	font-size: 1em;
	color: var(--labki-text-muted, #5a6a7a);
	margin: 0 0 16px;
	line-height: 1.5;
}

.workshop-meta > span:not(:last-child)::after {
	content: "·";
	margin-left: 12px;
	color: var(--labki-text-faint, #a0a8b0);
}

.workshop-meta-date {
	font-weight: 600;
	color: var(--labki-text, #1c1c1c);
}

/* ================================================================
   Status block — full-block tinted, big heading + detail + CTA
   ================================================================ */

.workshop-status-block {
	margin: 0 0 24px;
	padding: 20px 24px;
	border: 1px solid var(--labki-border, #d8dde3);
	border-radius: 8px;
	background: var(--labki-bg-subtle, #f8f9fa);
}

/* Per-state full-block tinting. Literal colors (no var) because the
 * sanitizer rejects var() in `border-color` longhand. These are
 * discrete state signals, not theme tokens, so literals are
 * appropriate. */
.workshop-status-block--open {
	background: #e6f5eb;
	border-color: #27AE60;
}

.workshop-status-block--soon {
	background: #e8f0f7;
	border-color: #2774AE;
}

.workshop-status-block--closed {
	background: #fcf3cf;
	border-color: #B7950B;
}

.workshop-status-block--now {
	background: #d4f0e0;
	border-color: #27AE60;
}

.workshop-status-block--past {
	background: #ececec;
	border-color: #c0c0c0;
}

.workshop-status-block--cancelled {
	background: #fbeaea;
	border-color: #c0392b;
}

.workshop-status-block--postponed {
	background: #fcf3cf;
	border-color: #B7950B;
}

/* Big state heading. Not an <h*> element to avoid MW's auto-anchor
 * TOC clutter — styled like a heading via CSS instead. */
.workshop-status-heading {
	font-size: 1.6em;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.01em;
	margin: 0;
}

.workshop-status-heading--open { color: #196f3d; }
.workshop-status-heading--soon { color: #1c4e7a; }
.workshop-status-heading--closed { color: #7d6608; }
.workshop-status-heading--now { color: #196f3d; }
.workshop-status-heading--past { color: #555555; }
.workshop-status-heading--cancelled { color: #922b21; }
.workshop-status-heading--postponed { color: #7d6608; }

.workshop-status-detail {
	margin: 8px 0 0;
	font-size: 0.95em;
	color: var(--labki-text-muted, #5a6a7a);
}

.workshop-status-cta {
	margin-top: 14px;
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
}

/* ================================================================
   Description — italic intro paragraph
   ================================================================ */

.workshop-description {
	font-size: 1.08em;
	line-height: 1.6;
	color: var(--labki-text, #1c1c1c);
	font-style: italic;
	margin: 0 0 20px;
}

/* ================================================================
   Details list — Type / Dates / Location / Timezone / Status
   ================================================================ */

.workshop-details {
	margin: 24px 0;
}

.workshop-details-list {
	list-style: none;
	padding: 0;
	margin: 8px 0 0;
}

.workshop-details-list li {
	padding: 8px 0;
	border-bottom: 1px solid var(--labki-border, #d8dde3);
	font-size: 0.95em;
	line-height: 1.5;
}

.workshop-details-list li:last-child {
	border-bottom: none;
}

.workshop-details-list strong {
	display: inline-block;
	min-width: 110px;
	color: var(--labki-text-muted, #5a6a7a);
	font-weight: 600;
}

/* ================================================================
   Flyer — portrait promo image at the bottom of the public page,
   clicks open the full-size file via {{filepath:}} (set in the
   template's link= param, not here)
   ================================================================ */

.workshop-flyer {
	margin: 24px 0;
	text-align: center;
}

.workshop-flyer img {
	max-width: 100%;
	height: auto;
	border: 1px solid var(--labki-border, #d8dde3);
	border-radius: 4px;
}

/* ================================================================
   Internal hub specifics
   ================================================================ */

.workshop-hub-context {
	margin: 16px 0;
	font-size: 0.95em;
	color: var(--labki-text-muted, #5a6a7a);
	font-style: italic;
}

.workshop-hub-external {
	margin: 24px 0 0;
}

.workshop-hub-external h2 {
	margin-bottom: 8px;
}

.workshop-hub-external-list {
	list-style: none;
	padding: 0;
	margin: 0;
}

.workshop-hub-external-list li {
	padding: 6px 0;
	font-size: 0.95em;
}

.workshop-hub-external-list strong {
	display: inline-block;
	min-width: 160px;
	color: var(--labki-text-muted, #5a6a7a);
	font-weight: 600;
}