/*
 * 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;
}
.ja-nav-list a { 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; }

.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); }

@media (max-width: 720px) {
	.ja-search { margin-left: 0; width: 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; }
}

/* ------------------------------------------------------------- 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 { color: var(--ja-ink); text-decoration: none; }

.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);
}

.ja-dek {
	margin: 0 0 var(--ja-gap);
	font-size: calc(var(--ja-root) * 1.0625);
	font-style: italic;
	color: color-mix(in srgb, var(--ja-ink) 85%, var(--ja-bg));
}

.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; }

.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 {
	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. */
.ja-gamecard-cover { display: block; width: 100%; 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); }

.ja-cards {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(calc(var(--ja-root) * 17), 1fr));
	gap: var(--ja-gap);
}

.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); }
.ja-card-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ja-card-body { padding: calc(var(--ja-root) * 0.75); }
/*
 * 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; }
.ja-card-title { margin: 0; font-family: var(--ja-serif); font-size: calc(var(--ja-root) * 1.125); line-height: var(--ja-leading-tight); color: var(--ja-ink-strong); }
.ja-card-meta { margin: calc(var(--ja-root) * 0.25) 0 0; font-size: var(--ja-size-label); color: var(--ja-ink); }
.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;
}
.ja-card--text .ja-card-body { padding: var(--ja-gap); }
.ja-card--text .ja-card-title { font-size: var(--ja-size-h2); }

.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-home-strip { display: grid; grid-template-columns: 1fr 1fr; gap: var(--ja-gap); margin-top: var(--ja-gap-lg); }
.ja-strip-item a { display: block; color: inherit; text-decoration: none; }
.ja-strip-item strong { display: block; font-family: var(--ja-serif); font-size: calc(var(--ja-root) * 1.0625); line-height: var(--ja-leading-tight); color: var(--ja-ink-strong); }
/*
 * --ja-ink, not --ja-muted: this date sits at --ja-size-label (12px), the
 * floor where --ja-muted is not verified (see tokens.css). Same fix as
 * .ja-card-kicker, .ja-card-meta and .ja-gamecard-meta above.
 */
.ja-strip-item span { font-size: var(--ja-size-label); color: var(--ja-ink); }

.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-strip-item span 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); }

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

/* ------------------------------------------- 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; }
