/*
 * Nivoli JA rules. Tokens only: no literal colour and no literal font size
 * below this line, and no `rem` anywhere. See assets/css/tokens.css.
 */

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

html { font-size: 100%; }

body {
	margin: 0;
	background: var(--ja-bg);
	color: var(--ja-ink);
	font-family: var(--ja-sans);
	font-size: var(--ja-size-body);
	line-height: var(--ja-leading);
	-webkit-text-size-adjust: 100%;
}

img, video { max-width: 100%; height: auto; }

a { color: var(--ja-accent); text-underline-offset: 0.15em; }
a:hover { text-decoration-thickness: 2px; }

:focus-visible { outline: 2px solid var(--ja-accent); outline-offset: 2px; border-radius: 2px; }

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

.ja-skip {
	position: absolute; left: -9999px;
	background: var(--ja-accent); color: var(--ja-accent-ink);
	padding: calc(var(--ja-root) * 0.5) calc(var(--ja-root) * 0.75);
}
.ja-skip:focus { left: calc(var(--ja-root) * 0.5); top: calc(var(--ja-root) * 0.5); z-index: 10; }

.ja-shell {
	max-width: var(--ja-shell);
	margin: 0 auto;
	padding: 0 clamp(calc(var(--ja-root) * 1), 4vw, calc(var(--ja-root) * 2));
}

/* masthead */

.ja-masthead {
	background: var(--ja-bg-sunken);
	border-bottom: 1px solid var(--ja-rule);
}

.ja-masthead-inner {
	display: flex;
	align-items: center;
	gap: var(--ja-gap);
	min-height: calc(var(--ja-root) * 4);
	flex-wrap: wrap;
}

.ja-logo {
	font-family: var(--ja-serif);
	font-size: calc(var(--ja-root) * 1.5);
	font-weight: 700;
	color: var(--ja-ink-strong);
	text-decoration: none;
	line-height: var(--ja-leading-tight);
}
.ja-logo-2 { color: var(--ja-accent); }

.ja-nav-list {
	display: flex;
	gap: calc(var(--ja-root) * 1);
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: var(--ja-size-meta);
	flex-wrap: wrap;
}
/*
 * The li below already reserves a 44px row, but a bare inline `a` only takes
 * up its own text height inside that row (the audit measured it at 24px):
 * flex plus the same min-height makes the link itself fill the row, so the
 * whole row is tappable, not just the letters in it.
 */
.ja-nav-list a {
	display: flex;
	align-items: center;
	min-height: calc(var(--ja-root) * 2.75);
	color: var(--ja-ink);
	text-decoration: none;
}
.ja-nav-list a:hover { color: var(--ja-accent); }
.ja-nav-list li { min-height: calc(var(--ja-root) * 2.75); display: flex; align-items: center; }

/*
 * Hidden by default: the collapsible small screen nav only exists below the
 * breakpoint (see the max-width: 720px block near the bottom of this file).
 * Desktop layout above it is completely untouched.
 */
.ja-nav-toggle {
	display: none;
	min-width: calc(var(--ja-root) * 2.75);
	min-height: calc(var(--ja-root) * 2.75);
	margin-left: auto;
	padding: 0;
	background: transparent;
	border: 1px solid var(--ja-rule-strong);
	border-radius: var(--ja-radius);
	color: var(--ja-ink);
	cursor: pointer;
}
.ja-nav-toggle[aria-expanded="true"] { border-color: var(--ja-accent); color: var(--ja-accent); }

.ja-nav-toggle-icon {
	position: relative;
	display: block;
	width: calc(var(--ja-root) * 1.25);
	height: calc(var(--ja-root) * 0.125);
	margin: 0 auto;
	background: currentColor;
}
.ja-nav-toggle-icon::before,
.ja-nav-toggle-icon::after {
	content: '';
	position: absolute;
	left: 0;
	width: 100%;
	height: 100%;
	background: currentColor;
}
.ja-nav-toggle-icon::before { top: calc(var(--ja-root) * -0.375); }
.ja-nav-toggle-icon::after { top: calc(var(--ja-root) * 0.375); }

.ja-search { margin-left: auto; display: flex; gap: calc(var(--ja-root) * 0.375); }
.ja-search input {
	min-height: calc(var(--ja-root) * 2.75);
	padding: 0 calc(var(--ja-root) * 0.625);
	background: var(--ja-bg);
	color: var(--ja-ink);
	border: 1px solid var(--ja-rule-strong);
	border-radius: var(--ja-radius);
	font-size: var(--ja-root); /* 16px: below this iOS zooms the page */
	font-family: inherit;
}
.ja-search button {
	min-height: calc(var(--ja-root) * 2.75);
	padding: 0 calc(var(--ja-root) * 0.875);
	background: var(--ja-accent);
	color: var(--ja-accent-ink);
	border: 0;
	border-radius: var(--ja-radius);
	font-size: var(--ja-size-meta);
	font-weight: 700;
	cursor: pointer;
}

/*
 * Sub-menus. The theme carried no rule for these at all: whatever menu an
 * editor assigns to `primary` or `footer` may have children, and until this
 * they rendered as an unstyled `<ul>` floating to the right of the masthead.
 *
 * Hidden by opacity/pointer-events, not `display` or `visibility`: both of
 * those pull child links out of the tab order, which breaks the
 * `:focus-within` reveal below (a link that cannot be focused can never
 * satisfy `:focus-within`). Revealed on `:hover` OR `:focus-within`, never
 * hover alone, so tabbing to a child with a keyboard opens the same dropdown
 * a mouse hover does.
 */
.ja-nav-list li { position: relative; }

.ja-nav-list .sub-menu {
	position: absolute;
	top: 100%;
	left: 0;
	z-index: 20;
	margin: 0;
	padding: calc(var(--ja-root) * 0.25) 0;
	min-width: calc(var(--ja-root) * 11);
	/* Bounded to the viewport, not just its own content: a long child label
	   must not be what pushes this past the right edge. */
	max-width: calc(100vw - var(--ja-gap) * 2);
	list-style: none;
	background: var(--ja-bg-sunken);
	border: 1px solid var(--ja-rule);
	border-radius: var(--ja-radius);
	opacity: 0;
	pointer-events: none;
	transform: translateY(calc(var(--ja-root) * -0.25));
	transition: opacity 0.15s ease, transform 0.15s ease;
}

.ja-nav-list li:hover > .sub-menu,
.ja-nav-list li:focus-within > .sub-menu {
	opacity: 1;
	pointer-events: auto;
	transform: translateY(0);
}

.ja-nav-list .sub-menu li { min-height: calc(var(--ja-root) * 2.75); width: 100%; }
.ja-nav-list .sub-menu a {
	display: flex;
	align-items: center;
	width: 100%;
	min-height: calc(var(--ja-root) * 2.75);
	padding: 0 calc(var(--ja-root) * 0.875);
	white-space: nowrap;
}
.ja-nav-list .sub-menu a:hover { background: var(--ja-bg-2); }

/*
 * Safety net for the max-width clamp above: it bounds the dropdown's own
 * box, not where that box sits relative to the parent link, so a dropdown
 * under a nav item near the right edge could still render partly past the
 * viewport. The masthead spans the full viewport width with no horizontal
 * margin of its own, so clipping overflow here is equivalent to clipping at
 * the viewport edge, and guarantees no menu, at any width, ever opens a
 * horizontal scrollbar on the page.
 */
.ja-masthead { overflow-x: clip; }

/* footer */

.ja-footer {
	margin-top: var(--ja-gap-lg);
	padding: var(--ja-gap-lg) 0;
	background: var(--ja-bg-sunken);
	border-top: 1px solid var(--ja-rule);
	font-size: var(--ja-size-meta);
	color: var(--ja-muted);
}
.ja-footer-line { max-width: var(--ja-measure); }

/*
 * --ja-muted clears 4.5:1 but is only verified at 14px and up (see
 * tokens.css). This line sits at the 12px floor, so it opts back into
 * --ja-ink rather than inheriting --ja-footer's muted colour.
 */
.ja-footer-meta { font-size: var(--ja-size-label); color: var(--ja-ink); }
/* Same 12px floor, same reason, as .ja-footer-meta above. */
.ja-footer-legacy { margin: calc(var(--ja-root) * 0.25) 0 0; font-size: var(--ja-size-label); color: var(--ja-ink); }

/*
 * The closing row: the copyright and the legacy link on the left, the wordmark
 * on the right. `align-items: end` sits the logo on the baseline of the block
 * rather than centred against it, so its bottom edge lines up with the last
 * line of text. It wraps on a narrow screen, where the logo lands under the
 * text and stays right aligned via margin-left: auto.
 */
.ja-footer-bottom {
	display: flex;
	align-items: end;
	justify-content: space-between;
	gap: var(--ja-gap);
	flex-wrap: wrap;
}
.ja-footer-bottom-text { min-width: 0; }
/*
 * The logo is a link, so it is a control and owes the 44px tap target the rest
 * of the theme keeps. At 192px wide the 400x100 file renders 48px tall, which
 * already clears it; the padding is there to keep the wordmark off the text
 * beside it, and it sits on the anchor rather than the image so the whole padded
 * box is clickable. 192px was chosen by looking at it: at 160px the house in the
 * mark stopped being readable as a house on a desktop screen.
 */
.ja-footer-logo {
	display: block;
	flex: 0 0 auto;
	margin-left: auto;
	padding: calc(var(--ja-root) * 0.25) 0;
}
.ja-footer-logo img { display: block; width: calc(var(--ja-root) * 12); height: auto; }
.ja-footer-logo:hover img { opacity: 0.85; }

@media (max-width: 720px) {
	.ja-search { margin-left: 0; width: 100%; order: 3; flex-basis: 100%; }
	.ja-nav-list { gap: calc(var(--ja-root) * 0.75); }
	/* `nowrap` labels plus the 100vw clamp above are enough to stop a
	   scrollbar, but on a narrow phone width the two together can still
	   clip a long label mid-word. Wrapping the text instead reads better
	   than a truncated word does. */
	.ja-nav-list .sub-menu { min-width: calc(var(--ja-root) * 9); }
	.ja-nav-list .sub-menu a { white-space: normal; }

	/*
	 * Small screen nav (I1/I2 in the audit). The six item bar used to wrap
	 * onto three lines here instead of collapsing, pushing roughly 400px of
	 * chrome above any real content.
	 *
	 * This block is the no-JS-required baseline: a plain full width vertical
	 * stack, one 44px row per item, not a wrap. It is reachable with zero
	 * script. The rule right after it, gated on html.ja-js, is the only part
	 * that actually hides the list, and that class is only ever added by
	 * nav-toggle.js once it has confirmed it can reopen what it hides. If
	 * that script never runs, this baseline is what stays on screen: no
	 * toggle button doing nothing, no menu stuck closed forever.
	 */
	.ja-nav-toggle { display: inline-flex; align-items: center; justify-content: center; order: 1; }
	.ja-nav { flex-basis: 100%; order: 2; }
	.ja-nav-list { flex-direction: column; gap: 0; }
	.ja-nav-list li { width: 100%; border-top: 1px solid var(--ja-rule); }
	.ja-nav-list a { width: 100%; }

	html.ja-js .ja-nav { display: none; }
	html.ja-js .ja-nav.is-open { display: block; }
}

/* ------------------------------------------------------------- article ---- */

.ja-article-wrap {
	display: flex;
	gap: var(--ja-gap-lg);
	align-items: flex-start;
	padding-top: var(--ja-gap-lg);
}

.ja-article { flex: 1; min-width: 0; max-width: var(--ja-measure); }

/*
 * --ja-muted is only verified at 14px and up (see tokens.css). The crumb sits
 * at the 12px label floor, so it opts into --ja-ink rather than --ja-muted,
 * the same fix .ja-footer-meta already needed for the same reason.
 */
.ja-crumb { margin: 0 0 calc(var(--ja-root) * 0.5); font-size: var(--ja-size-label); color: var(--ja-ink); text-transform: uppercase; letter-spacing: 0.08em; }
.ja-crumb a { position: relative; color: var(--ja-ink); text-decoration: none; }
/*
 * The audit measured this link at 17px tall: a breadcrumb has to print at
 * the 12px label size, so growing the visible text or padding is not an
 * option without it stopping looking like a breadcrumb. An invisible
 * pseudo-element floor instead extends the actual tappable box to 44px
 * around the text, without touching what is on screen or what any sibling
 * link (the_category(' / ') can print more than one) reserves for itself.
 */
.ja-crumb a::before {
	content: '';
	position: absolute;
	inset: calc(var(--ja-root) * -1) calc(var(--ja-root) * -0.25);
}

.ja-h1 {
	margin: 0 0 calc(var(--ja-root) * 0.5);
	font-family: var(--ja-serif);
	font-size: var(--ja-size-h1);
	font-weight: 700;
	line-height: var(--ja-leading-tight);
	color: var(--ja-ink-strong);
}

/*
 * 20px serif roman, not the old 17px italic dimmed tint: this is the small
 * fraction of posts (23 of 5,728) whose stored excerpt survives Dek's checks
 * and is worth reading, so it earns primary content treatment, not a
 * metadata one. Italic reads fine as a single line label but strains across
 * the two or three line paragraph a real dek runs to, so it drops to roman
 * weight; --ja-ink, not a dimmed mix, is the same full body colour used
 * below it, already verified at 11.11:1 (see tokens.css).
 */
.ja-dek {
	margin: 0 0 var(--ja-gap);
	font-family: var(--ja-serif);
	font-size: calc(var(--ja-root) * 1.25);
	font-weight: 400;
	line-height: var(--ja-leading);
	color: var(--ja-ink);
}

.ja-byline {
	display: flex;
	align-items: center;
	gap: calc(var(--ja-root) * 0.75);
	margin: 0 0 var(--ja-gap);
	padding: calc(var(--ja-root) * 0.5) 0;
	border-top: 1px solid var(--ja-rule);
	border-bottom: 1px solid var(--ja-rule);
	font-size: var(--ja-size-meta);
	color: var(--ja-muted);
	flex-wrap: wrap;
}
.ja-byline strong { color: var(--ja-ink); }

.ja-grade {
	margin-left: auto;
	font-family: var(--ja-serif);
	font-size: calc(var(--ja-root) * 1.9375);
	font-weight: 700;
	line-height: 1;
	color: var(--ja-accent);
}

.ja-hero { margin: 0 0 var(--ja-gap); }
.ja-hero img { border-radius: var(--ja-radius); }

.ja-prose > * + * { margin-top: 1.15em; }
.ja-prose h2 { font-family: var(--ja-serif); font-size: var(--ja-size-h2); line-height: var(--ja-leading-tight); color: var(--ja-ink-strong); margin-top: 2em; }
.ja-prose h3 { font-size: calc(var(--ja-root) * 1.25); color: var(--ja-ink-strong); margin-top: 1.8em; }
.ja-prose blockquote {
	margin: 1.4em 0; padding: 0.2em 0 0.2em 1em;
	border-left: 3px solid var(--ja-accent);
	font-family: var(--ja-serif);
	font-size: calc(var(--ja-root) * 1.25);
	color: var(--ja-ink-strong);
}
/* max()'s floor is the --ja-size-label token, not a bare 12px: nothing in this
   file renders below that floor, and this keeps the guarantee token-driven. */
.ja-prose code, .ja-prose pre { font-family: var(--ja-mono); font-size: max(var(--ja-size-label), 0.86em); }
.ja-prose pre {
	padding: calc(var(--ja-root) * 0.75);
	background: var(--ja-bg-sunken);
	border: 1px solid var(--ja-rule);
	border-radius: var(--ja-radius);
	overflow-x: auto;
}
.ja-prose img { border-radius: var(--ja-radius); }
.ja-prose table { width: 100%; border-collapse: collapse; font-size: var(--ja-size-meta); display: block; overflow-x: auto; }
.ja-prose td, .ja-prose th { border-bottom: 1px solid var(--ja-rule); padding: calc(var(--ja-root) * 0.4); text-align: left; }

/*
 * Neutralise legacy inline typography left behind by the Joomla/EE migration.
 * Measured across published posts and walkthroughs: 2,414 carry a dark inline
 * `color` (often the literal #333333, which computes to roughly 1.3:1 against
 * this theme's #242118 background) and 1,892 carry an inline `pt` font size
 * (10pt Helvetica is 13.3px, and drops under the 12px floor once nested
 * inside another sized span). `post_content` is the archive and this
 * project's spec forbids rewriting it, so the fix has to run at render time.
 *
 * An inline style attribute always outranks a stylesheet selector, no matter
 * how specific: `!important` is the only way a rule here can still win.
 * Scoped to text level elements only, never `img`, whose inline `style`
 * carries real sizing (`max-width`) that has to survive. `font-weight` and
 * `font-style` are deliberately absent from the list below: semantic
 * <b>/<strong> and <i>/<em> must keep rendering bold and italic, so only the
 * four properties that actually carry migration debris (colour, size,
 * family, background) are reset, and `inherit` hands them back to whatever
 * this theme already set on the wrapping element.
 */
.ja-prose span, .ja-prose p, .ja-prose div, .ja-prose td, .ja-prose th,
.ja-prose li, .ja-prose b, .ja-prose i, .ja-prose strong, .ja-prose em {
	color: inherit !important;
	background: inherit !important;
	font-family: inherit !important;
	font-size: inherit !important;
}

.ja-tags { margin-top: var(--ja-gap-lg); font-size: var(--ja-size-label); }
/* same 12px floor as .ja-crumb: --ja-ink, not --ja-muted. */
.ja-tags a { color: var(--ja-ink); }

/* ---------------------------------------------------------------- rail ---- */

.ja-rail { width: calc(var(--ja-root) * 13); flex: none; position: sticky; top: var(--ja-gap); }

.ja-gamecard {
	/* Cover plus the padding either side, so the card is exactly as wide as the
	   poster it frames however wide its container is. See --ja-cover-max. */
	max-width: calc(var(--ja-cover-max) + var(--ja-root) * 1.25);
	background: var(--ja-bg-2);
	border: 1px solid var(--ja-rule);
	border-radius: var(--ja-radius);
	padding: calc(var(--ja-root) * 0.625);
	font-size: var(--ja-size-meta);
}
/* 3px per the brief, not --ja-radius (5px): a cover thumbnail sits inside an
   already-rounded card, and radius is neither colour nor font size, so the
   tokens-only constraint does not reach it. Revert if a reviewer prefers 5px. */
/* The cover keeps its own shape: the catalogue holds both 3:4 box art (1,283 of
   1,403 covers) and wide banners (109), so there is no one ratio to force them
   into and nothing on this card to line a fixed box up against. Bounded on both
   axes instead, the height cap being a 3:4 poster at the maximum width, so only
   a taller-than-poster outlier is bounded at all and it letterboxes on the
   card's own surface rather than being cropped. */
.ja-gamecard-cover {
	display: block;
	width: 100%;
	max-width: var(--ja-cover-max);
	height: auto;
	max-height: calc(var(--ja-cover-max) * 4 / 3);
	object-fit: contain;
	border-radius: 3px;
	margin-bottom: calc(var(--ja-root) * 0.5);
}
.ja-gamecard-title { margin: 0; font-family: var(--ja-serif); font-size: calc(var(--ja-root) * 1.0625); line-height: var(--ja-leading-tight); }
.ja-gamecard-title a { color: var(--ja-ink-strong); text-decoration: none; }
/* meta line sits at the 12px label floor: --ja-ink, not --ja-muted, same as
   .ja-crumb and .ja-tags a above. */
.ja-gamecard-meta { margin: calc(var(--ja-root) * 0.125) 0 calc(var(--ja-root) * 0.375); color: var(--ja-ink); font-size: var(--ja-size-label); }
.ja-gamecard-guides { margin: 0 0 calc(var(--ja-root) * 0.5); }

/*
 * A link styled as a control, not a divider: judged against the 3:1 non-text
 * floor like .ja-search button, which this mirrors. Its accent fill against
 * --ja-bg already clears that (7.28:1 per tokens.css), so it needs no border
 * of its own, --ja-rule-strong or otherwise.
 */
.ja-btn {
	display: block;
	min-height: calc(var(--ja-root) * 2.75);
	line-height: calc(var(--ja-root) * 2.75);
	text-align: center;
	background: var(--ja-accent);
	color: var(--ja-accent-ink);
	border-radius: var(--ja-radius);
	font-size: var(--ja-size-meta);
	font-weight: 700;
	text-decoration: none;
}

@media (max-width: 900px) {
	.ja-article-wrap { display: block; }
	.ja-rail { width: auto; position: static; margin-top: var(--ja-gap-lg); }
}

/* ----------------------------------------------------------- list views ---- */

.ja-listhead { padding: var(--ja-gap-lg) 0 var(--ja-gap); }
.ja-listdesc { color: var(--ja-muted); font-size: var(--ja-size-meta); max-width: var(--ja-measure); }

/*
 * Card density. The minimum column was 17 root units (272px), which inside the
 * 1,184px shell less its 32px gutters (1,120px of content) at a 20px gap gives
 * floor((1120 + 20) / (272 + 20)) = 3 columns, so an archive of 50 posts came
 * out 17 rows deep with three items on a line. 12.5 root units (200px) gives
 * floor((1120 + 20) / (200 + 20)) = 5, ten rows for the same 50 posts, and a
 * card whose rendered width falls from 360px to 208px. The 16 / 9 thumbnail
 * scales with that width, so the card's height falls with it and the padding,
 * title and meta steps below are tightened to match: a smaller box with the
 * same interior spacing reads as a big card that got cropped.
 *
 * Nothing here goes below the floors tokens.css documents. The kicker and meta
 * stay at --ja-size-label (12px) and keep --ja-ink, the title lands at 16px,
 * and the tap target is the whole card link, which at 208px wide with a 117px
 * thumbnail is far past 44px in both directions.
 */
.ja-cards {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(calc(var(--ja-root) * 12.5), 1fr));
	gap: var(--ja-gap);
}

/*
 * Two columns on a phone, which the 200px minimum will not produce on its own.
 * At 390px the shell leaves 358px of content, one column short of the 420px
 * auto-fill needs for two tracks, so a 50 card archive came out 50 rows and
 * about 14,500px deep. Two columns make each card 169px wide and 222px tall and
 * the same archive 6,500px, measured at the origin.
 *
 * The bounds are both deliberate. Below 360px the same arithmetic gives a 134px
 * card, which is narrower than a three word title wants, so those widths keep
 * the single column. Above about 452px auto-fill reaches two tracks by itself
 * and this rule stops changing the answer, so the upper bound is only there to
 * keep the override off the widths that do not need it.
 */
@media (min-width: 360px) and (max-width: 480px) {
	.ja-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.ja-card { background: var(--ja-bg-2); border: 1px solid var(--ja-rule); border-radius: var(--ja-radius); overflow: hidden; }
.ja-card-link { display: block; color: inherit; text-decoration: none; height: 100%; }
/* --ja-bg-sunken, not a literal darkening of --ja-bg: this file carries no
   literal colour. It reads as an empty image slot behind the <img> until the
   thumbnail paints, the same "recessed" surface tokens.css already uses for
   the chrome bands and the code shelf, applied here for a third reason. */
.ja-card-thumb { aspect-ratio: 16 / 9; background: var(--ja-bg-sunken); }
/*
 * The image states the 16 / 9 ratio itself rather than taking `height: 100%`
 * from the frame, and the reason is robustness, not a crop anybody can see
 * today. This was reported as the defect nivoli-games 0.2.11 fixed on
 * `.ng-card-img`: a percentage height resolving against a parent whose height
 * comes only from `aspect-ratio`, computing to `auto`, and letting the image
 * render at its intrinsic ratio inside a frame that clips. It does not
 * reproduce here. Measured at the origin on justadventure.com in Chrome, at
 * 1440 and at 390, on the homepage, /category/reviews/ and /?s=syberia: 94
 * loaded card images with intrinsic ratios from 0.76 to 6.79, and under the
 * old declaration every one of them still resolved to exactly the frame's
 * height (201.375px in a 358x201 frame), the same as under this one. Current
 * engines treat a ratio-derived block size as definite for a child's
 * percentage.
 *
 * The pairing is still worth removing, because `height: 100%` here depends on
 * that engine behaviour and this does not: the ratio is stated where the box
 * is, which is also the convention the catalogue grid now follows. Rendered
 * geometry is identical, so nothing about the change is visible.
 *
 * `object-fit: cover` is kept, unlike the game covers on the rail, and the
 * difference is deliberate: a card image is editorial photography in a grid
 * where every title has to sit on the same line as its neighbours, so a
 * uniform frame is the point and cropping to fill it is correct. A game cover
 * is artwork of a ratio the catalogue does not control, where a crop loses part
 * of the poster, which is why .ja-gamecard-cover forces no ratio at all (see
 * tests/test-covers.php).
 */
.ja-card-thumb img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; }
/* 10px, down from 12px: at a 208px card the old padding took 12% of the width
   per side and the title had 336px of measure at 360px but only 184px here. */
.ja-card-body { padding: calc(var(--ja-root) * 0.625); }
/*
 * Kicker and meta both sit at --ja-size-label (12px), the floor where
 * --ja-muted is not verified (see tokens.css). Same fix as .ja-crumb,
 * .ja-tags a and .ja-gamecard-meta: --ja-ink instead, which the tokens.css
 * docblock documents at 10.25:1 on --ja-bg-2, the surface a card sits on.
 */
.ja-card-kicker {
	display: flex; align-items: baseline; gap: calc(var(--ja-root) * 0.5);
	margin: 0 0 calc(var(--ja-root) * 0.25);
	font-size: var(--ja-size-label); text-transform: uppercase; letter-spacing: 0.08em; color: var(--ja-ink);
}
.ja-card-grade { margin-left: auto; font-family: var(--ja-serif); font-size: var(--ja-size-meta); color: var(--ja-accent); letter-spacing: 0; }
/* 16px, one step down from 18px. Titles here are article headlines, some of
   them 80 characters long ("The Walking Dead: Season Two: No Going Back is
   Available Now on Most Platforms"), and at 18px in a 184px measure that one
   ran to six lines and made its whole grid row tall. */
.ja-card-title { margin: 0; font-family: var(--ja-serif); font-size: var(--ja-root); line-height: var(--ja-leading-tight); color: var(--ja-ink-strong); }
/*
 * One line where one line fits, and one continuous run of text where it does
 * not. The credit used to be `display: block` above the date, which spent a
 * whole line on a separator that a middle dot does in three characters.
 *
 * Deliberately inline flow rather than a flex row, and the reason is measured.
 * A flex row with the credit truncated to an ellipsis does hold every card to
 * one line, but at a 208px card the credit has about 100px to work in and
 * "by Malcolm Schmidt, part 10 of 12" wants 191: 22 of the 29 credits on
 * /?s=syberia came out as "by Malcolm Sc...", which is the exact failure
 * inc/CardCredit.php exists to prevent, twelve cards for one guide that a
 * reader cannot tell apart. Wrapping keeps all of it. An article card, which
 * has no credit at all, is one line either way.
 */
.ja-card-meta {
	margin: calc(var(--ja-root) * 0.25) 0 0;
	font-size: var(--ja-size-label); color: var(--ja-ink);
}
/*
 * The byline and part number that tell two guides for one game apart. Set
 * before the date, because on a walkthrough card it is the part that varies:
 * every imported guide carries the same import date.
 */
.ja-card-credit { color: var(--ja-ink-strong); }
/* The date and its leading separator never break across lines: "29 July" on one
   and "2026" on the next reads as two facts rather than one date. */
.ja-card-date { white-space: nowrap; }
.ja-card:hover { border-color: var(--ja-accent); }

/*
 * No thumbnail: not a broken card, a different one. No placeholder image,
 * gradient or monogram stands in for the missing cover (deliberate call, see
 * task-4-report.md); instead the accent rule across the top edge and the
 * larger, more generously padded title carry the card on type alone.
 * align-self: start keeps the card's own height honest instead of stretching
 * it to match a taller image card sharing its grid row with empty space.
 */
.ja-card--text {
	border-top: 2px solid var(--ja-accent);
	align-self: start;
}
/*
 * Both steps come down with the grid, and the relationship between them is
 * what has to survive: the text card stays more generous than an image card
 * (14px of padding against 10px, a 19px title against 16px) so it still reads
 * as a deliberate variant rather than a card that lost its picture. The title
 * was --ja-size-h2, which clamps up to 27px, and 27px in a 180px measure set
 * three-word lines: at 208px wide a section heading is not a card title.
 */
.ja-card--text .ja-card-body { padding: calc(var(--ja-root) * 0.875); }
.ja-card--text .ja-card-title { font-size: calc(var(--ja-root) * 1.1875); }

.ja-empty { color: var(--ja-muted); }

.ja-pagination { display: flex; flex-wrap: wrap; gap: calc(var(--ja-root) * 0.375); margin: var(--ja-gap-lg) 0; font-size: var(--ja-size-meta); }
/*
 * --ja-rule-strong, not --ja-rule: a pagination link is a control, not a
 * decorative hairline, and needs the 3:1 non-text floor --ja-rule-strong
 * clears (see tokens.css). Mirrors the .ja-search input fix from Task 3.
 */
.ja-pagination a, .ja-pagination .current {
	display: inline-flex; align-items: center; justify-content: center;
	min-width: calc(var(--ja-root) * 2.75); min-height: calc(var(--ja-root) * 2.75);
	padding: 0 calc(var(--ja-root) * 0.5);
	border: 1px solid var(--ja-rule-strong); border-radius: var(--ja-radius); text-decoration: none;
}
.ja-pagination .current { background: var(--ja-accent); color: var(--ja-accent-ink); border-color: var(--ja-accent); font-weight: 700; }

/* ------------------------------------------------------------ homepage ---- */

.ja-home { padding-top: var(--ja-gap-lg); }
.ja-home-grid { display: grid; grid-template-columns: 1.55fr 1fr; gap: var(--ja-gap-lg); }

.ja-lead-link { color: inherit; text-decoration: none; display: block; }
.ja-lead-thumb { border-radius: var(--ja-radius); overflow: hidden; margin-bottom: calc(var(--ja-root) * 0.75); }
.ja-lead-thumb img { width: 100%; display: block; }
.ja-lead-title { margin: 0 0 calc(var(--ja-root) * 0.375); font-family: var(--ja-serif); font-size: var(--ja-size-h2); line-height: var(--ja-leading-tight); color: var(--ja-ink-strong); }
.ja-lead-dek { margin: 0; color: var(--ja-muted); font-size: var(--ja-size-meta); }

.ja-panel { background: var(--ja-bg-2); border: 1px solid var(--ja-rule); border-radius: var(--ja-radius); padding: var(--ja-gap); }
.ja-panel + .ja-panel { margin-top: var(--ja-gap); }
.ja-panel-title { margin: 0 0 calc(var(--ja-root) * 0.625); font-family: var(--ja-serif); font-size: calc(var(--ja-root) * 1.25); color: var(--ja-ink-strong); }
.ja-panel-copy, .ja-panel-more { font-size: var(--ja-size-meta); color: var(--ja-muted); }
.ja-panel-search { display: flex; gap: calc(var(--ja-root) * 0.375); margin-bottom: calc(var(--ja-root) * 0.75); flex-wrap: wrap; }
/*
 * --ja-rule-strong, not --ja-rule: a search input is a control, not a
 * decorative hairline, and needs the 3:1 non-text floor --ja-rule-strong
 * clears (see tokens.css). Mirrors the .ja-search input fix from Task 3.
 */
.ja-panel-search input[type="search"] {
	flex: 1; min-width: calc(var(--ja-root) * 9); min-height: calc(var(--ja-root) * 2.75);
	padding: 0 calc(var(--ja-root) * 0.625); font-size: var(--ja-root);
	background: var(--ja-bg); color: var(--ja-ink); border: 1px solid var(--ja-rule-strong); border-radius: var(--ja-radius);
	font-family: inherit;
}
.ja-panel-search button {
	min-height: calc(var(--ja-root) * 2.75); padding: 0 calc(var(--ja-root) * 0.875);
	background: var(--ja-accent); color: var(--ja-accent-ink); border: 0; border-radius: var(--ja-radius);
	font-size: var(--ja-size-meta); font-weight: 700; cursor: pointer;
}
.ja-panel-list { margin: 0 0 calc(var(--ja-root) * 0.5); padding: 0; list-style: none; font-size: var(--ja-size-meta); }
.ja-panel-list li + li { margin-top: calc(var(--ja-root) * 0.375); padding-top: calc(var(--ja-root) * 0.375); border-top: 1px solid var(--ja-rule); }

.ja-stats { display: flex; margin: 0 0 calc(var(--ja-root) * 0.625); padding: calc(var(--ja-root) * 0.625) 0 0; border-top: 1px solid var(--ja-rule); }
.ja-stats > div { flex: 1; text-align: center; }
/* --ja-ink, not --ja-muted: same 12px floor fix as .ja-card-kicker above. */
.ja-stats dt { font-size: var(--ja-size-label); text-transform: uppercase; letter-spacing: 0.08em; color: var(--ja-ink); }
.ja-stats dd { margin: 0; font-family: var(--ja-serif); font-size: calc(var(--ja-root) * 1.375); color: var(--ja-accent); }

/*
 * The three full width sections below the lead/side grid: Recent, Reviews,
 * Recently added guides. Each reuses .ja-cards, the same grid list.php
 * views already use, so a card looks and behaves identically wherever it
 * appears on the site.
 */
.ja-home-section { margin-top: var(--ja-gap-lg); }
.ja-home-section-head {
	display: flex; align-items: baseline; justify-content: space-between; gap: var(--ja-gap);
	margin-bottom: var(--ja-gap);
	padding-bottom: calc(var(--ja-root) * 0.625);
	border-bottom: 1px solid var(--ja-rule);
}
.ja-home-section-title { margin: 0; font-family: var(--ja-serif); font-size: var(--ja-size-h2); line-height: var(--ja-leading-tight); color: var(--ja-ink-strong); }
.ja-home-section-more { font-size: var(--ja-size-meta); color: var(--ja-accent); text-decoration: none; white-space: nowrap; }
.ja-home-section-more:hover { text-decoration: underline; }

@media (max-width: 900px) {
	.ja-home-grid { grid-template-columns: 1fr; }
}

/* -------------------------------------------------- contributors index ---- */

/*
 * /our-authors/, rendered by page-our-authors.php from Nivoli\JA\Contributors.
 *
 * 414 names in one page, so the list is the thing that has to be cheap to scan.
 * Each letter is its own block with its own heading, and only the names inside
 * a block flow into columns: a single multi-column run over the whole index
 * would let the M heading sit at the bottom of column two with its names in
 * column three.
 */
.ja-contribs-count { font-size: var(--ja-size-meta); color: var(--ja-muted); margin: 0 0 var(--ja-gap); }

/*
 * The letter strip. Sticky, because a reader who has scrolled to S and wants B
 * should not have to go back up 4,000px to change their mind. --ja-bg, not
 * transparent: names scroll underneath it.
 */
.ja-contribs-jump {
	position: sticky; top: 0; z-index: 2;
	padding: calc(var(--ja-root) * 0.375) 0;
	margin-bottom: var(--ja-gap);
	background: var(--ja-bg);
	border-bottom: 1px solid var(--ja-rule);
}
.ja-contribs-jump ul {
	display: flex; flex-wrap: wrap; gap: calc(var(--ja-root) * 0.125);
	margin: 0; padding: 0; list-style: none;
}
/*
 * A jump link is a control, so it gets the 44px box the rest of the theme's
 * controls get (see .ja-nav-list li, .ja-pagination a). At a 12px label that is
 * mostly padding, which is the point: 27 single characters in a row are the
 * easiest thing on the page to miss with a thumb.
 */
.ja-contribs-jump a {
	display: inline-flex; align-items: center; justify-content: center;
	min-width: calc(var(--ja-root) * 2.75); min-height: calc(var(--ja-root) * 2.75);
	font-size: var(--ja-size-meta); font-weight: 700;
	text-decoration: none; border-radius: var(--ja-radius);
}
.ja-contribs-jump a:hover { background: var(--ja-bg-2); }

.ja-contribs-group { margin-bottom: var(--ja-gap-lg); }
/*
 * scroll-margin-top clears the sticky letter strip above: without it a jump to
 * #contributors-m puts the M heading exactly underneath the bar that was just
 * clicked. Sized off the same 2.75 unit the bar's own links are.
 */
.ja-contribs-letter {
	scroll-margin-top: calc(var(--ja-root) * 4);
	margin: 0 0 calc(var(--ja-root) * 0.5);
	padding-bottom: calc(var(--ja-root) * 0.25);
	border-bottom: 1px solid var(--ja-rule);
	font-family: var(--ja-serif); font-size: calc(var(--ja-root) * 1.375);
	line-height: var(--ja-leading-tight); color: var(--ja-accent);
}
.ja-contribs-list {
	margin: 0; padding: 0; list-style: none;
	columns: auto calc(var(--ja-root) * 15);
	column-gap: var(--ja-gap);
}
/* A name and its count are one row; a column break through the middle of one
   would read as two half rows. */
.ja-contribs-list li { break-inside: avoid; }
/*
 * The whole row is the link, name and count together, so the target is the
 * width of the column rather than the width of the name. 44px tall for the same
 * reason every other control in this theme is.
 */
.ja-contribs-list a {
	display: flex; align-items: baseline; justify-content: space-between;
	gap: calc(var(--ja-root) * 0.5);
	min-height: calc(var(--ja-root) * 2.75);
	padding: 0 calc(var(--ja-root) * 0.25);
	text-decoration: none; color: var(--ja-ink);
	border-bottom: 1px solid var(--ja-rule);
}
.ja-contribs-list a:hover { background: var(--ja-bg-2); color: var(--ja-ink-strong); }
.ja-contribs-name { min-width: 0; font-size: var(--ja-size-meta); }
/*
 * --ja-muted at --ja-size-meta (14px), which is the size tokens.css verifies it
 * at, so the count can recede without dropping under the contrast floor.
 */
.ja-contribs-n { flex: 0 0 auto; font-size: var(--ja-size-meta); color: var(--ja-muted); }

/* ------------------------------------------------------- recirculation ---- */

/*
 * What to read next, printed below the article/rail row (see single.php,
 * Nivoli\JA\Recirculation). Reuses .ja-cards/.ja-card for the entries and
 * mirrors .ja-home-section-head's layout for the block heading, so a
 * suggestion looks and behaves like every other card grid on the site
 * rather than introducing a fourth visual language for "a list of posts".
 */
.ja-recirc { margin-top: var(--ja-gap-lg); padding-top: var(--ja-gap-lg); border-top: 1px solid var(--ja-rule); }
.ja-recirc-head {
	display: flex; align-items: baseline; justify-content: space-between; gap: var(--ja-gap);
	margin-bottom: var(--ja-gap);
	padding-bottom: calc(var(--ja-root) * 0.625);
	border-bottom: 1px solid var(--ja-rule);
}
.ja-recirc-title { margin: 0; font-family: var(--ja-serif); font-size: var(--ja-size-h2); line-height: var(--ja-leading-tight); color: var(--ja-ink-strong); }
.ja-recirc-more { font-size: var(--ja-size-meta); color: var(--ja-accent); text-decoration: none; white-space: nowrap; }
.ja-recirc-more:hover { text-decoration: underline; }
/*
 * The guides list sits below the sibling-articles grid inside the SAME game
 * block, so it gets a subtitle one size down from .ja-recirc-title, no
 * border or "more" link of its own: it belongs to the block above it, not a
 * second block.
 */
.ja-recirc-subtitle { margin: var(--ja-gap) 0 calc(var(--ja-root) * 0.625); font-family: var(--ja-serif); font-size: calc(var(--ja-root) * 1.25); color: var(--ja-ink-strong); }

.ja-recirc-fallback { display: flex; flex-wrap: wrap; gap: var(--ja-gap); margin: 0; }
/* flex-basis derives from --ja-root like every other size in this file, not
   a bare px value: two links side by side on desktop, stacked full width
   the moment they no longer fit. */
.ja-recirc-btn { flex: 1 1 calc(var(--ja-root) * 13); }

/* ------------------------------------------- article enhancements ---- */

/* Pros and cons cards and the click to load YouTube facade. Both were styled in
   the Customizer record and driven by a script injected through the retired
   theme's footer copy option. See assets/js/enhance.js. */

.ja-proscons {
	display: flex; flex-wrap: wrap; gap: calc(var(--ja-root) * 1.125);
	margin: calc(var(--ja-root) * 1.6) 0;
	font-family: var(--ja-sans);
}
.ja-proscons .ja-col {
	flex: 1 1 calc(var(--ja-root) * 16.25);
	background: var(--ja-bg-2); border: 1px solid var(--ja-rule); border-radius: calc(var(--ja-root) * 0.5);
	padding: calc(var(--ja-root) * 0.875) calc(var(--ja-root) * 1.125);
}
/*
 * 14px (--ja-size-meta), not the original 13px: there is no token for 13,
 * and the header colour below (--ja-good) is only checked at 4.5:1 against
 * --ja-bg-2, the tier the binding rules only clear text at 14px and up.
 */
.ja-proscons h4 { margin: 0 0 calc(var(--ja-root) * 0.5); font-size: var(--ja-size-meta); letter-spacing: 0.06em; text-transform: uppercase; font-weight: 600; }
/* --ja-good on --ja-bg-2 measures ~4.98:1, clears the 4.5:1 floor this heading's
   14px size is entitled to (see the note above). */
.ja-proscons .ja-pros h4 { color: var(--ja-good); }
/*
 * --ja-ink-strong, not a "bad" colour: tokens.css has no red/danger token,
 * and inventing a literal hex here would recreate the very drift Task 9
 * retires the Customizer record to end. "The Bad" and the leading "–" glyph
 * already carry the meaning colour used to on the old site; --ja-ink-strong
 * (13.18:1 on --ja-bg-2, per tokens.css) keeps the heading legible without one.
 */
.ja-proscons .ja-cons h4 { color: var(--ja-ink-strong); }
.ja-proscons ul { list-style: none; margin: 0; padding: 0; }
/*
 * font-size: --ja-size-guide (18px), the closer of the two body tokens to
 * the original 17px. line-height: --ja-leading (1.7), the closer of the two
 * leading tokens to the original 1.5; tokens.css defines only 1.7 and 1.2.
 * color: --ja-ink is an exact match for the original #ddd6c6.
 */
.ja-proscons li {
	position: relative; padding-left: calc(var(--ja-root) * 1.375); margin: calc(var(--ja-root) * 0.375) 0;
	color: var(--ja-ink); line-height: var(--ja-leading); font-size: var(--ja-size-guide);
}
.ja-proscons .ja-pros li::before { content: '+'; position: absolute; left: 0; top: -1px; color: var(--ja-good); font-weight: 700; }
.ja-proscons .ja-cons li::before { content: '–'; position: absolute; left: 0; top: -1px; color: var(--ja-ink-strong); font-weight: 700; }

/*
 * The facade is a <button> now (see enhance.js), not a div, so the usual
 * UA button chrome is reset here: border, background shorthand, padding,
 * font and text-align all need an explicit value they never did as a div.
 * --ja-bg-sunken for the poster-frame well: the same "recessed surface
 * behind an image before it paints" role tokens.css already documents for
 * .ja-card-thumb, extended to a video poster instead of a cover image.
 */
.ja-lite-yt {
	display: block; position: relative; width: 100%; aspect-ratio: 16 / 9;
	background: var(--ja-bg-sunken) center/cover no-repeat;
	border: 0; border-radius: calc(var(--ja-root) * 0.5); padding: 0; margin: calc(var(--ja-root) * 1.4) 0;
	font: inherit; text-align: left; appearance: none; cursor: pointer; overflow: hidden;
}
/*
 * The original dimmed this layer with rgba(0,0,0,.12), a literal colour.
 * An opaque --ja-bg-sunken fill at 12% opacity composites to the same
 * result without one, and clearing to 0 opacity on hover reproduces the
 * original's rgba(0,0,0,0).
 */
.ja-lite-yt::after { content: ''; position: absolute; inset: 0; background: var(--ja-bg-sunken); opacity: 0.12; transition: opacity 0.2s; }
.ja-lite-yt:hover::after { opacity: 0; }
/*
 * Opaque, not the original's rgba(20,20,20,.8): a translucent pill's
 * contrast against the poster photo behind it depends on that photo, so it
 * cannot be guaranteed. Solid --ja-bg-sunken against the --ja-ink-strong
 * triangle below measures ~15.6:1, clearing the 3:1 non-text floor
 * regardless of what image sits under it.
 */
.ja-lite-yt-play {
	position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
	width: calc(var(--ja-root) * 4.25); height: calc(var(--ja-root) * 3);
	border: 0; border-radius: calc(var(--ja-root) * 0.875); background: var(--ja-bg-sunken);
	transition: background 0.2s;
}
.ja-lite-yt-play::before {
	content: ''; position: absolute; left: 50%; top: 50%; transform: translate(-40%, -50%);
	border-style: solid; border-width: 10px 0 10px 18px;
	border-color: transparent transparent transparent var(--ja-ink-strong);
}
/*
 * The original swapped this pill to #f00, YouTube's brand red, on hover:
 * a literal colour with no token, and no equivalent one belongs in this
 * system. --ja-accent is this theme's own hover/active colour instead, and
 * --ja-accent-ink is the token already established (search button, .ja-btn)
 * for text and icons that sit on an --ja-accent fill, so the triangle
 * repaints to it here too. Computed pairing, ~7.4:1, clears the 3:1 non-text
 * floor; --ja-ink-strong would not (~2:1 against --ja-accent), which is why
 * it only appears in the base state above.
 */
.ja-lite-yt:hover .ja-lite-yt-play { background: var(--ja-accent); }
.ja-lite-yt:hover .ja-lite-yt-play::before { border-color: transparent transparent transparent var(--ja-accent-ink); }

/* ------------------------------------------- migrated from Customizer ---- */

/* What survived the retired theme. Everything that targeted .article-post-content,
   .article_body, #page-header, #top-navigation, #header-navigation, .sidebar,
   #page-content, #page-footer, .entry-meta or body.night-mode went away with the
   theme it was patching, along with the forced dark background and the Inter
   @import: this theme is dark by default, self-hosts Inter, and needs no
   !important to prove either. The pros and cons and lite YouTube rules moved
   in Task 6, with their script. The table border reset is Task 3's
   .ja-prose table / td / th, already in this file. */

/* Old reviews embed a white logo GIF inside a layout table. It reads as a hole
   punched in the page on a dark background. */
.ja-prose table img[alt="Logo" i] { display: none; }

/* Browse by Topic. Ordinary page content, so it outlives any theme. */
.ja-topics { max-width: var(--ja-measure); }
.ja-topics h2 { font-family: var(--ja-serif); font-size: var(--ja-size-h2); color: var(--ja-ink-strong); }
.ja-topics-intro, .ja-topics-foot { color: var(--ja-muted); font-size: var(--ja-size-meta); }
.ja-topics-intro a, .ja-topics-foot a { color: var(--ja-accent); }

.ja-tagcloud { display: flex; flex-wrap: wrap; gap: calc(var(--ja-root) * 0.5); }
.ja-tagcloud a {
	display: inline-flex; align-items: center;
	min-height: calc(var(--ja-root) * 2.75);
	padding: 0 calc(var(--ja-root) * 0.625);
	border: 1px solid var(--ja-rule); border-radius: 999px;
	font-size: var(--ja-size-meta); text-decoration: none;
}
.ja-tagcloud a:hover { border-color: var(--ja-accent); }

/*
 * Popularity tiers (t1..t5): the page markup itself carries these classes per
 * tag, one per link, sized 13/15/17/19/23px in the original. Kept as calc()
 * steps off --ja-root so the cloud still reads as a cloud, biggest tags
 * heaviest. t4 reuses --ja-size-body (already 19px) rather than a new step.
 * t4/t5 also pick up a background: --ja-bg-2, the theme's established raised
 * surface (see .ja-gamecard), so the busiest tags still stand off the page
 * the way the original's bespoke shades did.
 */
.ja-tagcloud .t1 { font-size: calc(var(--ja-root) * 0.8125); opacity: 0.92; }
.ja-tagcloud .t2 { font-size: calc(var(--ja-root) * 0.9375); }
.ja-tagcloud .t3 { font-size: calc(var(--ja-root) * 1.0625); }
.ja-tagcloud .t4 { font-size: var(--ja-size-body); font-weight: 600; background: var(--ja-bg-2); }
.ja-tagcloud .t5 {
	font-size: calc(var(--ja-root) * 1.4375); font-weight: 700;
	color: var(--ja-ink-strong); background: var(--ja-bg-2); border-color: var(--ja-accent);
}

/* By platform: same pill, no popularity tiers, a quieter label colour. */
.ja-platforms a { font-size: calc(var(--ja-root) * 0.9375); color: var(--ja-muted); }

/*
 * Count badge. The original set font-size: .74em against the *link's* size,
 * which on a t1 tag (13px) resolves under the 12px floor. max() against the
 * label token is the same fix already used for .ja-prose code/pre. Because
 * that floor can bind, this sits at the 12px floor like .ja-crumb and
 * .ja-gamecard-meta: --ja-ink, not --ja-muted (see tokens.css).
 */
.ja-tagcloud a span {
	margin-left: calc(var(--ja-root) * 0.3125);
	padding: 0.12em calc(var(--ja-root) * 0.34375);
	border-radius: 999px;
	background: var(--ja-bg-sunken);
	color: var(--ja-ink);
	font-size: max(var(--ja-size-label), 0.74em);
	font-weight: 600;
}
.ja-lite-yt iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
