/*
Theme Name: MMO Culture Modern
Template: goodlife-wp
Description: MMO Culture's modern theme — sidebar/bottom-nav shell, light+dark themes, card-based layout, per the Claude Design handoff.
Version: 1.0.0
Text Domain: mmoculture-modern
*/

/* Dark is the theme's default: these are the dark values, and the light palette
   is the override under [data-theme="light"] below. Done this way round rather
   than defaulting to light and switching with JS, so a reader with JavaScript
   disabled — or one who sees the page before the bootstrap in functions.php runs
   — still gets dark rather than a flash of the wrong theme. */
:root {
	--bg: #1a1a1a;
	--card: #232323;
	--ink: #f4f4f4;
	--mut: #9d9d9d;
	--bd: #323232;
	--soft: #282828;
	--acc: #a385ff;
	--accSoft: #2c2340;
	--amber: #f5c15a;
	--shadow: 0 1px 2px rgba(0,0,0,0.4);
	/* Cast upward, for surfaces that rise from the bottom edge. */
	--shadow-up: 0 -4px 20px rgba(0,0,0,0.45);
	--font-ui: 'Plus Jakarta Sans', Arial, sans-serif;
	--font-mono: 'DM Mono', 'Courier New', monospace;
	--sidebar-w: 268px;
	--rail-w: 312px;
	/* Height of the mobile bottom nav. Everything that has to sit clear of it
	   reads this rather than repeating the number, so the bar can be resized in
	   one place. The safe-area inset is folded in here so devices with a home
	   indicator get a taller bar; the nav adds the same inset to its own bottom
	   padding, keeping the icons and labels above the indicator. */
	--bottom-nav-h: calc(64px + env(safe-area-inset-bottom, 0px));
	/* Height of the sticky mobile header. The titlebar below it reads this to
	   park itself directly underneath instead of sliding out of sight behind
	   it, so the two have to agree — hence one number for both. */
	--mobile-header-h: 56px;
	/* Desktop height of the featured block. Given rather than derived because the
	   two side cards fill it as 1fr rows — without a definite height they would
	   size to their own content and the hero spanning both would follow, so the
	   block's height would drift with whatever the headlines do. */
	--featured-h: 576px;
	/* Narrowest layout the theme is designed for. Below this the page scrolls
	   sideways rather than compressing further: at 320px the paired featured
	   cards and the bottom nav's five tabs both lose more than they gain from
	   shrinking. */
	--min-w: 360px;

	/* Spacing: 8px grid. --space-half is the only sub-step, reserved for
	   tight intra-component spacing (icon gaps, badge padding). */
	--space-half: 4px;
	--space-1: 8px;
	--space-2: 16px;
	--space-3: 24px;
	--space-4: 32px;
	--space-5: 40px;

	/* Line height scales inversely with type size: a modular ratio is right for
	   font sizes but wrong here, because leading is a function of size and
	   measure. Large type needs proportionally less of it, small type more.
	   Values are chosen to land on or near the 4px sub-grid at each token's
	   intended size. */
	--lh-flat: 1;        /* fixed-height centred controls; padding owns the box */
	--lh-display: 1.12;  /* 32px+ display        36 -> 40px */
	--lh-heading: 1.25;  /* 19-26px headings     23 -> 29px */
	--lh-snug: 1.35;     /* 14-15px UI titles    15 -> 20px */
	--lh-ui: 1.45;       /* 11-13px meta/labels  11 -> 16px */
	--lh-body: 1.65;     /* reading copy         19 -> 31px */
}

/* Light, for readers who have chosen it with the toggle. */
:root[data-theme="light"] {
	--bg: #e8ecf1;
	--card: #fbfcfd;
	--ink: #16181d;
	--mut: #6d7480;
	--bd: #dfe4ea;
	--soft: #eef1f5;
	--acc: #7c3aed;
	--accSoft: #efe9ff;
	--amber: #f5a524;
	--shadow: 0 1px 2px rgba(22,24,29,0.05);
	--shadow-up: 0 -4px 20px rgba(22,24,29,0.10);
}

.mmoc-body, .mmoc-body *, .mmoc-body *::before, .mmoc-body *::after {
	box-sizing: border-box;
}

.mmoc-body {
	background: var(--bg);
	color: var(--ink);
	font-family: var(--font-ui);
	line-height: var(--lh-ui);
	margin: 0;
	text-wrap: pretty;
	/* Floor for the whole layout — see --min-w. Everything else is inside the
	   body, so this is the one place it needs stating. */
	min-width: var(--min-w);
}

/* The fixed bars size to the viewport, not to the body, so on a narrower screen
   they would sit at 320px while the content they belong to is 360px wide and
   scrolled — the nav would drift out of line with the page under it. Giving them
   the same floor keeps the whole chrome on one width. */
.mmoc-bottom-nav,
.mmoc-anchor-ad {
	min-width: var(--min-w);
}

/* :where() keeps this at (0,1,0) so it still outranks the parent theme's bare
   `h1 { line-height: 1.15 }` while staying a baseline that component title
   classes below can override. Without it this rule scored (0,1,1) and silently
   beat every .mmoc-*__title, pinning them all to the heading value. */
.mmoc-body :where(h1, h2, h3) {
	font-family: var(--font-ui);
	font-weight: 800;
	line-height: var(--lh-heading);
	letter-spacing: -0.02em;
	margin: 0;
	color: var(--ink);
	text-wrap: pretty;
}

.mmoc-body a {
	text-decoration: none;
	color: inherit;
}

.mmoc-body img {
	max-width: 100%;
	display: block;
}

/* The parent theme ships `body p { font-size: 16px; line-height: 1.6em }` and
   `ul { line-height: 1.6 }`, which outrank the inherited value from every
   container below and were silently overriding their type — the article body
   read 16px/25.6px instead of its own 19px, and every list snapped to 1.6.
   Re-assert inheritance so each block's scale actually reaches its text.
   :where() keeps this at (0,1,0) so component classes below still win. */
.mmoc-body :where(p, ul, ol, li, dl, dt, dd, blockquote, figcaption, td, th) {
	font-size: inherit;
	line-height: inherit;
}

.mmoc-eyebrow {
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	line-height: var(--lh-ui);
	color: var(--acc);
}

.mmoc-meta {
	font-size: 12px;
	line-height: var(--lh-ui);
	color: var(--mut);
}

.mmoc-ad {
	background: var(--soft);
	border-radius: 14px;
	display: flex;
	align-items: center;
	justify-content: center;
	color: var(--mut);
	font-family: var(--font-mono);
	font-size: 12px;
	overflow: hidden;
}

.mmoc-ad--home_top { min-height: 250px; }

/* Site-wide leaderboard band. Full-bleed and above the shell, so it clears the
   sidebar rather than sitting inside the content column. Dark in both themes —
   it reads as ad chrome, not as page surface. */
.mmoc-topad {
	background: #0b0c10;
	display: flex;
	justify-content: center;
	padding: var(--space-2);
}

.mmoc-topad .mmoc-ad {
	width: 100%;
	max-width: 970px;
	border-radius: 12px;
}

@media (max-width: 899px) {
	.mmoc-topad {
		padding: var(--space-1);
	}

	/* Mobile creatives are 320x100 / 300x100 — reserving 250px of height here
	   would push the whole page below the fold. */
	.mmoc-topad .mmoc-ad--home_top {
		min-height: 100px;
		max-width: 320px;
	}
}
.mmoc-ad--feed_inline { min-height: 250px; }
.mmoc-ad--feed_end { min-height: 250px; }

/* Desktop-only leaderboard above the Fresh Codes section. Hidden below the
   shell's 899px breakpoint, where a 728px-wide unit has nowhere to sit. */
.mmoc-ad--codes_top { min-height: 90px; }

@media (max-width: 899px) {
	.mmoc-ad--codes_top { display: none; }
}
/* Above Top Stories: an MREC on phones, a 728x90 leaderboard on desktop. The
   two shapes are far enough apart that one reserved height would either strand
   200px of empty space on desktop or shove the section below the fold on mobile,
   so each breakpoint reserves its own. */
.mmoc-ad--top_stories { min-height: 250px; }

@media (min-width: 900px) {
	.mmoc-ad--top_stories {
		min-height: 90px;
		/* Centres the 728 unit in the wider content column instead of leaving it
		   hanging on the left. align-self, not auto margins: .mmoc-page__main is
		   a flex column, and auto margins on the cross axis there collapse the
		   box to its content width instead of centring a full-width one. */
		width: 100%;
		max-width: 728px;
		align-self: center;
	}
}

/* Reserved boxes match the size each slot declares in inc/ads.php — a 300x600
   half page reserving 250px told the reader the wrong thing and would shift the
   page by 350px when the ad filled. Width is capped too, and centred with
   align-self because .mmoc-rail is a flex column where auto margins on the cross
   axis collapse the box to its content instead. */
.mmoc-ad--rail_top {
	min-height: 600px;
	/* width with max-width, not max-width alone: align-self centres the box but
	   also makes it size to its content on the cross axis, and the only child is
	   an absolutely-positioned caption — so the box collapsed to 0 wide. */
	width: 100%;
	max-width: 300px;
	align-self: center;
}
.mmoc-ad--rail_sticky {
	min-height: 600px;
	/* width with max-width, not max-width alone: align-self centres the box but
	   also makes it size to its content on the cross axis, and the only child is
	   an absolutely-positioned caption — so the box collapsed to 0 wide. */
	width: 100%;
	max-width: 160px;
	align-self: center;
	position: sticky;
	top: 80px;
}
.mmoc-ad--post_intro, .mmoc-ad--post_mid { min-height: 200px; margin: var(--space-3) 0; }
.mmoc-ad--anchor { min-height: 54px; max-height: 100px; }
.mmoc-ad--extra_square { min-height: 200px; }

/* The interstitial's own box, so the panel is the size of the creative it is
   waiting for rather than collapsing to nothing. */
.mmoc-ad--interstitial {
	min-height: 480px;
	max-width: 320px;
	width: 100%;
	align-self: center;
}

/* In-feed slots. The label sits behind the ad unit, so the container has to be
   the positioning context and the unit has to sit on top of it. */
.mmoc-ad {
	position: relative;
}

.mmoc-ad__unit {
	position: relative;
	z-index: 1;
}

.mmoc-ad__label {
	/* Centred in the reserved box and out of the way: it is a caption for an
	   empty slot, never something to click or select. */
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	padding: 0 var(--space-2);
	pointer-events: none;
}

/* Gone the moment the ad stack puts something in the unit, so a filled slot
   never has a size caption sitting behind the creative. Cheaper and more
   reliable than watching for it in script, and it reverses by itself if the
   slot is later emptied. */
.mmoc-ad:has(.mmoc-ad__unit > *) .mmoc-ad__label {
	display: none;
}

/* Spans the archive grid rather than taking one cell of two. */
.mmoc-grid .mmoc-ad--feed-slot {
	grid-column: 1 / -1;
}

/* Every second in-feed slot stands down once there is room for four articles
   between ads. theme.js only activates the units that are still displayed, so a
   slot hidden here costs no ad request. */
@media (min-width: 900px) {
	.mmoc-ad--feed-slot--narrow {
		display: none;
	}
}

.mmoc-shell {
	display: block;
}

@media (min-width: 900px) {
	.mmoc-shell {
		display: grid;
		grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
	}
}

.mmoc-sidebar {
	display: none;
}

@media (min-width: 900px) {
	.mmoc-sidebar {
		display: flex;
		flex-direction: column;
		background: var(--card);
		border-right: 1px solid var(--bd);
		padding: var(--space-3) var(--space-2);
		position: sticky;
		top: 0;
		height: 100vh;
		overflow-y: auto;
	}
}

.mmoc-sidebar__logo {
	padding: 0 var(--space-1) var(--space-3);
	display: block;
}

.mmoc-sidebar__logo img {
	width: 168px;
}

/* The wordmark is a dark PNG, so it needs inverting on the dark default and
   leaving alone in light. */
.mmoc-sidebar__logo img {
	filter: invert(1) brightness(1.9);
}

:root[data-theme="light"] .mmoc-sidebar__logo img {
	filter: none;
}

.mmoc-sidebar__nav {
	display: flex;
	flex-direction: column;
	gap: var(--space-half);
}

/* Prefixed for the same reason as the interstitial button above: without it
   `.mmoc-body a { color: inherit }` wins and every inactive sidebar link renders
   at --ink, as bright as the active one, losing the muted/current distinction the
   bottom nav has. */
.mmoc-body .mmoc-navlink {
	display: flex;
	align-items: center;
	gap: var(--space-2);
	padding: var(--space-1) var(--space-2);
	min-height: 40px;
	border-radius: 11px;
	font-size: 15px;
	font-weight: 600;
	line-height: var(--lh-snug);
	color: var(--mut);
}

/* Prefixed too, so it stays above the base rule rather than relying on the two
   tying on specificity and this one happening to come later in the file. */
.mmoc-body .mmoc-navlink.is-active {
	background: var(--accSoft);
	color: var(--acc);
}

.mmoc-navlink__icon svg,
.mmoc-theme-toggle__icon svg {
	width: 20px;
	height: 20px;
}

/* An inline SVG sits on the text baseline, so its box carries a couple of pixels
   of descender space below the glyph — a 20px icon in a 24px box. The glyph then
   renders ~2px above the centre of the label beside it, and align-items: center
   on the row cannot correct it: it is centring the box, which is already
   centred. Block-level icons have no baseline and no phantom space, so the glyph
   and the label share a centre line. Applied to every icon paired with text or
   centred in a control. */
.mmoc-navlink__icon svg,
.mmoc-theme-toggle__icon svg,
.mmoc-bottom-nav__icon svg,
.mmoc-mobile-header__search svg,
.mmoc-sheet__close svg,
.mmoc-more-sheet__item svg,
.mmoc-adjacent__dir svg {
	display: block;
}

.mmoc-theme-toggle--mobile .mmoc-theme-toggle__icon svg {
	width: 18px;
	height: 18px;
}

/* The toggle carries both icons; aria-pressed (set by theme.js) picks which
   one shows, so the swap needs no JS of its own. */
.mmoc-theme-toggle .mmoc-icon--sun,
.mmoc-theme-toggle[aria-pressed="true"] .mmoc-icon--moon {
	display: none;
}

.mmoc-theme-toggle[aria-pressed="true"] .mmoc-icon--sun {
	display: block;
}

.mmoc-theme-toggle {
	display: flex;
	align-items: center;
	gap: var(--space-2);
	padding: var(--space-1) var(--space-2);
	min-height: 40px;
	border-radius: 11px;
	border: none;
	background: none;
	font-family: var(--font-ui);
	font-size: 15px;
	font-weight: 600;
	color: var(--mut);
	cursor: pointer;
	margin-top: auto;
	text-align: left;
}

.mmoc-mobile-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	/* Fixed height rather than padding-driven: the titlebar sticks to the
	   bottom of this bar, so its height has to be a number both can use. The
	   border is inside it — box-sizing is border-box. */
	height: var(--mobile-header-h);
	padding: 0 var(--space-2);
	background: var(--bg);
	position: sticky;
	top: 0;
	z-index: 50;
	border-bottom: 1px solid var(--bd);
}

@media (min-width: 900px) {
	.mmoc-mobile-header {
		display: none;
	}
}

.mmoc-mobile-header__logo img {
	width: 104px;
}

/* The wordmark is a dark PNG, so it needs inverting on the dark default and
   leaving alone in light. */
.mmoc-mobile-header__logo img {
	filter: invert(1) brightness(1.9);
}

:root[data-theme="light"] .mmoc-mobile-header__logo img {
	filter: none;
}

/* 36px, not the 44px this used to be: the header is now 56px tall and a 44px
   control left it no breathing room. The 44px touch target is preserved by the
   header's own height — the control is centred in a 56px bar with nothing else
   to hit. */
.mmoc-theme-toggle--mobile {
	width: 36px;
	height: 36px;
	min-height: 0;
	border-radius: 10px;
	background: var(--card);
	justify-content: center;
	margin-top: 0;
	padding: 0;
}

/* The header's trailing controls. Without this wrapper the header's
   space-between would spread three children across the bar and float the search
   control into the middle. */
.mmoc-mobile-header__actions {
	display: flex;
	align-items: center;
	gap: var(--space-1);
}

/* Same box as the theme toggle beside it — the two read as one pair. */
.mmoc-mobile-header__search {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	padding: 0;
	border: 0;
	border-radius: 10px;
	background: var(--card);
	/* Same --mut as the theme toggle it sits beside — the pair is one set of
	   header affordances, and --ink made this one read as the loud sibling. */
	color: var(--mut);
	cursor: pointer;
}

.mmoc-mobile-header__search:hover {
	color: var(--ink);
}

/* Matching .mmoc-theme-toggle__icon svg next to it rather than the bottom nav's
   22px — these two sit side by side and are read together. */
.mmoc-mobile-header__search svg {
	width: 18px;
	height: 18px;
}

/* The control carries both marks and aria-expanded picks which one shows, the
   same arrangement .mmoc-theme-toggle uses for its moon and sun — so the swap to
   a dismiss needs no JS beyond the attribute the button already sets. */
.mmoc-mobile-header__search .mmoc-icon--close,
.mmoc-mobile-header__search[aria-expanded="true"] .mmoc-icon--search {
	display: none;
}

.mmoc-mobile-header__search[aria-expanded="true"] .mmoc-icon--close {
	display: block;
}

/* The field expanded in place. It is collapsed rather than absent so the form
   stays where it is in the bar and in the tab order; the logo and the theme
   toggle stand down to give it the row, and the dismiss stays put so the
   control that opened the field is the control that closes it.

   Scoped to the mobile range because .mmoc-mobile-header is display: none above
   it, but stated anyway: the inline field must never appear beside the
   titlebar's own search on a desktop-width window. */
@media (max-width: 899px) {
	/* Prefixed with the header because the base .mmoc-search { display: flex }
	   sits further down the file: at equal specificity that one would win and
	   the field would start out expanded, pushing the logo and controls out of
	   the bar. */
	.mmoc-mobile-header .mmoc-search--inline {
		display: none;
	}

	.mmoc-mobile-header.is-searching .mmoc-search--inline {
		display: flex;
		/* Takes whatever the row has left rather than the rail width the base
		   rule gives every other copy of this field. */
		flex: 1 1 auto;
		min-width: 0;
		margin-left: 0;
	}

	.mmoc-mobile-header.is-searching .mmoc-search--inline input {
		width: 100%;
		/* The parent stylesheet sets every input to 11px, which is fine for a
		   corner affordance and far too small for the bar that has just taken
		   over the header. */
		font-size: 15px;
		/* Match the 36px dismiss beside it exactly: the base rule's vertical
		   padding would otherwise carry the field 3px past the control and the
		   pair would sit visibly uneven. */
		height: 36px;
		min-height: 0;
		padding-top: 0;
		padding-bottom: 0;
		border-radius: 10px;
	}

	.mmoc-mobile-header.is-searching .mmoc-mobile-header__logo,
	.mmoc-mobile-header.is-searching .mmoc-theme-toggle--mobile {
		display: none;
	}
}

@media (min-width: 900px) {
	.mmoc-mobile-header .mmoc-search--inline {
		display: none;
	}
}

.mmoc-mobile-header__search:focus-visible {
	outline: 2px solid var(--acc);
	outline-offset: 2px;
}

/* Shell column holding main + the site footer. min-width: 0 so a wide table or
   code block inside cannot push the grid track past its share and squeeze the
   sidebar. */
.mmoc-content {
	min-width: 0;
	display: flex;
	flex-direction: column;
}

/* Puts the footer at the bottom of the column rather than directly under short
   content, on templates that do not fill the viewport. Desktop only: the
   sidebar is already 100vh there so the page cannot get shorter than this, while
   on mobile the leaderboard and header sit above the shell and 100vh here would
   add a screen of scroll to every short page. */
@media (min-width: 900px) {
	.mmoc-content {
		min-height: 100vh;
	}
}

.mmoc-region {
	min-width: 0;
	flex: 1 0 auto;
}

.mmoc-footer {
	text-align: center;
	padding: var(--space-3) var(--space-2);
	color: var(--mut);
	font-size: 13px;
}

@media (max-width: 899px) {
	/* Room for the fixed bottom nav plus the anchor ad stacked on top of it. */
	.mmoc-footer {
		padding-bottom: calc(var(--bottom-nav-h) + 120px);
	}
}

.mmoc-anchor-ad {
	display: none;
	position: fixed;
	bottom: var(--bottom-nav-h);
	left: 0;
	right: 0;
	z-index: 90;
}

.mmoc-anchor-ad.is-visible {
	display: flex !important;
	align-items: center;
}

@media (min-width: 900px) {
	.mmoc-anchor-ad.is-visible,
	.mmoc-anchor-ad {
		display: none !important;
	}
}

.mmoc-anchor-ad .mmoc-ad {
	flex: 1;
	border-radius: 0;
}

.mmoc-anchor-ad__dismiss {
	position: absolute;
	right: 8px;
	top: 50%;
	transform: translateY(-50%);
	width: 28px;
	height: 28px;
	border-radius: 999px;
	border: none;
	background: var(--card);
	color: var(--ink);
	cursor: pointer;
}

.mmoc-bottom-nav {
	display: none;
}

@media (max-width: 899px) {
	.mmoc-bottom-nav {
		display: flex;
		position: fixed;
		bottom: 0;
		left: 0;
		right: 0;
		height: var(--bottom-nav-h);
		/* The 22px icon and its 11px label stack to 46px; at the old 54px that
		   left about 4px above and below, so both read as touching the bar's
		   edges. An 8px step each side gives the stack room inside the 64px
		   bar. box-sizing is border-box here, so the height already covers
		   this padding and the top border. */
		padding-top: var(--space-1);
		padding-bottom: calc(var(--space-1) + env(safe-area-inset-bottom, 0px));
		background: var(--card);
		border-top: 1px solid var(--bd);
		z-index: 100;
	}
}

.mmoc-bottom-nav__item {
	flex: 1;
	min-height: 44px;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: var(--space-half);
	color: var(--mut);
	font-size: 11px;
	font-weight: 700;
	background: none;
	border: none;
	font-family: var(--font-ui);
	cursor: pointer;
}

/* The Search tab used to be a <button> among four <a>s, and looked it: the
   parent stylesheet's `.mmoc-body a { color: inherit }` outranks a single class
   here, so the links picked up --ink from the bar while only the button honoured
   the --mut above — the button was right and the links were the bug. Prefixing
   with .mmoc-body puts every tab, link or button, on the same scale. Size,
   weight and spacing were already shared and are unchanged. */
.mmoc-body .mmoc-bottom-nav__item {
	color: var(--mut);
}

.mmoc-body .mmoc-bottom-nav__item.is-active {
	color: var(--acc);
}

/* Same treatment on the pointer/keyboard states, which the parent theme's own
   a:hover would otherwise take over for the links only. */
.mmoc-body .mmoc-bottom-nav__item:hover,
.mmoc-body .mmoc-bottom-nav__item:focus-visible,
/* The More tab while its sheet is open. --ink rather than the accent, so it
   reads as pressed without competing with whichever tab is actually current. */
.mmoc-body .mmoc-bottom-nav__item[aria-expanded="true"] {
	color: var(--ink);
}

.mmoc-body .mmoc-bottom-nav__item.is-active:hover,
.mmoc-body .mmoc-bottom-nav__item.is-active:focus-visible {
	color: var(--acc);
}

.mmoc-body .mmoc-bottom-nav__item:focus-visible {
	outline: 2px solid var(--acc);
	outline-offset: -2px;
	border-radius: 8px;
}

.mmoc-bottom-nav__icon svg {
	width: 22px;
	height: 22px;
}

/* Bottom sheet. The More nav is the only one left — search now expands in
   place in the header, next to the control that opens it — but the chrome stays
   factored out under .mmoc-sheet rather than folded into .mmoc-more-sheet, so a
   second sheet does not have to reinvent it.

   It rises from the bottom edge and stops on top of the nav, so it appears
   where it was summoned from.

   display stays none outside the mobile range: the sheet has no trigger there
   (the bottom nav is hidden), and leaving it laid out would let a
   desktop-width window paint it over the footer. */
.mmoc-sheet {
	display: none;
}

@media (max-width: 899px) {
	.mmoc-sheet {
		display: block;
		position: fixed;
		left: 0;
		right: 0;
		/* Sits on the nav rather than over it, so the reader keeps the tabs and
		   can see which one is open. */
		bottom: var(--bottom-nav-h);
		/* Above the anchor ad (90), below the nav (100). */
		z-index: 95;
		background: var(--card);
		border-top: 1px solid var(--bd);
		/* Only the leading corners round — the trailing edge meets the nav. */
		border-radius: 16px 16px 0 0;
		box-shadow: var(--shadow-up);
		padding: var(--space-1) var(--space-2) var(--space-2);
		/* Parked one sheet-height down, which for a sheet anchored above the nav
		   means fully behind the nav and off-screen. Kept in flow and hidden
		   with visibility instead of display so the slide can animate; the
		   delayed visibility lets it play on the way out too. */
		transform: translateY(100%);
		visibility: hidden;
		transition: transform .24s ease, visibility 0s linear .24s;
	}

	.mmoc-sheet.is-open {
		transform: translateY(0);
		visibility: visible;
		transition: transform .24s ease, visibility 0s;
	}

	.mmoc-sheet__head {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: var(--space-2);
		margin-bottom: var(--space-2);
	}

	.mmoc-sheet__title {
		font-size: 17px;
		font-weight: 700;
		line-height: var(--lh-heading);
		margin: 0;
	}

	/* 36px, the same box as the header controls that open these sheets. */
	.mmoc-sheet__close {
		display: flex;
		align-items: center;
		justify-content: center;
		flex: 0 0 auto;
		width: 36px;
		height: 36px;
		padding: 0;
		border: 0;
		border-radius: 50%;
		background: var(--soft);
		color: var(--mut);
		cursor: pointer;
	}

	.mmoc-sheet__close svg {
		width: 18px;
		height: 18px;
	}

	.mmoc-sheet__close:hover {
		color: var(--ink);
	}

	.mmoc-sheet__close:focus-visible {
		outline: 2px solid var(--acc);
		outline-offset: 2px;
	}

	/* Grab-handle: reads as a sheet, and marks the top edge as the thing that
	   moved rather than a panel that blinked into place. Decorative. */
	.mmoc-sheet::before {
		content: '';
		display: block;
		width: 36px;
		height: 4px;
		margin: 0 auto var(--space-2);
		border-radius: 999px;
		background: var(--bd);
	}

	/* More nav: the nav items the five-slot bar cannot show, as full-width rows
	   so the icon column lines up with the labels beside it. */
	.mmoc-more-sheet__list {
		display: flex;
		flex-direction: column;
	}

	.mmoc-more-sheet__item {
		display: flex;
		align-items: center;
		gap: var(--space-2);
		padding: var(--space-2) var(--space-half);
		font-size: 16px;
		font-weight: 600;
		line-height: var(--lh-snug);
	}

	.mmoc-more-sheet__item + .mmoc-more-sheet__item {
		border-top: 1px solid var(--bd);
	}

	.mmoc-more-sheet__item svg {
		width: 20px;
		height: 20px;
		flex: 0 0 auto;
		color: var(--mut);
	}

	.mmoc-more-sheet__item:focus-visible {
		outline: 2px solid var(--acc);
		outline-offset: -2px;
		border-radius: 8px;
	}
}

/* .is-open has to be named too: it carries its own transition at two classes,
   which outranks a lone .mmoc-sheet here however late it sits, so without this
   the guard only ever suppressed the slide on the way out. */
@media (prefers-reduced-motion: reduce) {
	.mmoc-sheet,
	.mmoc-sheet.is-open {
		transition: none;
	}
}

.mmoc-titlebar {
	grid-column: 1 / -1;
	position: sticky;
	top: 0;
	z-index: 45;
	/* Share the content region's track so the bar lines up with the cards
	   below it instead of stretching the full viewport on wide screens. */
	width: 100%;
	max-width: 1280px;
	margin: 0 auto;
	padding: var(--space-3) var(--space-4) var(--space-2);
	background: var(--bg);
	border-bottom: 1px solid var(--bd);
	display: flex;
	/* Without this the pills stretch to the h1's height instead of keeping
	   their own 36px pill height. */
	align-items: center;
	flex-wrap: wrap;
	gap: var(--space-2);
	row-gap: var(--space-2);
}

@media (max-width: 899px) {
	.mmoc-titlebar {
		padding: var(--space-2);
	}

	/* On this layout the wordmark sits directly above the bar, so "Home" says
	   nothing the reader cannot already see and costs the section nav a row.
	   Hidden the .screen-reader-text way rather than with display: none, so the
	   page keeps its h1 for assistive tech and the document outline. */
	.mmoc-titlebar--home .mmoc-titlebar__main {
		position: absolute;
		width: 1px;
		height: 1px;
		padding: 0;
		margin: -1px;
		overflow: hidden;
		clip: rect(0, 0, 0, 0);
		white-space: nowrap;
		border: 0;
	}

	/* The mobile header is sticky at top: 0 with a higher z-index, so a titlebar
	   also stuck at 0 slid underneath it and vanished. Parking it at the header's
	   height keeps the section nav on screen, directly below the bar. */
	.mmoc-titlebar {
		top: var(--mobile-header-h);
	}

	/* The mobile header's search control opens the sheet, so the bar's own field
	   would be a second way to do the same thing in the space the section nav
	   needs. The search page's own full-width field is untouched: it lives in
	   the content column, not in here. */
	.mmoc-titlebar .mmoc-search {
		display: none;
	}

	/* The titlebar's own share of making its pill row swipeable: flex-basis 100%
	   claims the bar's full width, and min-width: 0 lets the row shrink below its
	   contents — a nowrap flex row's min-content is the sum of its pills, so
	   without this it refuses to shrink and overflows the bar instead of
	   scrolling inside it. The swiping itself is .mmoc-pills--slide. */
	.mmoc-titlebar .mmoc-pills {
		flex: 1 1 100%;
		min-width: 0;
	}

}

/* Article header: the bar carries breadcrumb + title + byline, so it can't
   stick (it would pin most of the viewport) and needs no rule under it — the
   hero starts the content column immediately below.

   Its own grid replaces the base bar's wrapping flex row: the info column and
   the search sit side by side on one row and cannot wrap apart. The columns
   mirror .mmoc-page — same minmax(0, 1fr) + var(--rail-w) tracks, same
   var(--space-3) gap — and the two share a max-width and horizontal padding, so
   the info block lines up with the hero below it and the search lines up with
   the rail beside it. */
.mmoc-titlebar--article {
	position: static;
	border-bottom: 0;
	padding-bottom: 0;
	display: grid;
	gap: var(--space-3);
	align-items: center;
	/* One column until the rail exists — see the min-width: 1120px block below.
	   The search takes the first row rather than landing between the byline and
	   the hero, which would split the header in two. */
	grid-template-columns: minmax(0, 1fr);
}

.mmoc-titlebar--article .mmoc-titlebar__main {
	min-width: 0;
}

.mmoc-titlebar--article .mmoc-breadcrumb {
	margin-bottom: var(--space-half);
}

/* The grid track sets the width now, so the field just fills its cell instead
   of carrying the rail width itself and being pushed over by an auto margin. */
.mmoc-titlebar--article .mmoc-search {
	margin-left: 0;
	width: 100%;
	order: -1;
}

.mmoc-titlebar--article .mmoc-search input {
	width: 100%;
}

/* Two tracks at the same breakpoint .mmoc-page uses, because that is where the
   rail appears: the info column then equals the body's width and the search
   equals the aside's, side by side on one row and unable to wrap apart. Below
   this the page is a single column with no aside to match, and reserving a
   312px track there would misalign the info block from the hero and squeeze the
   headline to roughly 250px. */
@media (min-width: 1120px) {
	.mmoc-titlebar--article {
		grid-template-columns: minmax(0, 1fr) var(--rail-w);
	}

	.mmoc-titlebar--article .mmoc-search {
		order: 0;
	}
}

/* Section titlebars ("Home", "Redeem Codes") take a compact heading. The
   article variant is excluded: its own .mmoc-article__title sets 36px (25px
   under 900px), and the extra element selector here scored higher, silently
   pinning article headlines to 26px — smaller than the same story's teaser on
   the home page, and leaving that component's own sizes dead. */
.mmoc-titlebar:not(.mmoc-titlebar--article) h1 {
	font-size: 26px;
}

.mmoc-pills {
	display: flex;
	align-items: center;
	gap: var(--space-1);
	flex-wrap: wrap;
	overflow-x: auto;
}

/* One swipeable row on phones rather than wrapping into two. Wrapping costs a
   whole extra row of height above content that has not started yet — on the
   search page it pushed the results down the screen. Shared by the home section
   nav and the search filters so the two behave alike.

   The scrollbar is hidden because the partly-visible last pill is the
   affordance. Desktop keeps the wrapping row, where there is width for it. */
@media (max-width: 899px) {
	.mmoc-pills--slide {
		flex-wrap: nowrap;
		overflow-x: auto;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
		/* Keeps a pill scrolled into view clear of the row's edge. */
		scroll-padding-inline: var(--space-1);
	}

	.mmoc-pills--slide::-webkit-scrollbar {
		display: none;
	}
}

.mmoc-pill {
	white-space: nowrap;
	padding: var(--space-1) var(--space-2);
	border-radius: 999px;
	background: var(--card);
	border: 0;
	font-size: 14px;
	font-weight: 600;
	line-height: var(--lh-flat);
	color: var(--ink);
}

.mmoc-pill.is-active {
	background: var(--acc);
	color: #fff;
}

.mmoc-search {
	margin-left: auto;
	/* Without this the form's line box is taller than the input, so the titlebar
	   centres the form rather than the field the reader sees. */
	display: flex;
	/* Anchor for the leading icon, which overlays the field rather than sitting
	   beside it so the input keeps owning the form's full width. */
	position: relative;
	align-items: center;
}

.mmoc-search__icon {
	position: absolute;
	left: var(--space-2);
	width: 18px;
	height: 18px;
	color: var(--mut);
	/* Clicks fall through to the field underneath. */
	pointer-events: none;
}

/* The field shares the titlebar row with the section pills, and used to be the
   one thing in it that did not belong: 40px against their 30px, 11px text
   against their 14px, and the only surface in the row carrying a border while
   the pills and cards around it are a --card fill with --shadow. It now takes
   that same treatment, at a control height the theme already uses elsewhere
   (36px: the mobile header buttons, the sheet close). */
.mmoc-search input {
	/* The parent goodlife stylesheet puts a 24px bottom margin on every input,
	   which pushes the field off the titlebar's centre line. */
	margin: 0;
	width: var(--rail-w);
	padding: var(--space-1) var(--space-2);
	/* Clear the icon: gutter + icon + one grid step. */
	padding-left: calc(var(--space-2) + 18px + var(--space-1));
	/* Fixed rather than min-height: the vertical padding above pushes the line
	   box past 36 and the field would sit 3px off the control size it is meant
	   to match. */
	height: 36px;
	padding-top: 0;
	padding-bottom: 0;
	/* Fully rounded, like the pills it sits with. The larger copies override
	   this: they stand alone rather than in that row. */
	border-radius: 999px;
	border: 0;
	background: var(--card);
	box-shadow: var(--shadow);
	color: var(--ink);
	font-size: 14px;
	font-family: var(--font-ui);
}

/* States, which the field had none of while every other control in the chrome
   gained them. The theme's hover idiom is --mut going to --ink, so that is what
   the icon does; the ring on focus is the same one #scroll_totop and the nav
   use. A text field matches :focus-visible on click as well as on Tab, so this
   covers both. */
.mmoc-search:hover .mmoc-search__icon,
.mmoc-search:focus-within .mmoc-search__icon {
	color: var(--ink);
}

/* .mmoc-body prefix to outrank the parent stylesheet's
   `input[type="search"]:focus { background:#fff; color:#080808 }`, which is a
   near-invisible shift in light mode and turns the field white with near-black
   text in dark mode the moment it is focused. */
.mmoc-body .mmoc-search input:focus,
.mmoc-body .mmoc-search input:focus-visible {
	background: var(--card);
	color: var(--ink);
	outline: 2px solid var(--acc);
	outline-offset: 2px;
}

/* Chrome's stock clear button is a fixed-size bitmap X in its own dark slate,
   which is the one colour in the field that answers to nothing in the theme.
   Replaced with the Lucide X from the nav set, drawn as a mask so it takes a
   token and scales with the field. --mut going to --ink on hover is what every
   other dismiss here does, .mmoc-sheet__close included. */
.mmoc-search input::-webkit-search-cancel-button {
	-webkit-appearance: none;
	appearance: none;
	width: 16px;
	height: 16px;
	margin-left: var(--space-1);
	cursor: pointer;
	background-color: var(--mut);
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 6 6 18'/%3E%3Cpath d='m6 6 12 12'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 6 6 18'/%3E%3Cpath d='m6 6 12 12'/%3E%3C/svg%3E") center / contain no-repeat;
	transition: background-color .18s ease;
}

.mmoc-search input::-webkit-search-cancel-button:hover {
	background-color: var(--ink);
}

/* Scales with the 64px field, which carries a 22px leading icon. */
.mmoc-search--lg input::-webkit-search-cancel-button {
	width: 20px;
	height: 20px;
}

/* The parent goodlife stylesheet also pins every placeholder to 11px uppercase,
   so the hint arrived shouting and in a different size to the text that
   replaces it. Inheriting the field's own size and dropping the case gives one
   line of type the reader can read straight through. */
.mmoc-search input::placeholder {
	font-size: inherit;
	text-transform: none;
	font-weight: 500;
	color: var(--mut);
	/* Firefox dims placeholders a second time on top of the colour. */
	opacity: 1;
}

/* Search page: the field is the page's primary control rather than a corner
   affordance, so it spans the content column at roughly double the height. The
   base rule's margin-left: auto would otherwise shrink it to its content and
   pin it right inside .mmoc-page__main's flex column. */
.mmoc-search--lg {
	margin-left: 0;
	width: 100%;
}

.mmoc-search--lg .mmoc-search__icon {
	left: var(--space-3);
	width: 22px;
	height: 22px;
}

.mmoc-search--lg input {
	width: 100%;
	padding: var(--space-2) var(--space-3);
	padding-left: calc(var(--space-3) + 22px + var(--space-2));
	/* Back to padding-driven sizing: the base pins a 36px control height, which
	   this field is not. */
	height: auto;
	min-height: 64px;
	/* Not the base pill radius: at 64px tall a fully rounded field reads as a
	   giant capsule rather than a text box. */
	border-radius: 16px;
	font-size: 18px;
}


@media (max-width: 899px) {
	.mmoc-search--lg .mmoc-search__icon {
		left: var(--space-2);
		width: 20px;
		height: 20px;
	}

	.mmoc-search--lg input {
		padding: var(--space-1) var(--space-2);
		padding-left: calc(var(--space-2) + 20px + var(--space-1));
		height: auto;
		min-height: 52px;
		font-size: 16px;
	}
}

/* --- Scroll to top ---------------------------------------------------------
   The parent theme ships a 25px square with a 2px radius and a blue hover.
   Restyled here as a circular control matching the theme's other 40px round
   affordances, with the accent purple on hover. Selectors are prefixed with
   .mmoc-body so they outrank the parent theme's plain #scroll_totop. */
.mmoc-body #scroll_totop {
	width: 40px;
	height: 40px;
	line-height: 40px;
	border-radius: 50%;
	background: var(--card);
	border: 1px solid var(--bd);
	color: var(--mut);
	box-shadow: var(--shadow);
	display: flex;
	align-items: center;
	justify-content: center;
	transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}

.mmoc-body #scroll_totop:hover,
.mmoc-body #scroll_totop:focus-visible {
	background: var(--acc);
	border-color: var(--acc);
	color: #fff;
}

.mmoc-body #scroll_totop:focus-visible {
	outline: 2px solid var(--acc);
	outline-offset: 2px;
}

@media (max-width: 899px) {
	/* Clear the bottom nav and the anchor ad that sits on top of it. */
	.mmoc-body #scroll_totop {
		bottom: calc(var(--bottom-nav-h) + 64px);
	}
}

.mmoc-page {
	max-width: 1280px;
	margin: 0 auto;
	padding: var(--space-3) var(--space-4) var(--space-4);
	display: grid;
	gap: var(--space-3);
	grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 1120px) {
	.mmoc-page {
		grid-template-columns: minmax(0, 1fr) var(--rail-w);
	}
}

@media (max-width: 899px) {
	.mmoc-page {
		padding: var(--space-2) var(--space-2) var(--space-1);
	}
}

.mmoc-page__main {
	display: flex;
	flex-direction: column;
	gap: var(--space-3);
}

.mmoc-section {
	scroll-margin-top: 112px;
}

.mmoc-section__heading {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	margin-bottom: var(--space-2);
}

.mmoc-section__heading h2 {
	font-size: 20px;
}

/* .mmoc-body prefix because the parent stylesheet's own `.mmoc-body a { color:
   inherit }` outranks a single class, which is why this rendered near-black
   despite the accent below — the same override that was flattening the bottom
   nav. */
.mmoc-body .mmoc-see-all {
	display: inline-flex;
	align-items: center;
	gap: var(--space-half);
	font-size: 13px;
	font-weight: 700;
	color: var(--acc);
}

/* Lucide chevron-right, the same set as the nav and search icons, drawn as a
   mask so it takes currentColor and needs no markup at the five call sites. */
.mmoc-see-all::after {
	content: '';
	flex: 0 0 auto;
	width: 14px;
	height: 14px;
	background-color: currentColor;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Featured block: one column of stacked cards on phones, a 2x2 grid on desktop
   with the hero holding the whole left column and two cards stacked on the
   right. */
.mmoc-featured {
	display: grid;
	gap: var(--space-2);
	/* Two columns from the smallest screen up: the hero spans both, and the two
	   cards under it pair off in one row rather than stacking into a third and
	   fourth screenful. The desktop block below re-lays the same three items as
	   a 2x2. */
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
}

.mmoc-featured .mmoc-featured-card {
	grid-column: 1 / -1;
}

@media (max-width: 899px) {
	/* Paired, each card is half the width it had stacked, so a headline that
	   took two lines now takes four and the card grows taller than the image it
	   sits under. Three lines caps the worst of them without truncating most. */
	.mmoc-featured .mmoc-card__title {
		display: -webkit-box;
		-webkit-box-orient: vertical;
		-webkit-line-clamp: 3;
		overflow: hidden;
	}
}

@media (min-width: 900px) {
	.mmoc-featured {
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
		/* A definite height split evenly, rather than rows sized by whatever the
		   side cards happen to need: it keeps the block the same height whatever
		   the headlines do, and gives the rail a number to match. */
		height: var(--featured-h);
		grid-template-rows: 1fr 1fr;
	}

	.mmoc-featured .mmoc-featured-card {
		grid-column: 1;
		grid-row: 1 / span 2;
	}

	/* If the side query comes back empty — a thin site, or every candidate
	   already used above — the hero would hold column 1 and leave the other half
	   of the block blank. Alone, it takes the full width and the block sizes to
	   its own content instead of the 576px the pair would have set. */
	.mmoc-featured .mmoc-featured-card:only-child {
		grid-column: 1 / -1;
	}

	.mmoc-featured:has(.mmoc-featured-card:only-child) {
		height: auto;
	}

	/* The side cards now fill a row taller than their own content, so they get
	   the hero's treatment — image absorbs the slack, body stays its own size. */
	.mmoc-featured .mmoc-card {
		display: flex;
		flex-direction: column;
		min-height: 0;
	}

	.mmoc-featured .mmoc-card__media {
		height: auto;
		flex: 1 1 auto;
		min-height: 0;
	}
}

.mmoc-featured-card {
	display: block;
	background: var(--card);
	border-radius: 18px;
	overflow: hidden;
	box-shadow: var(--shadow);
}

/* Spanning two rows makes the hero taller than its own content, so it becomes a
   column with the image taking up the slack — a fixed media height would leave
   the card's background showing under the body instead. */
@media (min-width: 900px) {
	.mmoc-featured .mmoc-featured-card {
		display: flex;
		flex-direction: column;
	}

	.mmoc-featured .mmoc-featured-card__media {
		height: auto;
		flex: 1 1 auto;
		/* Floor for the case where the two side cards are short. */
		min-height: 300px;
	}

	/* 36px was set for a hero spanning the whole content column. At half that
	   width it wraps to five lines and the body claims the height the image
	   should be using, so the type comes down with the measure. */
	.mmoc-featured .mmoc-featured-card__title {
		font-size: 27px;
		line-height: var(--lh-heading);
		/* Clamped for the same reason it is smaller: the row height is fixed by
		   the two cards alongside, so every line the headline takes is a line
		   taken off the image. Three is enough for the longest titles in the
		   corpus at this measure. */
		display: -webkit-box;
		-webkit-box-orient: vertical;
		-webkit-line-clamp: 3;
		overflow: hidden;
	}
}

.mmoc-featured-card__media {
	position: relative;
	height: 330px;
	background: var(--soft);
	overflow: hidden;
}

.mmoc-featured-card__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* On phones the hero is not a hero: it is a full-width card above a pair of
   half-width ones, so it takes .mmoc-card's radius and type sizes rather than
   its own larger set. Their shared media height lives with .mmoc-card__media
   further down, which is where the value it overrides is declared. */
@media (max-width: 899px) {
	/* The featured pair is half width, so a height that suits a full-width card
	   leaves them nearly square. A ratio rather than a number: they then scale
	   with the column instead of needing a value per breakpoint. */
	.mmoc-featured .mmoc-card__media {
		height: auto;
		aspect-ratio: 16 / 9;
	}

	.mmoc-featured-card {
		border-radius: 16px;
	}
}

.mmoc-pill-badge {
	position: absolute;
	top: 14px;
	left: 14px;
	background: rgba(16,17,21,0.82);
	color: #fff;
	font-size: 11px;
	font-weight: 700;
	padding: var(--space-1) var(--space-2);
	border-radius: 999px;
	display: inline-flex;
	align-items: center;
	gap: var(--space-1);
}

.mmoc-pill-badge__dot {
	width: 7px;
	height: 7px;
	border-radius: 999px;
	background: var(--amber);
}

.mmoc-featured-card__body {
	padding: var(--space-3);
}

@media (max-width: 899px) {
	.mmoc-featured-card__body {
		padding: var(--space-2);
	}
}

.mmoc-featured-card__title {
	font-size: 36px;
	line-height: var(--lh-display);
	margin: var(--space-1) 0;
}

/* The eyebrow and byline are the card's own 11px and 12px stepped up one notch,
   so the hero reads as the same component at a larger size rather than as a
   different one. */
.mmoc-featured-card__body .mmoc-eyebrow {
	font-size: 12px;
}

.mmoc-featured-card__body .mmoc-meta {
	font-size: 13px;
}

@media (max-width: 899px) {
	/* .mmoc-card__title's size and leading — see the media note above: on phones
	   this is a card among cards, not a hero. */
	.mmoc-featured-card__title {
		font-size: 15px;
		line-height: var(--lh-snug);
	}

	.mmoc-featured-card__body .mmoc-eyebrow {
		font-size: 11px;
	}

	.mmoc-featured-card__body .mmoc-meta {
		font-size: 12px;
	}
}

.mmoc-grid {
	display: grid;
	gap: var(--space-3);
}

.mmoc-grid--2up {
	grid-template-columns: 1fr;
}

@media (min-width: 560px) {
	.mmoc-grid--2up {
		grid-template-columns: 1fr 1fr;
	}
}

.mmoc-card {
	display: block;
	background: var(--card);
	border-radius: 16px;
	overflow: hidden;
	box-shadow: var(--shadow);
}

.mmoc-card__media {
	height: 158px;
	background: var(--soft);
	overflow: hidden;
}

/* Shorter on phones, and the same number for the featured hero, which is a
   full-width card among cards there. One declaration for both so they cannot
   drift apart, and placed after both base heights: media queries add no
   specificity, so a copy of this sitting earlier in the file would simply lose
   to the 158px above. At a 343px measure 140 is still a 2.45:1 band, and it buys
   back most of a thumb-scroll on the way to the stories below. */
@media (max-width: 899px) {
	.mmoc-card__media,
	.mmoc-featured-card__media {
		height: 140px;
	}
}

.mmoc-card__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.mmoc-card__body {
	padding: var(--space-2);
}

.mmoc-card__title {
	font-size: 15px;
	line-height: var(--lh-snug);
	margin: var(--space-1) 0;
}

.mmoc-list {
	display: flex;
	flex-direction: column;
	gap: var(--space-2);
}

.mmoc-list-row {
	display: flex;
	gap: var(--space-2);
	background: var(--card);
	border-radius: 14px;
	padding: var(--space-2);
	box-shadow: var(--shadow);
}

.mmoc-list-row__thumb {
	width: 100px;
	height: 76px;
	flex-shrink: 0;
	border-radius: 10px;
	overflow: hidden;
	background: var(--soft);
}

.mmoc-list-row__thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.mmoc-list-row__body {
	flex: 1;
	min-width: 0;
}

.mmoc-list-row__title {
	font-size: 15px;
	font-weight: 700;
	line-height: var(--lh-snug);
	margin: var(--space-half) 0;
}

/* On phones the body column is roughly 200px wide, so a long headline runs to
   four or five lines and the row grows to twice the height of its own thumbnail.
   Two lines keeps every row the same height and the list scannable; the full
   title is one tap away. */
@media (max-width: 899px) {
	.mmoc-list-row__title {
		display: -webkit-box;
		-webkit-box-orient: vertical;
		-webkit-line-clamp: 2;
		overflow: hidden;
	}
}

/* --- Article interstitial --- */
/* [hidden] needs stating explicitly: the display: flex below would otherwise
   override the attribute's own display: none and the overlay would sit over the
   page permanently. The attribute selector outranks the class, so this wins
   wherever it sits. */
.mmoc-interstitial[hidden] {
	display: none;
}

.mmoc-interstitial {
	position: fixed;
	inset: 0;
	z-index: 200;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--space-3);
	/* Dark either way: this sits over the page, not in it, so it does not follow
	   the palette. */
	background: rgba(10,11,14,0.72);
}

.mmoc-interstitial__panel {
	width: 100%;
	max-width: 360px;
	display: flex;
	flex-direction: column;
	gap: var(--space-2);
	padding: var(--space-2);
	border-radius: 18px;
	background: var(--card);
	box-shadow: 0 12px 40px rgba(0,0,0,0.45);
}

.mmoc-interstitial__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-2);
}

/* Labelled as advertising rather than left to look like content — the panel
   interrupts a click the reader made for a different reason. */
.mmoc-interstitial__label {
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--mut);
}

/* The same 36px round dismiss the sheets use. */
.mmoc-interstitial__close {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 36px;
	height: 36px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: var(--soft);
	color: var(--mut);
	cursor: pointer;
}

.mmoc-interstitial__close svg {
	display: block;
	width: 18px;
	height: 18px;
}

.mmoc-interstitial__close:hover {
	color: var(--ink);
}

.mmoc-interstitial__close:focus-visible,
.mmoc-interstitial__continue:focus-visible {
	outline: 2px solid var(--acc);
	outline-offset: 2px;
}

/* .mmoc-body prefix, or the parent stylesheet's `.mmoc-body a { color: inherit }`
   outranks this and the label inherits --ink instead: near-white on the dark
   default, so it looks right, and near-black on the purple button in light mode,
   where it does not. */
.mmoc-body .mmoc-interstitial__continue {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	border-radius: 999px;
	background: var(--acc);
	color: #fff;
	font-size: 14px;
	font-weight: 700;
}

/* The page behind must not scroll under the overlay. */
.mmoc-body.is-interstitial-open {
	overflow: hidden;
}

/* --- Right rail --- */
.mmoc-rail {
	display: none;
}

@media (min-width: 1120px) {
	.mmoc-rail {
		display: flex;
		flex-direction: column;
		gap: var(--space-3);
		min-width: 0;
	}
}

/* --- Compact language switcher --- */
/* Nothing renders this at the moment: the sidebar dropped it, and so has the
   mobile search sheet. The styles and mmoculture_modern_render_language_links()
   are kept for wherever it lands next. */

.mmoc-lang-select {
	width: 100%;
	font-family: var(--font-ui);
	font-size: 12px;
	font-weight: 600;
	color: var(--mut);
	background: var(--soft);
	border: 1px solid var(--bd);
	border-radius: 10px;
	padding: var(--space-1) var(--space-2);
	cursor: pointer;
}

.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* --- Archive: load more + pagination --- */
.mmoc-load-more {
	display: flex;
	justify-content: center;
	margin-top: var(--space-1);
}

.mmoc-load-more__btn {
	padding: var(--space-2) var(--space-3);
	min-height: 40px;
	border-radius: 999px;
	border: 1px solid var(--ink);
	background: transparent;
	color: var(--ink);
	font-family: var(--font-ui);
	font-size: 14px;
	font-weight: 600;
	line-height: var(--lh-flat);
	cursor: pointer;
}

.mmoc-load-more__btn[disabled] {
	opacity: .55;
	cursor: default;
}

.mmoc-pagination {
	margin-top: var(--space-3);
}

.mmoc-pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 40px;
	min-height: 40px;
	padding: 0 var(--space-1);
	margin-right: var(--space-1);
	border-radius: 10px;
	background: var(--card);
	font-size: 14px;
	font-weight: 600;
	line-height: var(--lh-flat);
	color: var(--ink);
}

.mmoc-pagination .page-numbers.current {
	background: var(--acc);
	color: #fff;
}

/* The prev/next links carry a chevron instead of a word. display: block for the
   same reason every other icon here has it — an inline SVG sits on the text
   baseline and would render the chevron a couple of pixels above the centre of
   the 40px pill. */
.mmoc-pagination .page-numbers svg {
	display: block;
	width: 16px;
	height: 16px;
}

.mmoc-empty {
	color: var(--mut);
	font-size: 15px;
	line-height: var(--lh-body);
}

/* --- Single article --- */
.mmoc-progress {
	position: fixed;
	top: 0;
	left: 0;
	height: 3px;
	width: 0;
	background: var(--acc);
	z-index: 200;
}

.mmoc-breadcrumb {
	display: flex;
	align-items: center;
	gap: var(--space-1);
	font-size: 12px;
	font-weight: 600;
	line-height: var(--lh-ui);
	color: var(--mut);
}

.mmoc-breadcrumb a {
	color: var(--mut);
}

/* Flush with the content column: the breadcrumb and title above it and the ad
   and module surfaces below it all share this edge, so the article body carries
   no card of its own. */
.mmoc-article {
	min-width: 0;
}

.mmoc-article__hero {
	height: 328px;
	margin: 0 0 var(--space-3);
	border-radius: 16px;
	overflow: hidden;
	background: var(--soft);
}

@media (max-width: 899px) {
	.mmoc-article__hero {
		height: 208px;
	}
}

.mmoc-article__hero img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.mmoc-article__title {
	font-size: 36px;
	line-height: var(--lh-display);
	letter-spacing: -0.03em;
	margin-bottom: var(--space-1);
}

@media (max-width: 899px) {
	.mmoc-article__title {
		font-size: 25px;
	}
}

.mmoc-byline {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: var(--space-1);
}

.mmoc-avatar {
	flex: 0 0 auto;
	width: 24px;
	height: 24px;
	border-radius: 50%;
	background: var(--accSoft);
	color: var(--acc);
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 11px;
	font-weight: 700;
	line-height: var(--lh-flat);
}

.mmoc-byline__text {
	font-size: 13px;
	line-height: var(--lh-ui);
	color: var(--mut);
}

.mmoc-byline__sep {
	margin: 0 var(--space-half);
}

.mmoc-byline__chips {
	margin-left: auto;
	display: flex;
	gap: var(--space-1);
}

.mmoc-chip {
	display: inline-flex;
	align-items: center;
	padding: var(--space-1) var(--space-2);
	min-height: 32px;
	border-radius: 999px;
	background: var(--soft);
	color: var(--ink);
	font-size: 12px;
	font-weight: 600;
	line-height: var(--lh-flat);
}

.mmoc-article__body {
	font-size: 19px;
	line-height: var(--lh-body);
	color: var(--ink);
}

.mmoc-article__body > * + * {
	margin-top: var(--space-3);
}

.mmoc-article__body h2 {
	font-size: 23px;
	line-height: var(--lh-heading);
	margin-top: var(--space-4);
}

.mmoc-article__body h3 {
	font-size: 19px;
	line-height: var(--lh-heading);
	margin-top: var(--space-3);
}

/* Reading copy steps down on phones: 19px is right for the desktop measure but
   oversized on a ~343px column, where it runs to roughly 40 characters a line.
   The headings come down with it so the scale between them holds rather than the
   h2 closing on the body size. */
@media (max-width: 899px) {
	.mmoc-article__body {
		font-size: 15px;
	}

	.mmoc-article__body h2 {
		font-size: 19px;
	}

	.mmoc-article__body h3 {
		font-size: 16px;
	}
}

/* Legacy editor content marks emphasis with <strong> and <b> interchangeably,
   and the parent theme weights them differently (body strong -> 600, b -> bold).
   Pin reading-copy emphasis to one weight so the two tags look alike. */
.mmoc-article__body :where(strong, b) {
	font-weight: 700;
}

/* Most headings in the corpus are typed as <h2><strong>…</strong></h2>, which
   made them render at 600 or 700 instead of the theme's 800 — reading as a
   lighter, almost different face than a heading with no wrapper. Some also
   carry an editor-injected inline `font-weight: 400`, which drops the heading
   to body weight entirely. Let any wrapper inside a heading inherit the
   heading's own weight.

   !important is the only thing that beats an inline style, so the scope is kept
   deliberately narrow: wrappers inside an article-body heading, nowhere else.
   Only weight is touched, so italics from <em>/<i> survive. */
.mmoc-article__body h1 :where(strong, b, span, em, i),
.mmoc-article__body h2 :where(strong, b, span, em, i),
.mmoc-article__body h3 :where(strong, b, span, em, i),
.mmoc-article__body h4 :where(strong, b, span, em, i) {
	font-weight: inherit !important;
}

.mmoc-article__body img,
.mmoc-article__body iframe {
	max-width: 100%;
	height: auto;
	border-radius: 14px;
}

.mmoc-article__body ul,
.mmoc-article__body ol {
	padding-left: var(--space-3);
}

.mmoc-article__body li + li {
	margin-top: var(--space-1);
}

.mmoc-article__body a {
	color: var(--acc);
	text-decoration: underline;
}

.mmoc-article__footer {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: var(--space-2);
	margin-top: var(--space-3);
}

.mmoc-tags {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-1);
}

.mmoc-adjacent {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-2);
	margin-top: var(--space-3);
}

@media (min-width: 560px) {
	.mmoc-adjacent {
		grid-template-columns: 1fr 1fr;
	}
}

.mmoc-adjacent__card {
	display: flex;
	flex-direction: column;
	gap: var(--space-1);
	padding: var(--space-2);
	border-radius: 14px;
	background: var(--soft);
}

.mmoc-adjacent__card--next {
	text-align: right;
}

/* Lucide chevrons in place of the &larr;/&rarr; glyphs, matching the caret on
   "See all" and the rest of the icon set — the HTML arrows came from the text
   font and sat heavier and lower than every other mark on the page.

   The card is a column flex container, so this span stretches to its full
   width; the next card pushes its row to the trailing edge to stay with the
   card's right alignment. */
.mmoc-adjacent__dir {
	display: flex;
	align-items: center;
	gap: var(--space-half);
}

.mmoc-adjacent__card--next .mmoc-adjacent__dir {
	justify-content: flex-end;
}

.mmoc-adjacent__dir svg {
	width: 14px;
	height: 14px;
	flex: 0 0 auto;
}

.mmoc-adjacent__title {
	font-size: 14px;
	font-weight: 700;
	line-height: var(--lh-snug);
	color: var(--ink);
}

.mmoc-related {
	margin-top: var(--space-4);
}

.mmoc-comments {
	margin-top: var(--space-4);
	padding-top: var(--space-3);
	border-top: 1px solid var(--bd);
}

.mmoc-comments input:not([type="submit"]),
.mmoc-comments textarea {
	width: 100%;
	max-width: 100%;
	padding: var(--space-1) var(--space-2);
	min-height: 40px;
	border: 1px solid var(--bd);
	border-radius: 10px;
	background: var(--bg);
	color: var(--ink);
	font-family: var(--font-ui);
	font-size: 15px;
	line-height: var(--lh-body);
}

.mmoc-comments .submit {
	padding: var(--space-1) var(--space-3);
	min-height: 40px;
	border: 0;
	border-radius: 999px;
	background: var(--acc);
	color: #fff;
	font-family: var(--font-ui);
	font-size: 14px;
	font-weight: 700;
	cursor: pointer;
}

/* --- Codes module (redeem-codes posts) --- */
.mmoc-codes,
.mmoc-tiers {
	margin-top: var(--space-4);
}

.mmoc-codes__table {
	display: flex;
	flex-direction: column;
	gap: var(--space-1);
	margin-top: var(--space-2);
}

.mmoc-codes__row {
	display: flex;
	align-items: center;
	gap: var(--space-2);
	padding: var(--space-2);
	border-radius: 14px;
	background: var(--soft);
}

.mmoc-codes__info {
	min-width: 0;
	flex: 1;
}

.mmoc-codes__code {
	display: block;
	font-family: var(--font-mono);
	font-size: 15px;
	font-weight: 500;
	letter-spacing: .05em;
	line-height: var(--lh-snug);
	color: var(--ink);
}

.mmoc-codes__reward {
	display: block;
	font-size: 12px;
	line-height: var(--lh-ui);
	color: var(--mut);
}

.mmoc-copy {
	flex: 0 0 auto;
	padding: var(--space-1) var(--space-2);
	min-height: 32px;
	border: 0;
	border-radius: 999px;
	background: var(--acc);
	color: #fff;
	font-family: var(--font-ui);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: .06em;
	line-height: var(--lh-flat);
	cursor: pointer;
}

.mmoc-codes__row.is-expired .mmoc-codes__code {
	text-decoration: line-through;
	color: var(--mut);
}

.mmoc-steps {
	display: flex;
	flex-direction: column;
	gap: var(--space-2);
	margin-top: var(--space-2);
}

.mmoc-step {
	display: flex;
	gap: var(--space-2);
	padding: var(--space-2);
	border-radius: 14px;
	background: var(--soft);
}

.mmoc-step__num {
	flex: 0 0 auto;
	font-size: 26px;
	font-weight: 800;
	line-height: var(--lh-flat);
	color: var(--acc);
}

.mmoc-step__label {
	display: block;
	font-size: 15px;
	font-weight: 700;
	line-height: var(--lh-snug);
	color: var(--ink);
}

.mmoc-step__body {
	display: block;
	font-size: 14px;
	line-height: var(--lh-body);
	color: var(--mut);
}

/* --- Tier module (tips-guides posts) --- */
.mmoc-tiers__table {
	display: flex;
	flex-direction: column;
	gap: var(--space-1);
	margin-top: var(--space-2);
}

.mmoc-tier {
	display: flex;
	align-items: center;
	gap: var(--space-2);
	padding: var(--space-1) var(--space-2);
	border-radius: 14px;
	background: var(--soft);
}

.mmoc-tier__badge {
	flex: 0 0 auto;
	width: 32px;
	height: 32px;
	border-radius: 10px;
	color: #fff;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 15px;
	font-weight: 800;
	line-height: var(--lh-flat);
}

.mmoc-tier__names {
	font-size: 14px;
	line-height: var(--lh-ui);
	color: var(--ink);
}

/* --- 404 --- */
.mmoc-404 {
	background: var(--card);
	border-radius: 18px;
	box-shadow: var(--shadow);
	padding: var(--space-4) var(--space-3);
	text-align: center;
}

.mmoc-404__code {
	font-family: var(--font-ui);
	font-size: 48px;
	font-weight: 800;
	line-height: var(--lh-flat);
	color: var(--acc);
	margin: 0;
}

.mmoc-404__text {
	color: var(--mut);
	font-size: 15px;
	line-height: var(--lh-body);
	margin: var(--space-1) 0 var(--space-3);
}

.mmoc-404 .mmoc-pills {
	justify-content: center;
}
