/**
 * Vote Page frame — nominee renderer (Task 3).
 *
 * Styles `shining_render_nominees()` output (`.sa-nom`), which frames the
 * TotalPoll widget with a premium, poll-sourced nominee list. Three visual
 * layouts share the same markup/classes and are switched purely with a
 * modifier class: `.sa-nom--grid` (face grid, default), `.sa-nom--roster`
 * (two-column info cards), `.sa-nom--chips` (flowing compact chips).
 *
 * Ported + rescoped from the approved mockup (grid-a/g-item/g-name/g-grp,
 * grid-b/r-card/r-rank/r-name/r-grp/r-link, grid-c/chip/c-name/c-grp) into
 * `.sa-nom__*` BEM-ish parts, and re-pointed from literal hex to the theme's
 * `--sa-*` tokens (`tokens.css`) so it tracks the active palette.
 *
 * Never touches the TotalPoll plugin — this only styles our own frame markup.
 *
 * @package Shining
 */

/* Lazy-frame placeholder: a heavy poll's frame is fetched by vote-frame.js and
   swapped in for these. Empty until then — collapse it so it never adds a gap
   (and defeat any .entry-content div spacing it would otherwise inherit). */
.sa-vf-lazy { margin: 0 !important; padding: 0; min-height: 0; }
.sa-vf-lazy:empty { display: none; }

/* Voting-page article title — the <h1> at the top of a vote post — is rendered
   in UPPERCASE. Two guards, both body classes: `shining-vote-post` (added only
   on singular posts that host a poll, so ordinary articles / news / K-Pop /
   K-Drama posts are never touched) and `sa-vote-uc` (the "Force UPPERCASE
   titles" switch in the Vote Page studio, on by default — remove it to opt out
   site-wide). Both are set on <body>, so they combine without a descendant.

   Two selectors on purpose: the Typography studio pins the single title's
   casing at `html .single .entry-header h1.post-title.entry-title
   {text-transform:none}` (0,4,2) — pure/typography.php — which outranks the
   plain guard (0,3,1). The first selector (0,5,3) exists solely to beat that
   on the standard layout; the plain one still covers post layouts whose title
   sits outside `.entry-header` (e.g. the fullwidth featured-area header),
   where the typography rule never matches. */
html body.sa-vote-uc.shining-vote-post .entry-header h1.post-title.entry-title,
body.sa-vote-uc.shining-vote-post .entry-title {
	text-transform: uppercase;
}

.sa-nom {
	max-width: 1080px;
	margin: 34px auto;
	padding: 0 16px;
}

/* Nominee section header: uppercase, wide-tracked and gradient-filled, with a
   hairline-and-heart rule beneath it. Uppercase because this is a section
   LABEL, not a sentence — at display weight the extra tracking is what stops
   it reading as shouting. The rule does the separating so the heading itself
   needs no box or underline. */
.sa-nom__head {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 12px;
	margin-bottom: 30px;   /* the breathing room between label and avatars */
}
.sa-nom__heading {
	font-family: var(--sa-font-display);
	font-weight: 800;
	font-size: clamp(19px, 2.9vw, 27px);
	line-height: 1.15;
	text-transform: uppercase;
	letter-spacing: .14em;
	/* Tracking adds space AFTER the final letter too, which visually pushes a
	   centred line left. Pulling that back re-centres it optically. */
	text-indent: .14em;
	text-align: center;
	text-wrap: balance;
	margin: 0;
}

/* Hairline that fades out from a centre heart — the same rose motif the rest
   of the theme uses, at section scale. */
.sa-nom__rule {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	width: min(260px, 62%);
	color: var(--sa-heart);
}
.sa-nom__rule::before,
.sa-nom__rule::after {
	content: "";
	flex: 1;
	height: 1px;
	background: linear-gradient(90deg, transparent, var(--sa-border-strong));
}
.sa-nom__rule::after { background: linear-gradient(90deg, var(--sa-border-strong), transparent); }
.sa-nom__heart { width: 11px; height: 11px; flex: none; }

@media (max-width: 480px) {
	.sa-nom__head { gap: 10px; margin-bottom: 22px; }
	.sa-nom__heading { letter-spacing: .1em; text-indent: .1em; }
}

/* Shared avatar shell — reused by all three nominee layouts AND the standings
   strip; sizes are set per-layout below. `shining_nominee_avatar()` always includes this base class, whether
   it renders an initials span or a `--photo` span wrapping an <img>. */
.sa-nom__av,
.sa-stand__av,
.sa-pulse__av {
	border-radius: 50%;
	overflow: hidden;
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--sa-gradient);
	color: var(--sa-on-accent);
	font-family: var(--sa-font-display);
	font-weight: 800;
	flex: none;
}

/* Real nominee photo — reproduce the hero's own focal crop so the FACE fills
   the circle (no "frame-in-frame"): the image is blown up past the visible
   frame and offset by the per-nominee focal point (--np-fx/--np-fy/--np-zoom).
   Verbatim from home.php's `.sa-hero__av--photo` rules, renamed only. */
.sa-nom__av--photo,
.sa-stand__av--photo,
.sa-pulse__av--photo{position:relative;background:var(--sa-surface-2);}
.sa-nom__av--photo img,
.sa-stand__av--photo img,
.sa-pulse__av--photo img{position:absolute;width:calc(308% * var(--np-zoom,1));height:calc(308% * var(--np-zoom,1));max-width:none;max-height:none;left:calc(var(--np-fx,.5) * (1 - 3.08 * var(--np-zoom,1)) * 100%);top:calc(var(--np-fy,.4) * (1 - 3.08 * var(--np-zoom,1)) * 100%);object-fit:cover;object-position:center 40%;}

.sa-nom__name {
	font-weight: 600;
	color: var(--sa-text);
}

.sa-nom__grp {
	color: var(--sa-violet-light);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .04em;
}

/* Leak defense: each nominee is a full-width <a>, and when the frame renders
   inside `.entry-content` it inherits Jannah's gradient-underline for links
   (`background-image: linear-gradient(...)`), which stretches into a stray
   horizontal line across the whole grid row. Kill the inherited underline on
   every nominee link; the roster/chips layouts set their own background-COLOR
   separately, so only the leaked image is removed. `!important` because the
   base `.entry-content a` rule outranks our layout selectors and LiteSpeed
   combines CSS so source order can't be relied on. */
.sa-nom__item {
	background-image: none !important;
	text-decoration: none !important;
	box-shadow: none;
}

/* ------------------------------------------------------------------ */
/* Semantic list resets                                               */
/* ------------------------------------------------------------------ */
/* Both rosters are real <ul>/<ol> now. Inside .entry-content that means
   inheriting Jannah's prose list styling — bullets/numbers, a left indent, and
   a per-item font-size — none of which belong on a layout grid. Reset at the
   source and keep the layout rules untouched. !important because the prose
   rules are element-based inside a class-scoped ancestor and LiteSpeed combines
   CSS, so source order cannot settle it. See the note on .sa-nom__item. */
.sa-nom__list,
.sa-stand__list,
.sa-follow__list {
	list-style: none !important;
	margin: 0 !important;
	padding: 0 !important;
}
.sa-nom__cell,
.sa-stand__item,
.sa-follow__cell {
	list-style: none !important;
	margin: 0 !important;
	padding: 0 !important;
	font-size: inherit;
	line-height: inherit;
	min-width: 0;   /* let grid/flex children actually shrink */
}
.sa-nom__cell::marker,
.sa-stand__item::marker,
.sa-follow__cell::marker { content: ""; }
.sa-nom__cell::before,
.sa-stand__item::before,
.sa-follow__cell::before { content: none !important; }

/* ------------------------------------------------------------------ */
/* Layout: grid — face gallery (default)                              */
/* ------------------------------------------------------------------ */
.sa-nom--grid .sa-nom__list {
	display: grid;
	grid-template-columns: repeat(var(--sa-nom-cols, 5), 1fr);
	gap: 18px 12px;
}
.sa-nom--grid .sa-nom__item {
	display: block;
	height: 100%;
	text-align: center;
	text-decoration: none;
	color: inherit;
	display: block;
}
/* ~28% smaller than the old 80px shell — tighter on desktop without going tiny;
   mobile shrinks further (and gains a column) in the responsive block below. */
.sa-nom--grid .sa-nom__av {
	width: 58px;
	height: 58px;
	margin: 0 auto 8px;
	font-size: 19px;
	transition: transform .2s ease;
}
.sa-nom--grid .sa-nom__name {
	display: block;
	font-size: 13px;
}
.sa-nom--grid .sa-nom__grp {
	display: block;
	font-size: 10.5px;
	margin-top: 2px;
}
.sa-nom--grid .sa-nom__item:hover .sa-nom__av {
	transform: translateY(-3px);
}

/* ------------------------------------------------------------------ */
/* Layout: roster — two-column info cards                             */
/* ------------------------------------------------------------------ */
.sa-nom--roster .sa-nom__list {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 12px;
}
.sa-nom--roster .sa-nom__item {
	height: 100%;   /* cards in a row match, whatever the name length */
	display: flex;
	align-items: center;
	gap: 14px;
	background: var(--sa-surface-2);
	border: 1px solid var(--sa-border);
	border-radius: 14px;
	padding: 12px 14px;
	position: relative;
	overflow: hidden;
	text-decoration: none;
	color: inherit;
	transition: border-color .15s ease;
}
.sa-nom--roster .sa-nom__item::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0;
	bottom: 0;
	width: 3px;
	background: var(--sa-gradient);
}
.sa-nom--roster .sa-nom__item:hover {
	border-color: var(--sa-border-strong);
}
.sa-nom--roster .sa-nom__av {
	width: 54px;
	height: 54px;
	font-size: 19px;
}
.sa-nom--roster .sa-nom__rank {
	position: absolute;
	top: 10px;
	right: 12px;
	font-family: var(--sa-font-display);
	font-weight: 800;
	font-size: 12px;
	color: var(--sa-text-dim);
}
.sa-nom--roster .sa-nom__meta {
	display: flex;
	flex-direction: column;
	min-width: 0;
}
.sa-nom--roster .sa-nom__name {
	font-size: 15px;
}
.sa-nom--roster .sa-nom__grp {
	font-size: 12px;
}
.sa-nom--roster .sa-nom__link {
	color: var(--sa-text-dim);
	font-size: 11.5px;
	margin-top: 3px;
}

/* ------------------------------------------------------------------ */
/* Layout: chips — compact, flowing                                   */
/* ------------------------------------------------------------------ */
.sa-nom--chips .sa-nom__list {
	display: flex;
	flex-wrap: wrap;
	gap: 9px;
	justify-content: center;
}
.sa-nom--chips .sa-nom__item {
	display: inline-flex;
	align-items: center;
	gap: 9px;
	background: var(--sa-surface-2);
	border: 1px solid var(--sa-border);
	border-radius: 999px;
	padding: 6px 14px 6px 6px;
	text-decoration: none;
	color: inherit;
	transition: border-color .15s ease;
}
.sa-nom--chips .sa-nom__item:hover {
	border-color: var(--sa-border-strong);
}
.sa-nom--chips .sa-nom__av {
	width: 34px;
	height: 34px;
	font-size: 13px;
}
.sa-nom--chips .sa-nom__name {
	font-size: 13.5px;
}
.sa-nom--chips .sa-nom__grp {
	margin-left: 2px;
	font-size: 11px;
}

/* ------------------------------------------------------------------ */
/* Responsive                                                         */
/* ------------------------------------------------------------------ */
@media (max-width: 720px) {
	.sa-nom--grid .sa-nom__list {
		grid-template-columns: repeat(4, 1fr) !important;
		gap: 14px 8px;
	}
	.sa-nom--grid .sa-nom__av { width: 60px; height: 60px; margin-bottom: 6px; font-size: 18px; }
	.sa-nom--grid .sa-nom__name { font-size: 12.5px; }
	.sa-nom--grid .sa-nom__grp { font-size: 10px; }
	.sa-nom--roster .sa-nom__list { grid-template-columns: 1fr; }
}
/* Phones: 3 across (was 2), with much shorter row rhythm so the whole roster
   fits in far less vertical space — no more tall scrolling. Avatar + gaps
   tightened to fit a ~360px viewport while the face + name stay readable. */
@media (max-width: 460px) {
	.sa-nom--grid .sa-nom__list {
		grid-template-columns: repeat(3, 1fr) !important;
		gap: 14px 6px;
	}
	.sa-nom--grid .sa-nom__av { width: 58px; height: 58px; margin-bottom: 5px; font-size: 17px; }
	.sa-nom--grid .sa-nom__name { font-size: 11.5px; line-height: 1.2; }
	.sa-nom--grid .sa-nom__grp { font-size: 9px; margin-top: 1px; }
	.sa-nom__heading { margin-bottom: 12px; }
	.sa-nom { margin: 22px auto; }
}

@media (prefers-reduced-motion: reduce) {
	.sa-nom--grid .sa-nom__av,
	.sa-nom--roster .sa-nom__item,
	.sa-nom--chips .sa-nom__item {
		transition: none;
	}
}

/* ------------------------------------------------------------------ */
/* "About this poll" info panel v2 — four styles rendered by            */
/* `shining_render_poll_info()`: Holo Pass (default), Countdown         */
/* Marquee, Live Board and Aurora Strip. All share `.sa-pinfo__card`:   */
/* a 1px gradient hairline (double-background trick, no extra element)  */
/* plus a specular shine sweep — a transform-only overlay that runs     */
/* FIVE times with a ~2s rest between passes, then stops for good. The  */
/* sweep only starts when the card scrolls into view (`.is-lit`, set    */
/* by vote-frame.js) so nothing animates unseen below the fold.         */
/* The "time left" chip + window meter are hydrated client-side.        */
/* ------------------------------------------------------------------ */
.sa-pinfo {
	max-width: 1080px;
	margin: 26px auto;
	padding: 0 16px;
}
/* Shared gradient-text helper (nominee heading + every panel style). */
.sa-nom__heading.sa-grad,
.sa-pinfo .sa-grad {
	background: var(--sa-gradient);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
}
/* Tutorial link (board + strip; holo/marquee restyle it). */
.sa-pinfo__tut {
	display: inline-block;
	color: var(--sa-violet-light);
	font-weight: 600;
	font-size: 12.5px;
	text-decoration: none;
}
.sa-pinfo__tut:hover { text-decoration: underline; }

/* -- The shared premium frame ----------------------------------------- */
.sa-pinfo__card {
	position: relative;
	border: 1px solid transparent;
	border-radius: 18px;
	overflow: hidden;
	background:
		linear-gradient(180deg, var(--sa-surface-1), var(--sa-bg-2)) padding-box,
		linear-gradient(130deg, var(--sa-border-strong), var(--sa-border) 30%, var(--sa-border) 62%, var(--sa-border-strong)) border-box;
}
/* The shine sweep. Finite by design: 5 passes, each cycle = ~1.3s of
   sweep + ~2.1s of rest, then the animation ends and the overlay parks
   off-canvas. transform-only = GPU-composited, no layout/paint work. */
.sa-pinfo__card::before {
	content: "";
	position: absolute;
	inset: -2px;
	z-index: 3;
	pointer-events: none;
	background: linear-gradient(115deg, transparent 42%, rgba(255, 255, 255, .12) 50%, transparent 58%);
	transform: translateX(-101%);
}
.sa-pinfo.is-lit .sa-pinfo__card::before {
	animation: sa-pinfo-sweep 3.4s ease-in-out .4s 5;
}
@keyframes sa-pinfo-sweep {
	0% { transform: translateX(-101%); }
	38% { transform: translateX(101%); }
	100% { transform: translateX(101%); }
}

/* Pulsing "live" dot. The ring colour follows the active palette. */
.sa-pinfo__dot {
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: var(--sa-violet);
	flex: none;
	animation: sa-pinfo-p 1.9s infinite;
}
@keyframes sa-pinfo-p {
	0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--sa-violet) 50%, transparent); }
	70% { box-shadow: 0 0 0 8px transparent; }
	100% { box-shadow: 0 0 0 0 transparent; }
}
.sa-pinfo__heart {
	width: 13px;
	height: 13px;
	color: var(--sa-heart);
	flex: none;
}

/* "9 days left" chip — hydrated by vote-frame.js from data-sa-timeleft. */
.sa-pinfo__chip {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-size: 11.5px;
	font-weight: 700;
	color: var(--sa-violet-light);
	border: 1px solid var(--sa-border-strong);
	border-radius: 999px;
	padding: 5px 11px;
	letter-spacing: .04em;
	white-space: nowrap;
	background: rgba(255, 255, 255, .04);
	background: color-mix(in srgb, var(--sa-violet) 8%, transparent);
}
.sa-pinfo__chip-ic { width: 12px; height: 12px; flex: none; }

/* Voting-window meter (holo + marquee). Bar width hydrated client-side. */
.sa-pinfo__meterwrap { margin-top: 18px; max-width: 430px; }
.sa-pinfo__meter {
	height: 4px;
	border-radius: 999px;
	background: rgba(255, 255, 255, .09);
	background: color-mix(in srgb, var(--sa-text) 10%, transparent);
	overflow: hidden;
}
.sa-pinfo__meter i {
	display: block;
	height: 100%;
	border-radius: 999px;
	background: var(--sa-gradient);
}
.sa-pinfo__meterfoot {
	display: flex;
	justify-content: space-between;
	gap: 12px;
	font-size: 10.5px;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--sa-text-dim);
	font-weight: 600;
	margin-top: 7px;
}

@media (prefers-reduced-motion: reduce) {
	.sa-pinfo.is-lit .sa-pinfo__card::before { animation: none; }
	.sa-pinfo__dot { animation: none; }
}

/* -- A · Holo Pass (default) ------------------------------------------ */
.sa-holo { display: grid; grid-template-columns: 1fr 280px; }
.sa-pinfo--holo.is-nostub .sa-holo { grid-template-columns: 1fr; }
.sa-holo__main {
	padding: clamp(20px, 4.5vw, 30px);
	min-width: 0;
	background: linear-gradient(115deg, rgba(255, 255, 255, .04), transparent 55%);
	background: linear-gradient(115deg, color-mix(in srgb, var(--sa-violet) 8%, transparent), transparent 55%);
}
.sa-holo__eyerow {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	flex-wrap: wrap;
	margin-bottom: 16px;
}
.sa-holo__eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-size: 11px;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--sa-violet);
	font-weight: 700;
}
.sa-holo__eyebrow.is-closed { color: var(--sa-text-dim); }
.sa-holo__date { line-height: .92; }
.sa-holo__d1 {
	display: block;
	font-family: var(--sa-font-display);
	font-weight: 800;
	font-size: clamp(44px, 9vw, 60px);
	letter-spacing: -.02em;
}
.sa-holo__d2 {
	display: block;
	font-family: var(--sa-font-display);
	font-weight: 600;
	font-size: clamp(14px, 3vw, 16.5px);
	color: var(--sa-text);
	letter-spacing: .02em;
	margin-top: 9px;
}
.sa-holo__headline {
	font-family: var(--sa-font-display);
	font-weight: 800;
	font-size: clamp(26px, 5vw, 38px);
	letter-spacing: -.02em;
	line-height: 1;
}
.sa-holo__closes {
	color: var(--sa-text-muted);
	font-size: 13px;
	margin-top: 13px;
	display: flex;
	align-items: center;
	gap: 7px;
}
.sa-holo__tut {
	display: inline-block;
	margin-top: 16px;
	background: var(--sa-gradient);
	color: var(--sa-on-accent);
	font-weight: 700;
	font-size: 13px;
	border-radius: 999px;
	padding: 9px 18px;
	text-decoration: none;
}

/* Stub: the perforated fact column. */
.sa-holo__stub {
	position: relative;
	padding: clamp(18px, 4vw, 22px);
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 15px;
	border-left: 2px dashed var(--sa-border-strong);
	background:
		repeating-linear-gradient(135deg, rgba(255, 255, 255, .03) 0 10px, transparent 10px 20px),
		var(--sa-surface-2);
}
/* Perforation notches, anchored to the STUB so they follow the tear line in
   both orientations (left edge on desktop, top edge on mobile). */
.sa-holo__notch {
	position: absolute;
	width: 20px;
	height: 20px;
	border-radius: 50%;
	background: var(--sa-bg);
	border: 1px solid var(--sa-border);
	transform: translate(-50%, -50%);
	z-index: 2;
}
.sa-holo__notch--t { left: 0; top: 0; }
.sa-holo__notch--b { left: 0; top: 100%; }
/* label on top, big value left, context right — all on one baseline grid */
.sa-holo__si {
	display: grid;
	grid-template-columns: 1fr auto;
	align-items: baseline;
	column-gap: 10px;
}
.sa-holo__lab {
	grid-column: 1 / -1;
	font-size: 11.5px;
	letter-spacing: .13em;
	text-transform: uppercase;
	color: var(--sa-text-dim);
	font-weight: 700;
	margin-bottom: 2px;
}
.sa-holo__v {
	font-family: var(--sa-font-display);
	font-weight: 800;
	font-size: clamp(24px, 6vw, 27px);
	letter-spacing: -.01em;
	font-variant-numeric: tabular-nums;
	color: var(--sa-text);
}
.sa-holo__v--sm { font-size: clamp(16px, 4.4vw, 18px); }
.sa-holo__sub {
	font-size: 11.5px;
	color: var(--sa-text-muted);
	font-weight: 600;
	justify-self: end;
	display: inline-flex;
	align-items: center;
	gap: 5px;
}
/* Serial + CSS barcode — fan-pass flavour, zero image bytes. */
.sa-holo__serial {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	margin-top: 4px;
	padding-top: 13px;
	border-top: 1px solid var(--sa-border);
}
.sa-holo__serial span:first-child {
	font-size: 10px;
	letter-spacing: .26em;
	text-transform: uppercase;
	color: var(--sa-text-dim);
	font-weight: 700;
}
.sa-holo__bars {
	flex: 1;
	max-width: 96px;
	height: 16px;
	opacity: .5;
	background: repeating-linear-gradient(90deg, var(--sa-text-dim) 0 1px, transparent 1px 3px, var(--sa-text-dim) 3px 5px, transparent 5px 6px);
}

@media (max-width: 640px) {
	/* The perforation ROTATES instead of disappearing: the tear goes
	   horizontal and the notches move to its ends, so the card still
	   reads as a ticket on a phone. */
	.sa-holo { grid-template-columns: 1fr; }
	.sa-holo__stub {
		border-left: none;
		border-top: 2px dashed var(--sa-border-strong);
	}
	.sa-holo__notch--t { left: 0; top: 0; }
	.sa-holo__notch--b { left: 100%; top: 0; }
}

/* -- B · Countdown Marquee -------------------------------------------- */
.sa-mq__body { padding: clamp(20px, 4.5vw, 30px); }
.sa-mq__top {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	flex-wrap: wrap;
	margin-bottom: 18px;
}
.sa-mq__eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-size: 11px;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--sa-violet);
	font-weight: 700;
}
.sa-mq__eyebrow.is-closed { color: var(--sa-text-dim); }
.sa-mq__hero {
	display: flex;
	align-items: center;
	gap: clamp(16px, 4vw, 28px);
	flex-wrap: wrap;
}
.sa-mq__num {
	font-family: var(--sa-font-display);
	font-weight: 800;
	font-size: clamp(64px, 14vw, 96px);
	line-height: .85;
	letter-spacing: -.03em;
	font-variant-numeric: tabular-nums;
}
.sa-mq__side { min-width: 0; flex: 1; }
.sa-mq__side b {
	display: block;
	font-family: var(--sa-font-display);
	font-weight: 800;
	font-size: clamp(20px, 5vw, 26px);
	letter-spacing: -.01em;
	line-height: 1.1;
	color: var(--sa-text);
}
.sa-mq__side span {
	display: block;
	color: var(--sa-text-muted);
	font-size: 13.5px;
	margin-top: 6px;
}
.sa-mq__side .sa-pinfo__tut { margin-top: 10px; }
.sa-mq__body .sa-pinfo__meterwrap { max-width: none; margin-top: 20px; }
.sa-mq__stats {
	display: grid;
	grid-template-columns: repeat(var(--sa-mq-cols, 3), 1fr);
	gap: 1px;
	background: var(--sa-border);
	border-top: 1px solid var(--sa-border);
}
.sa-mq__cell {
	background: var(--sa-surface-2);
	background: color-mix(in srgb, var(--sa-surface-2) 72%, transparent);
	padding: 15px 12px 16px;
	text-align: center;
}
.sa-mq__cv {
	font-family: var(--sa-font-display);
	font-weight: 800;
	font-size: clamp(22px, 6vw, 26px);
	letter-spacing: -.01em;
	font-variant-numeric: tabular-nums;
	color: var(--sa-text);
}
.sa-mq__cv--sm { font-size: clamp(15px, 4.2vw, 18px); }
.sa-mq__cl {
	font-size: 11px;
	letter-spacing: .13em;
	text-transform: uppercase;
	color: var(--sa-text-dim);
	font-weight: 700;
	margin-top: 4px;
}

/* -- C · Live Board ---------------------------------------------------- */
.sa-lbd { padding: clamp(20px, 4.5vw, 30px); }
.sa-lbd__top {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	flex-wrap: wrap;
}
.sa-lbd__eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-size: 11px;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--sa-violet);
	font-weight: 700;
}
.sa-lbd__eyebrow.is-closed { color: var(--sa-text-dim); }
.sa-lbd__hero { margin-top: 16px; }
.sa-lbd__lab {
	font-size: 11.5px;
	letter-spacing: .15em;
	text-transform: uppercase;
	color: var(--sa-text-dim);
	font-weight: 700;
}
.sa-lbd__num {
	font-family: var(--sa-font-display);
	font-weight: 800;
	font-size: clamp(48px, 12vw, 84px);
	line-height: .95;
	letter-spacing: -.03em;
	font-variant-numeric: tabular-nums;
	overflow-wrap: anywhere;
}
.sa-lbd__climb {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	color: var(--sa-text-muted);
	font-size: 13px;
	font-weight: 600;
	margin-top: 8px;
}
.sa-lbd__tiles {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
	gap: 10px;
	margin-top: 22px;
}
.sa-lbd__tile {
	border: 1px solid var(--sa-border);
	border-radius: 13px;
	padding: 13px 14px;
	background: var(--sa-surface-2);
	background: color-mix(in srgb, var(--sa-surface-2) 62%, transparent);
}
.sa-lbd__tv {
	font-family: var(--sa-font-display);
	font-weight: 800;
	font-size: clamp(19px, 5vw, 24px);
	letter-spacing: -.01em;
	font-variant-numeric: tabular-nums;
	color: var(--sa-text);
}
.sa-lbd__tv small {
	font-size: 12px;
	font-weight: 600;
	color: var(--sa-text-muted);
	letter-spacing: 0;
}
.sa-lbd__tl {
	font-size: 10.5px;
	letter-spacing: .13em;
	text-transform: uppercase;
	color: var(--sa-text-dim);
	font-weight: 700;
	margin-top: 3px;
}
.sa-lbd__tut { margin-top: 14px; }
@media (max-width: 430px) {
	.sa-lbd__tiles { grid-template-columns: 1fr 1fr; }
	.sa-lbd__tile--wide { grid-column: 1 / -1; }
}

/* -- D · Aurora Strip --------------------------------------------------- */
.sa-strip__rail {
	height: 3px;
	background: var(--sa-gradient);
	border-radius: 18px 18px 0 0;
}
.sa-strip__in {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
}
.sa-strip__cell {
	padding: clamp(18px, 4vw, 26px) clamp(16px, 3.4vw, 24px);
	border-right: 1px solid var(--sa-border);
	min-width: 0;
}
.sa-strip__cell:last-child { border-right: none; }
.sa-strip__cell--lead {
	background: radial-gradient(130% 100% at 0 0, rgba(255, 255, 255, .04), transparent 60%);
	background: radial-gradient(130% 100% at 0 0, color-mix(in srgb, var(--sa-violet) 7%, transparent), transparent 60%);
}
.sa-strip__lab {
	font-size: 11px;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--sa-text-dim);
	font-weight: 700;
	display: block;
	margin-bottom: 8px;
}
.sa-strip__v {
	font-family: var(--sa-font-display);
	font-weight: 800;
	font-size: clamp(21px, 6vw, 26px);
	letter-spacing: -.01em;
	line-height: 1.08;
	font-variant-numeric: tabular-nums;
	color: var(--sa-text);
}
.sa-strip__v--sm { font-size: clamp(16px, 4.4vw, 19px); }
.sa-strip__v small {
	display: block;
	font-family: var(--sa-font-body);
	font-size: 12px;
	font-weight: 600;
	color: var(--sa-text-muted);
	margin-top: 5px;
	letter-spacing: 0;
}
.sa-strip__foot {
	display: flex;
	align-items: center;
	gap: 7px;
	color: var(--sa-text-muted);
	font-size: 12px;
	font-weight: 600;
	margin-top: 6px;
}
.sa-strip__tut { margin-top: 10px; }
@media (max-width: 640px) {
	.sa-strip__in { grid-template-columns: 1fr 1fr; }
	.sa-strip__cell { border-bottom: 1px solid var(--sa-border); }
	.sa-strip__cell:nth-child(2n) { border-right: none; }
	.sa-strip__cell--lead {
		grid-column: 1 / -1;
		border-right: none;
	}
	.sa-strip__cell:last-child,
	.sa-strip__cell:nth-last-child(2):not(.sa-strip__cell--lead) { border-bottom: none; }
}

/* ------------------------------------------------------------------ */
/* Feature banner (Task 5) — `[shining_banner]`. Two interchangeable    */
/* styles: `.sa-banner--banner` (cinematic wide image, uncropped via a  */
/* blurred cover-fill layer behind a sharp object-fit:contain image,    */
/* caption overlay with expand/collapse) and `.sa-banner--duo` (two     */
/* framed image cards). Caption clamp/expand hooks into the EXISTING    */
/* `[data-sa-caption-toggle]` handler in vote-frame.js (Task 4) which    */
/* toggles `.sa-banner.is-open`. Ported + rescoped from the mockup's     */
/* `.fi-a*` (-> banner) / `.fi-b*` (-> duo) blocks into `.sa-banner__*`  */
/* BEM-ish parts, re-pointed from literal hex to the theme's `--sa-*`   */
/* tokens so it tracks the active palette.                              */
/* ------------------------------------------------------------------ */
.sa-banner {
	max-width: 1080px;
	margin: 26px auto;
	padding: 0 16px;
}

/* -- banner (default): one cinematic wide image ----------------------- */
.sa-banner--banner {
	position: relative;
	border-radius: 18px;
	overflow: hidden;
	border: 1px solid var(--sa-border);
	min-height: 240px;
	display: flex;
	align-items: flex-end;
}
.sa-banner__bg {
	position: absolute;
	inset: 0;
	background-size: cover;
	background-position: center;
	filter: blur(26px) saturate(1.2);
	transform: scale(1.1);
}
.sa-banner__img {
	position: relative;
	width: 100%;
	max-height: 420px;
	object-fit: contain;
	display: block;
}
.sa-banner__cap-wrap {
	position: absolute;
	left: 22px;
	right: 22px;
	bottom: 18px;
	z-index: 2;
}
.sa-banner__cap-wrap::before {
	content: "";
	position: absolute;
	inset: -40px -22px -18px;
	background: linear-gradient(180deg, transparent, rgba(6, 15, 12, .85));
	z-index: -1;
}
.sa-banner__ec {
	font-size: 11px;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--sa-violet);
	font-weight: 600;
}
.sa-banner__title {
	font-weight: 800;
	font-size: 22px;
	margin: 3px 0;
}
.sa-banner__cap {
	color: var(--sa-text);
	opacity: .9;
	font-size: 13.5px;
	margin: 0;
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: var(--sa-cap-lines, 2);
	overflow: hidden;
}
.sa-banner.is-open .sa-banner__cap {
	-webkit-line-clamp: unset;
}
.sa-banner__more {
	margin-top: 6px;
	background: none;
	border: none;
	color: var(--sa-violet-light);
	font-weight: 600;
	cursor: pointer;
	padding: 0;
	font-size: 12.5px;
}

/* -- duo: two framed image cards --------------------------------------- */
.sa-banner--duo {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 14px;
}
.sa-banner__card {
	border-radius: 16px;
	overflow: hidden;
	border: 1px solid var(--sa-border);
	background: var(--sa-surface-2);
}
.sa-banner__im {
	height: 170px;
	background-size: cover;
	background-position: center;
}
.sa-banner__cc {
	padding: 13px 16px;
}

@media (max-width: 600px) {
	.sa-banner--duo {
		grid-template-columns: 1fr;
	}
}

/* -- slideshow: JS carousel, degrades to first slide when JS is off ---- */
.sa-banner--slideshow { position: relative; border-radius: 18px; overflow: hidden; border: 1px solid var(--sa-border); background: var(--sa-surface-2); }
/* Two inherited-style leaks had to be closed here, both measured live:
     1. `.sa-banner` above sets `padding: 0 16px` for the cinematic caption. On
        the slideshow that shrank the slide 32px narrower than its own frame.
     2. `.single .entry-content figure { margin: 2rem 0 }` (0,3,1) outranks any
        plain `.sa-slides__slide` rule, so each slide was pushed 33px DOWN
        inside a fixed-height frame with overflow:hidden — which is what
        clipped the bottom of the artwork.
   !important because both live in .entry-content and LiteSpeed combines CSS,
   so source order cannot be relied on. Same pattern as `.sa-nom__item`. */
.sa-banner--slideshow { padding: 0 !important; }
.sa-banner--slideshow .sa-slides__slide { margin: 0 !important; padding: 0 !important; }
.sa-banner--slideshow .sa-slides__slide img { display: block; width: 100%; height: auto; max-height: 460px; object-fit: contain; }

/* Blurred fill behind each slide. The poster is shown WHOLE (`contain`), and
   the leftover space is filled with an out-of-focus copy of the same image
   rather than a flat panel — so a 16:9 frame can hold artwork of any shape
   without ever cropping it, and without the dead letterbox bars that make a
   `contain` fit look broken. Costs no extra request: it is the same file the
   slide already loaded. */
.sa-slides__bg {
	position: absolute;
	inset: 0;
	z-index: 0;
	background-image: var(--sa-slide-bg);
	background-size: cover;
	background-position: center;
	filter: blur(26px) saturate(1.25);
	transform: scale(1.18);
	opacity: .5;
	pointer-events: none;
}
.sa-banner--slideshow .sa-lbtrig,
.sa-banner--slideshow .sa-slides__slide img { position: relative; z-index: 1; }
/* With a ratio set (the default, 16/9) the frame is fixed and the artwork
   crops to fill it. That keeps a mixed-size set from resizing the banner as
   each slide fades in, and reserves the box before the image lands so there is
   no layout shift. The un-cropped original is one tap away in the lightbox, so
   nothing is actually lost by cropping here. `natural` opts back out. */
.sa-banner--slideshow.has-ratio { aspect-ratio: var(--sa-slide-ratio, 16 / 9); }
.sa-banner--slideshow.has-ratio .sa-slides__slide,
.sa-banner--slideshow.has-ratio .sa-lbtrig--fill { height: 100%; }
/* `contain`, not `cover`: the whole poster stays visible inside the fixed
   frame and the blurred backdrop above fills the rest. The frame still
   reserves its box before the image lands, so there is no layout shift. */
.sa-banner--slideshow.has-ratio .sa-slides__slide img { height: 100%; max-height: none; object-fit: contain; }
/* JS-off fallback: show only the first slide and hide the (inert) controls,
   so a JS-disabled visitor sees one clean image instead of a stacked list.
   Gated on the absence of `sa-js-slides` (added by the carousel JS) to avoid a
   specificity fight with the active-slide rules below. */
html:not(.sa-js-slides) .sa-banner--slideshow .sa-slides__slide:not(:first-child),
html:not(.sa-js-slides) .sa-banner--slideshow .sa-slides__dots,
html:not(.sa-js-slides) .sa-banner--slideshow .sa-slides__arrow { display: none; }
/* When JS is on, stack slides and cross-fade; JS-off shows only the first. */
html.sa-js-slides .sa-banner--slideshow .sa-slides__slide { position: absolute; inset: 0; opacity: 0; transition: opacity .5s ease; pointer-events: none; }
html.sa-js-slides .sa-banner--slideshow .sa-slides__slide.is-active { position: relative; opacity: 1; pointer-events: auto; }
html.sa-js-slides .sa-banner--slideshow .sa-slides__slide img { height: 100%; }
.sa-slides__dots { position: absolute; left: 0; right: 0; bottom: 12px; display: flex; gap: 7px; justify-content: center; z-index: 3; }
.sa-slides__dot { width: 8px; height: 8px; border-radius: 50%; border: none; background: rgba(255,255,255,.4); cursor: pointer; padding: 0; }
.sa-slides__dot.is-active { background: var(--sa-gradient); width: 20px; border-radius: 999px; }
.sa-slides__arrow { position: absolute; top: 50%; transform: translateY(-50%); z-index: 3; width: 38px; height: 38px; border-radius: 50%; border: 1px solid var(--sa-border-strong); background: rgba(8,17,13,.55); color: var(--sa-text); font-size: 20px; cursor: pointer; backdrop-filter: blur(6px); }
.sa-slides__arrow--prev { left: 12px; }
.sa-slides__arrow--next { right: 12px; }

/* -- when the controls are allowed to show ------------------------------- */
/* The rule is the POINTER, not the viewport width: "show it when I hover with
   a mouse" is a statement about the input device, and a narrowed desktop window
   still has a mouse while a 1024px tablet still has none. `hover: none` is also
   what already gates the zoom hint below, so both halves of the overlay answer
   to one question.

   Nothing is lost on touch: the carousel advances itself every 5s and swipe is
   bound in vote-frame.js, so hiding the arrows removes the chrome, not the
   navigation. Tapping the slide still opens the lightbox — the whole slide is
   the trigger — so only the hint disappears, never the ability. */
@media (hover: none) {
	.sa-banner--slideshow .sa-slides__arrow,
	.sa-banner--slideshow .sa-slides__dots { display: none !important; }
}

@media (hover: hover) {
	.sa-banner--slideshow .sa-slides__arrow,
	.sa-banner--slideshow .sa-slides__dots {
		opacity: 0;
		/* Invisible controls must not eat clicks: without this the arrow would
		   still swallow a click meant for the artwork underneath it. Focusability
		   is unaffected — pointer-events does not reach the keyboard — which is
		   what makes the :focus-within reveal below work. */
		pointer-events: none;
		transition: opacity .18s ease;
	}
	.sa-banner--slideshow:hover .sa-slides__arrow,
	.sa-banner--slideshow:hover .sa-slides__dots,
	/* A keyboard user has no pointer to discover these with. Tabbing into the
	   carousel reveals them, so the controls are reachable rather than merely
	   present. Do NOT swap the opacity above for visibility/display — either one
	   would make the buttons unfocusable and this selector unreachable. */
	.sa-banner--slideshow:focus-within .sa-slides__arrow,
	.sa-banner--slideshow:focus-within .sa-slides__dots {
		opacity: 1;
		pointer-events: auto;
	}
}

/* ==========================================================================
   Lightbox trigger + overlay
   ========================================================================== */

/* -- trigger -------------------------------------------------------------- */
/* The button IS the image box in slideshow/gallery cells, so it has to reset
   every default a <button> brings (padding, border, background, font) or it
   would draw a chrome frame around the artwork. */
.sa-lbtrig {
	display: block;
	position: relative;
	width: 100%;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	font: inherit;
	color: inherit;
	cursor: zoom-in;
	-webkit-appearance: none;
	appearance: none;
}
.sa-lbtrig img { display: block; width: 100%; }

/* The ⤢ affordance. Hidden until hover on pointer devices — the artwork is the
   thing being looked at — but always visible on touch, where there is no hover
   to discover it with. */
.sa-lbtrig__ic {
	position: absolute;
	right: 10px;
	bottom: 10px;
	z-index: 2;
	width: 34px;
	height: 34px;
	border-radius: 50%;
	border: 1px solid var(--sa-border-strong);
	background: rgba(10, 8, 14, .58);
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
	opacity: 0;
	transition: opacity .18s ease, transform .18s ease;
	pointer-events: none;
}
.sa-lbtrig__ic::before,
.sa-lbtrig__ic::after {
	content: "";
	position: absolute;
	width: 9px;
	height: 9px;
	border: 2px solid var(--sa-text);
}
.sa-lbtrig__ic::before { top: 9px;  left: 9px;  border-right: 0; border-bottom: 0; }
.sa-lbtrig__ic::after  { right: 9px; bottom: 9px; border-left: 0;  border-top: 0; }

.sa-lbtrig:hover .sa-lbtrig__ic,
.sa-lbtrig:focus-visible .sa-lbtrig__ic { opacity: 1; }
/* In a slideshow the frame is taller than the `contain`ed image, so hovering
   the letterboxed area never touched the trigger and the hint stayed hidden
   while the arrows around it appeared. Let the frame reveal it too, so the
   whole overlay arrives and leaves as one. */
.sa-banner--slideshow:hover .sa-slides__slide.is-active .sa-lbtrig__ic,
.sa-banner--slideshow:focus-within .sa-slides__slide.is-active .sa-lbtrig__ic { opacity: 1; }
/* On touch the hint used to sit there permanently, on the theory that there is
   no hover to discover it with. In practice it was one more thing parked on top
   of the artwork on the smallest screen. Tapping the image still opens the
   lightbox; the affordance is what goes, not the feature. */
@media (hover: none) {
	.sa-lbtrig__ic { display: none !important; }
}
.sa-lbtrig:focus-visible {
	outline: 2px solid var(--sa-accent);
	outline-offset: 3px;
}

/* Corner variant: used by the cinematic banner, where the image is absolutely
   positioned and must NOT be wrapped. Sits over the artwork as its own control. */
/* Scoped for the same reason as `.sa-lb .sa-lb__btn` above: this trigger is a
   focusable button whose position is load-bearing. */
.sa-banner .sa-lbtrig--corner {
	position: absolute;
	right: 12px;
	top: 12px;
	width: 34px;
	height: 34px;
	z-index: 3;
}
/* Hidden until the pointer is over the banner — the artwork is the thing being
   looked at. Revealed by hovering the FRAME, not just the 34px button: hunting
   for a control you cannot see is not a discovery mechanism. */
.sa-banner .sa-lbtrig--corner .sa-lbtrig__ic { inset: 0; right: auto; bottom: auto; opacity: 0; }
.sa-banner:hover .sa-lbtrig--corner .sa-lbtrig__ic,
.sa-banner:focus-within .sa-lbtrig--corner .sa-lbtrig__ic { opacity: .85; }
.sa-banner .sa-lbtrig--corner:hover .sa-lbtrig__ic,
.sa-banner .sa-lbtrig--corner:focus-visible .sa-lbtrig__ic { opacity: 1; transform: scale(1.06); }

/* -- auto-gallery wrapper ------------------------------------------------- */
.sa-autogal { margin: 26px 0; }

/* -- overlay -------------------------------------------------------------- */
html.sa-lb-lock,
html.sa-lb-lock body { overflow: hidden; }
/* Position:fixed + the JS-set top offset is what stops iOS Safari scrolling
   the page behind the overlay; overflow:hidden alone does not hold there. */
html.sa-lb-lock body { position: fixed; width: 100%; }

.sa-lb {
	position: fixed;
	inset: 0;
	z-index: 100000;
	display: flex;
	align-items: center;
	justify-content: center;
	opacity: 0;
	transition: opacity .18s ease;
	overscroll-behavior: contain;
}
.sa-lb.is-open { opacity: 1; }
.sa-lb[hidden] { display: none; }

.sa-lb__backdrop {
	position: absolute;
	inset: 0;
	background: rgba(6, 4, 10, .92);
	backdrop-filter: blur(10px);
	-webkit-backdrop-filter: blur(10px);
}

.sa-lb__stage {
	position: relative;
	z-index: 1;
	max-width: min(94vw, 1400px);
	max-height: 88vh;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 12px;
	transform: scale(.985);
	transition: transform .2s ease;
}
.sa-lb.is-open .sa-lb__stage { transform: scale(1); }

.sa-lb__img {
	display: block;
	max-width: 100%;
	max-height: 80vh;
	width: auto;
	height: auto;
	border-radius: 10px;
	object-fit: contain;
}

.sa-lb__cap {
	margin: 0;
	max-width: 62ch;
	text-align: center;
	font-size: 14px;
	line-height: 1.5;
	color: var(--sa-text-dim, rgba(255, 255, 255, .72));
}
.sa-lb__cap[hidden] { display: none; }

/* Scoped under `.sa-lb` (0,2,0) on purpose. skin.css:336 sets
   `a:focus-visible, button:focus-visible { position: relative }` to stop the
   focus ring being clipped by an overflow-hidden ancestor — and at (0,1,1)
   that outranks a bare `.sa-lb__btn`. Since we move focus to the close button
   the moment the lightbox opens, the unscoped version made that button drop
   out of its corner and land in the middle of the artwork. */
.sa-lb .sa-lb__btn {
	position: absolute;
	z-index: 2;
	display: grid;
	place-items: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border-radius: 50%;
	border: 1px solid var(--sa-border-strong);
	background: rgba(18, 14, 24, .72);
	color: var(--sa-text);
	font-size: 22px;
	line-height: 1;
	cursor: pointer;
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
	transition: background .15s ease, transform .15s ease;
}
.sa-lb .sa-lb__btn:hover { background: rgba(38, 30, 50, .9); transform: scale(1.05); }
.sa-lb .sa-lb__btn:focus-visible { outline: 2px solid var(--sa-accent); outline-offset: 2px; }
.sa-lb .sa-lb__btn[hidden] { display: none; }

.sa-lb .sa-lb__close { top: 16px; right: 16px; font-size: 18px; }
.sa-lb .sa-lb__nav { top: 50%; transform: translateY(-50%); }
.sa-lb .sa-lb__nav:hover { transform: translateY(-50%) scale(1.05); }
.sa-lb .sa-lb__nav--prev { left: 16px; }
.sa-lb .sa-lb__nav--next { right: 16px; }

.sa-lb__count {
	position: absolute;
	left: 50%;
	bottom: 18px;
	transform: translateX(-50%);
	z-index: 2;
	padding: 4px 12px;
	border-radius: 999px;
	border: 1px solid var(--sa-border);
	background: rgba(18, 14, 24, .72);
	font-size: 12px;
	font-variant-numeric: tabular-nums;
	letter-spacing: .04em;
	color: var(--sa-text-dim, rgba(255, 255, 255, .78));
}
.sa-lb__count[hidden] { display: none; }

/* On a phone the side arrows would sit on top of the artwork, so they move to
   the bottom edge where the thumb already is. */
@media (max-width: 600px) {
	.sa-lb__stage { max-width: 96vw; }
	.sa-lb .sa-lb__nav { top: auto; bottom: 16px; transform: none; }
	.sa-lb .sa-lb__nav:hover { transform: scale(1.05); }
	.sa-lb .sa-lb__nav--prev { left: 22px; }
	.sa-lb .sa-lb__nav--next { right: 22px; }
	.sa-lb__count { bottom: 26px; }
	.sa-lb__img { max-height: 70vh; }
}

@media (prefers-reduced-motion: reduce) {
	.sa-lb,
	.sa-lb__stage,
	.sa-lb__btn,
	.sa-lbtrig__ic,
	.sa-banner--slideshow .sa-slides__arrow,
	.sa-banner--slideshow .sa-slides__dots { transition: none; }
	.sa-lb__stage { transform: none; }
	.sa-banner .sa-lbtrig--corner:hover .sa-lbtrig__ic { transform: none; }
}

/* ==========================================================================
   Standings strip — "who's leading", per-poll. The only JS it uses is the
   winner-mode flip in vote-frame.js (initStand); everything else is CSS.
   ========================================================================== */

.sa-stand {
	position: relative;
	max-width: 720px;              /* narrower than the nominee grid: a ranking
	                                  reads as a column, not a full-bleed slab */
	margin: 32px auto;
	padding: 22px 20px 18px;
	border: 1px solid var(--sa-border);
	border-radius: 20px;
	background:
		radial-gradient(90% 75% at 50% -25%, color-mix(in srgb, var(--sa-heart) 8%, transparent), transparent 62%),
		radial-gradient(120% 90% at 50% -20%, rgba(255, 255, 255, .05), transparent 60%),
		var(--sa-surface-2);
	overflow: hidden;
}
/* A single hairline of the brand gradient across the top edge, fading out at
   the corners — the whole "premium" budget of this component is spent on the
   header, so the rows below need no borders or glows to look considered. */
.sa-stand::before {
	content: "";
	position: absolute;
	inset: 0 0 auto;
	height: 2px;
	background: var(--sa-gradient);
	opacity: .9;
	-webkit-mask: linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent);
	mask: linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent);
}

/* -- centred header ------------------------------------------------------- */
.sa-stand__head {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 9px;
	margin-bottom: 16px;
}
/* The eyebrow is a SPLIT pill — a LIVE tag in the palette colour, then the
   running total — with a gradient hairline border drawn by the same
   padding-box/border-box two-layer trick as .sa-pinfo__card. */
.sa-stand__live {
	display: inline-flex;
	align-items: stretch;
	overflow: hidden;
	border: 1px solid transparent;
	border-radius: 999px;
	background:
		linear-gradient(var(--sa-surface), var(--sa-surface)) padding-box,
		linear-gradient(90deg, color-mix(in srgb, var(--sa-heart) 55%, transparent), var(--sa-border) 45%, var(--sa-border) 72%, color-mix(in srgb, var(--sa-heart) 35%, transparent)) border-box;
	font-size: 10.5px;
	line-height: 1;
}
.sa-stand__livetag {
	--sa-violet: var(--sa-heart);   /* recolours the shared pulsing dot + its ring */
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 6px 10px 6px 12px;
	font-weight: 800;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--sa-heart);
	background: color-mix(in srgb, var(--sa-heart) 13%, transparent);
	border-right: 1px solid var(--sa-border);
}
.sa-stand__livetag .sa-pinfo__dot { width: 6px; height: 6px; }
.sa-stand__count {
	display: inline-flex;
	align-items: center;
	padding: 6px 13px 6px 11px;
	font-weight: 600;
	letter-spacing: .07em;
	text-transform: uppercase;
	color: var(--sa-text-dim);
	font-variant-numeric: tabular-nums;
}
/* Title, v2: smaller on purpose — the five rows are the show, the heading only
   introduces them — set between two hairlines that fade outward and a pair of
   softly twinkling hearts. */
.sa-stand__title {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	width: 100%;
	margin: 0;
	font-family: var(--sa-font-display);
	font-weight: 800;
	font-size: clamp(17px, 2.6vw, 22px);
	line-height: 1.15;
	letter-spacing: -.01em;
}
.sa-stand__title::before,
.sa-stand__title::after {
	content: "";
	flex: 0 1 56px;
	height: 1px;
	background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--sa-heart) 45%, var(--sa-border)));
}
.sa-stand__title::after {
	background: linear-gradient(90deg, color-mix(in srgb, var(--sa-heart) 45%, var(--sa-border)), transparent);
}
.sa-stand__tt { min-width: 0; text-wrap: balance; }
.sa-stand__hm {
	width: 11px;
	height: 11px;
	flex: none;
	color: var(--sa-heart);
	animation: sa-stand-tw 2.8s ease-in-out infinite;
}
.sa-stand__title .sa-stand__hm:last-of-type { animation-delay: -1.4s; }
@keyframes sa-stand-tw {
	0%, 100% { transform: scale(1); opacity: .5; }
	50% { transform: scale(1.18); opacity: 1; }
}
.sa-stand__sub {
	font-size: 12px;
	line-height: 1.5;
	color: var(--sa-text-dim);
	max-width: 46ch;
}

/* -- rows ----------------------------------------------------------------- */
.sa-stand__list { display: flex; flex-direction: column; gap: 4px; }

/* A 4-column grid so rank digits, bars and numbers stay aligned down the
   column no matter how long a name runs. */
.sa-stand__row {
	display: grid;
	grid-template-columns: 1.6rem 42px minmax(0, 1fr) 4.2rem;
	align-items: center;
	gap: 12px;
	padding: 8px 10px;
	border-radius: 14px;
	border: 1px solid transparent;
	text-decoration: none;
	color: inherit;
	/* Leak defense: a full-width <a> inside .entry-content inherits Jannah's
	   gradient link-underline, which stretches into a stray line across the
	   row. Same fix as .sa-nom__item — see the note above it. */
	background-image: none !important;
	text-decoration: none !important;
	transition: background-color .16s ease, border-color .16s ease;
}
a.sa-stand__row:hover {
	background-color: var(--sa-surface);
	border-color: var(--sa-border);
}

/* The leader gets a tinted plate. Everyone below is quiet, so first place
   reads instantly without a medal or a trophy.
   background-COLOR, not a gradient: the leak defense above forces
   `background-image: none !important` to kill Jannah's inherited link
   underline, and that !important also swallowed the tint when it was written
   as a linear-gradient. A flat tint is not affected. */
.sa-stand__item:first-child .sa-stand__row {
	background-color: color-mix(in srgb, var(--sa-heart) 10%, transparent);
	border-color: color-mix(in srgb, var(--sa-heart) 28%, transparent);
}
.sa-stand__item:first-child a.sa-stand__row:hover {
	background-color: color-mix(in srgb, var(--sa-heart) 16%, transparent);
	border-color: color-mix(in srgb, var(--sa-heart) 44%, transparent);
}

.sa-stand__rank {
	font-family: var(--sa-font-display);
	font-weight: 800;
	font-size: 15px;
	text-align: center;
	color: var(--sa-text-dim);
	font-variant-numeric: tabular-nums;
}
.sa-stand__item:first-child .sa-stand__rank { color: var(--sa-heart); font-size: 19px; }
.sa-stand__item:nth-child(2) .sa-stand__rank,
.sa-stand__item:nth-child(3) .sa-stand__rank { color: var(--sa-text); }

/* The avatar ring is drawn on a wrapper, not the avatar itself: the avatar
   clips its own overflow to stay circular, so a ring on it would be cut off. */
.sa-stand__ava {
	display: grid;
	place-items: center;
	width: 42px;
	height: 42px;
	border-radius: 50%;
	padding: 2px;
	background: var(--sa-border);
}
.sa-stand__item:first-child .sa-stand__ava { background: var(--sa-gradient); }
.sa-stand__av { width: 100%; height: 100%; font-size: 14px; }

.sa-stand__meta { display: flex; flex-direction: column; gap: 6px; min-width: 0; }

/* Name + group on one line, bar underneath. The tight line-height is
   deliberate: .entry-content sets 1.62 for prose, which on a 13px label adds
   ~9px of dead space per row — 45px across the strip for nothing. */
.sa-stand__top {
	display: flex;
	align-items: baseline;
	gap: 7px;
	min-width: 0;
	line-height: 1.2;
}
.sa-stand__name {
	font-weight: 700;
	font-size: 14.5px;
	line-height: 1.2;
	color: var(--sa-text);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	flex: 0 1 auto;   /* the long part shrinks first */
}
.sa-stand__grp {
	font-size: 10px;
	line-height: 1.2;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--sa-text-dim);
	white-space: nowrap;
	/* The group tag absorbs essentially the whole deficit before the name gives
	   up a single pixel. Equal shrink factors were not enough: on a 360px phone
	   "Hyunjin / STRAY KIDS" still truncated to "Hyun… / STRAY KI…", and the
	   idol's name is the one word in this row that must never be cut. */
	flex: 0 1 auto;
	flex-shrink: 999;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	padding: 2px 7px;
	border-radius: 999px;
	background: var(--sa-surface);
}
.sa-stand__item:first-child .sa-stand__grp { color: var(--sa-text); }

.sa-stand__bar {
	display: block;
	height: 6px;
	border-radius: 999px;
	background: var(--sa-border);
	overflow: hidden;
}
.sa-stand__fill {
	display: block;
	height: 100%;
	border-radius: inherit;
	background: var(--sa-gradient);
}
/* Only the leader's bar glows; on every bar it would just be noise. */
.sa-stand__item:first-child .sa-stand__fill {
	box-shadow: 0 0 12px color-mix(in srgb, var(--sa-heart) 55%, transparent);
}

.sa-stand__num {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 1px;
	line-height: 1.15;
}
.sa-stand__pct {
	font-family: var(--sa-font-display);
	font-size: 15px;
	font-weight: 800;
	color: var(--sa-text);
	font-variant-numeric: tabular-nums;
}
.sa-stand__item:first-child .sa-stand__pct { color: var(--sa-heart); font-size: 17px; }
.sa-stand__votes {
	font-size: 10.5px;
	color: var(--sa-text-dim);
	font-variant-numeric: tabular-nums;
}

/* -- winner mode (poll closed) ---------------------------------------------
   Flipped on by the server for fresh renders and by vote-frame.js for cached
   ones. Everything below is a reveal of markup that is ALWAYS present — the
   badge ships in row 1 on every render precisely so the client-side flip has
   something to show without building DOM. */

/* The pulse stops: nothing is live any more. */
.sa-stand--closed .sa-pinfo__dot { animation: none; box-shadow: none; }

/* WINNER badge — brand gradient, not gold: fan-choice energy, not a gala. */
.sa-stand__wbadge {
	display: none;
	align-items: center;
	flex: none;
	padding: 2px 8px;
	border-radius: 999px;
	background: var(--sa-gradient);
	color: var(--sa-on-accent, #fff);
	font-size: 9px;
	font-weight: 800;
	line-height: 1.2;
	letter-spacing: .12em;
	text-transform: uppercase;
}
.sa-stand--closed .sa-stand__item:first-child .sa-stand__wbadge { display: inline-flex; }

/* The champion's plate steps up one notch from the live leader tint. */
.sa-stand--closed .sa-stand__item:first-child .sa-stand__row {
	position: relative;
	overflow: hidden;
	background-color: color-mix(in srgb, var(--sa-heart) 14%, transparent);
	border-color: color-mix(in srgb, var(--sa-heart) 55%, transparent);
}
/* Celebration shine across the winner row — same finite spec as the info
   panel's sweep (5 passes, then parked), armed by .is-lit only once seen. */
.sa-stand--closed .sa-stand__item:first-child .sa-stand__row::after {
	content: "";
	position: absolute;
	inset: -2px;
	pointer-events: none;
	background: linear-gradient(115deg, transparent 42%, rgba(255, 255, 255, .10) 50%, transparent 58%);
	transform: translateX(-101%);
}
.sa-stand--closed.is-lit .sa-stand__item:first-child .sa-stand__row::after {
	animation: sa-pinfo-sweep 3.4s ease-in-out .4s 5;
}

@media (max-width: 480px) {
	.sa-stand { padding: 18px 12px 14px; border-radius: 16px; margin: 26px auto; }
	.sa-stand__title { gap: 8px; }
	.sa-stand__title::before,
	.sa-stand__title::after { flex-basis: 22px; }
	.sa-stand__sub { font-size: 11.5px; }
	.sa-stand__row { grid-template-columns: 1.1rem 34px minmax(0, 1fr) 3rem; gap: 8px; padding: 7px 6px; }
	.sa-stand__ava { width: 34px; height: 34px; }
	.sa-stand__name { font-size: 13px; }
	.sa-stand__grp { font-size: 9px; padding: 1px 5px; }
	.sa-stand__pct { font-size: 13.5px; }
	.sa-stand__item:first-child .sa-stand__pct { font-size: 15px; }
	.sa-stand__votes { font-size: 9.5px; }
}

@media (prefers-reduced-motion: reduce) {
	.sa-stand__row { transition: none; }
	.sa-stand__hm { animation: none; opacity: .85; }
	.sa-stand--closed.is-lit .sa-stand__item:first-child .sa-stand__row::after { animation: none; }
}

/* ==========================================================================
   Follow CTA — inline-SVG social block, no images, no JS
   ========================================================================== */

/* The gradient-text utility `.sa-grad` lives in skin.css. Every heading in THIS
   file leans on it, which was fine on the front end and broke the moment the
   block was previewed in the editor with only tokens.css + this file loaded:
   `.sa-grad` was undefined, so the titles fell back to black on a dark card.
   A stylesheet should stand up on its own — these three carry the treatment
   themselves. Identical declarations, so skin.css winning changes nothing. */
.sa-follow__title,
.sa-stand__tt,
.sa-nom__heading {
	background: var(--sa-gradient);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
}

.sa-follow {
	position: relative;
	/* Narrower than it was (900px). The tiles below are compact squares now, and
	   six of them centred in a 900px card left the block reading as a wide empty
	   panel with something small floating in it. */
	max-width: 720px;
	margin: 34px auto;
	padding: 22px 18px 20px;
	border: 1px solid var(--sa-border);
	border-radius: 20px;
	background:
		radial-gradient(120% 100% at 50% -30%, rgba(255, 255, 255, .05), transparent 62%),
		var(--sa-surface-2);
	overflow: hidden;
}
/* Top hairline: full-bleed gradient that fades out at both ends rather than
   stopping dead against the rounded corners. */
.sa-follow::before {
	content: "";
	position: absolute;
	inset: 0 0 auto;
	height: 2px;
	background: linear-gradient(90deg, transparent, var(--sa-violet) 18%, var(--sa-violet-light) 50%, var(--sa-violet) 82%, transparent);
	opacity: .9;
}

.sa-follow__head {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 5px;
	margin-bottom: 16px;
}
/* Leak defense: inside `.entry-content` this H2 picks up the article accent bar
   (`.single .entry-content h2::before`) plus its left padding — a 5px gradient
   tick pinned to the left of a CENTRED heading, which reads as a rendering bug.
   Same fix `.sa-related` already carries; see the note above it. */
.sa-follow__title::before { content: none !important; display: none !important; }
/* !important on the type, not just the box: inside `.entry-content` the article
   scale wins on specificity — `.single .entry-content h2` (0,3,1) rendered this
   heading at 32px and `.entry-content p` pushed the sub-line to 17px, so every
   size set here was decorative. LiteSpeed combines the stylesheets, so source
   order cannot settle it either. Same class of leak as `.sa-nom__item`. */
.sa-follow__title {
	font-family: var(--sa-font-display);
	font-weight: 700 !important;
	/* Compact on purpose: this is a footer-of-the-article CTA, not the page's
	   headline, and at the article's own H2 size it out-shouted the vote title. */
	font-size: clamp(16px, 2.1vw, 20px) !important;
	line-height: 1.2 !important;
	letter-spacing: -.01em;
	margin: 0 !important;
	padding-left: 0 !important;
	text-wrap: balance;
}
.sa-follow__sub {
	margin: 0 !important;
	max-width: 52ch;
	font-size: 12px !important;
	line-height: 1.5 !important;
	color: var(--sa-text-dim);
}

/* Centred flex-wrap rather than a grid. The network count is whatever the site
   configured (2 to 7), so any fixed column count is wrong for someone — and an
   auto-fit grid leaves the last row hanging at the left edge, which reads as a
   layout bug rather than a choice. Wrapping centred means an orphan row lands
   under the middle and looks deliberate at every count.
   `flex-basis` is a floor, never a bare 1fr: a track that refuses to shrink
   below its content clips on a 360px phone. */
.sa-follow__list {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 9px;
}
/* `0 1` — shrink, never grow. With `1 1` a two-chip last row split the whole
   width between them and rendered 230px wide next to 172px chips above: same
   component, two sizes, one row apart. Not growing keeps every chip identical
   and lets `justify-content: center` place the leftovers. */
/* A near-square tile, not a wide row. The old 172px chip laid the icon and the
   name side by side, so six of them tiled into what read as a link list; stacked
   vertically the same content makes a compact card the eye takes in as one unit. */
.sa-follow__cell {
	flex: 0 1 104px;
	min-width: 0;
	max-width: 100%;
}

.sa-follow__item {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 9px;
	height: 100%;
	/* Roughly square (~104 x ~88): a tile, not a button. The 6px side padding is
	   what buys the handle enough room to print in full instead of ellipsising —
	   "@shiningawardsofc" is the longest one a site is likely to have. */
	padding: 16px 6px 14px;
	border: 1px solid var(--sa-border);
	border-radius: 16px;
	/* `--sa-surface` is not a token (the tiles used to compute to transparent and
	   sat flat on the panel). Tint the panel surface instead, so the tile reads
	   as raised at every palette. */
	background-color: color-mix(in srgb, var(--sa-surface-1) 72%, transparent);
	color: inherit;
	/* Leak defense: inside .entry-content these anchors inherit Jannah's
	   gradient link-underline, which draws a stray bar across each tile.
	   Same fix as .sa-nom__item — see the note above it. */
	background-image: none !important;
	text-decoration: none !important;
	overflow: hidden;
	transition: border-color .16s ease, transform .16s ease, background-color .16s ease;
}
/* A hairline of light along the top edge — the one detail that separates a tile
   from a rectangle. Sits above the fill, under the content. */
.sa-follow__item::after {
	content: "";
	position: absolute;
	inset: 0 22% auto;
	height: 1px;
	background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .16), transparent);
}
.sa-follow__item:hover {
	/* The brand colour appears on hover only. Six saturated logos side by side
	   would fight the palette and each other; on hover it reads as feedback. */
	border-color: color-mix(in srgb, var(--sa-fbrand) 55%, transparent);
	background-color: color-mix(in srgb, var(--sa-fbrand) 11%, var(--sa-surface-1));
	transform: translateY(-3px);
}
.sa-follow__item:focus-visible {
	outline: 2px solid var(--sa-accent);
	outline-offset: 2px;
}

.sa-follow__ic {
	position: relative;
	display: grid;
	place-items: center;
	width: 40px;
	height: 40px;
	flex: none;
	border-radius: 13px;
	background: color-mix(in srgb, var(--sa-fbrand) 15%, transparent);
	box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--sa-fbrand) 26%, transparent);
	color: var(--sa-fbrand);
	transition: background-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.sa-follow__item:hover .sa-follow__ic {
	background: color-mix(in srgb, var(--sa-fbrand) 26%, transparent);
	box-shadow:
		inset 0 0 0 1px color-mix(in srgb, var(--sa-fbrand) 45%, transparent),
		0 8px 20px -10px var(--sa-fbrand);
	transform: scale(1.04);
}
.sa-follow__svg { width: 19px; height: 19px; display: block; }

.sa-follow__meta { display: flex; flex-direction: column; gap: 1px; min-width: 0; width: 100%; }
.sa-follow__net {
	font-weight: 700;
	font-size: 12.5px;
	line-height: 1.25;
	color: var(--sa-text);
}
.sa-follow__handle {
	font-size: 9.5px;
	letter-spacing: -.01em;
	line-height: 1.3;
	color: var(--sa-text-dim);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

@media (max-width: 480px) {
	.sa-follow { padding: 18px 12px 14px; border-radius: 16px; margin: 26px auto; }
	.sa-follow__head { margin-bottom: 13px; }
	.sa-follow__list { gap: 8px; }
	/* Exactly three across, whatever the well turns out to be. A fixed px basis
	   was off by a few pixels once `.entry-content` padding was in play and the
	   row silently fell back to two — the percentage cannot drift. */
	.sa-follow__cell { flex-basis: calc((100% - 16px) / 3); }
	.sa-follow__item { padding: 12px 6px 10px; gap: 7px; border-radius: 14px; }
	.sa-follow__ic { width: 34px; height: 34px; border-radius: 11px; }
	.sa-follow__svg { width: 16px; height: 16px; }
	.sa-follow__net { font-size: 11.5px; }
	.sa-follow__handle { font-size: 9px; }
}

@media (prefers-reduced-motion: reduce) {
	.sa-follow__item { transition: none; }
	.sa-follow__item:hover { transform: none; }
}

/* ===========================================================================
   Vote Pulse strip — poll vitals under the title (the vacated metabar slot)
   =========================================================================== */

.sa-pulse {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 14px 0 2px;
}

.sa-pulse__chip {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 5px 12px;
	border-radius: var(--sa-radius-pill);
	border: 1px solid var(--sa-border);
	background: color-mix(in srgb, var(--sa-surface-1) 55%, transparent);
	font-size: 12.5px;
	line-height: 1.4;
	letter-spacing: .01em;
	color: var(--sa-text-muted);
	white-space: nowrap;
}
.sa-pulse__chip b {
	font-weight: 700;
	color: var(--sa-text);
	font-variant-numeric: tabular-nums;
}
/* The chip's own display would beat the UA's [hidden] rule — restate it, or a
   zero-surge momentum chip renders "+0" instead of disappearing. */
.sa-pulse__chip[hidden] { display: none; }

.sa-pulse__ic { width: 14px; height: 14px; flex: none; display: block; }
.sa-pulse__total .sa-pulse__ic { color: var(--sa-pink); fill: var(--sa-pink); }
.sa-pulse__cd .sa-pulse__ic { color: var(--sa-gold); }
.sa-pulse__mo .sa-pulse__ic { color: var(--sa-gold); }

/* Status pill — the one chip allowed to carry a full accent tint. */
.sa-pulse__status {
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	font-size: 11px;
}
.sa-pulse__status b { font-weight: 700; }
.sa-pulse__dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.sa-pulse__status.is-live {
	border-color: color-mix(in srgb, var(--sa-vote) 45%, transparent);
	background: color-mix(in srgb, var(--sa-vote) 14%, transparent);
}
.sa-pulse__status.is-live b { color: var(--sa-vote-2); }
.sa-pulse__status.is-live .sa-pulse__dot {
	background: var(--sa-vote);
	box-shadow: 0 0 0 0 color-mix(in srgb, var(--sa-vote) 55%, transparent);
	animation: sa-pulse-dot 2.2s ease-out infinite;
}
.sa-pulse__status.is-soon {
	border-color: color-mix(in srgb, var(--sa-gold) 45%, transparent);
	background: color-mix(in srgb, var(--sa-gold) 12%, transparent);
}
.sa-pulse__status.is-soon b { color: var(--sa-gold); }
.sa-pulse__status.is-soon .sa-pulse__dot { background: var(--sa-gold); }
.sa-pulse__status.is-closed { border-color: var(--sa-border-strong); }
.sa-pulse__status.is-closed b { color: var(--sa-text); }
.sa-pulse__status.is-closed .sa-pulse__dot { background: var(--sa-text-dim); }

@keyframes sa-pulse-dot {
	0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--sa-vote) 55%, transparent); }
	70%  { box-shadow: 0 0 0 6px transparent; }
	100% { box-shadow: 0 0 0 0 transparent; }
}

/* Momentum — warm tint; it earns the emphasis by only existing while surging. */
.sa-pulse__mo {
	border-color: color-mix(in srgb, var(--sa-gold) 40%, transparent);
	background: color-mix(in srgb, var(--sa-gold) 10%, transparent);
}
.sa-pulse__mo b { color: var(--sa-gold); }

/* Facepile — the standings' avatar pipeline at chip scale. The ring is the
   page background so the overlap reads as a deliberate stack, not a collision. */
.sa-pulse__faces { padding-left: 6px; }
.sa-pulse__stack { display: inline-flex; align-items: center; }
.sa-pulse__av {
	width: 24px;
	height: 24px;
	font-size: 9px;
	box-shadow: 0 0 0 2px var(--sa-bg);
}
.sa-pulse__stack .sa-pulse__av + .sa-pulse__av { margin-left: -8px; }

/* Voting-window meter (optional) — a full-width hairline under the chips. */
.sa-pulse__meter {
	flex-basis: 100%;
	height: 3px;
	border-radius: 2px;
	background: color-mix(in srgb, var(--sa-text-dim) 22%, transparent);
	overflow: hidden;
}
.sa-pulse__meter i {
	display: block;
	height: 100%;
	border-radius: 2px;
	background: var(--sa-gradient);
}

/* Compact, not cramped, on small screens. */
@media (max-width: 640px) {
	.sa-pulse { gap: 6px; margin-top: 12px; }
	.sa-pulse__chip { font-size: 11.5px; padding: 4px 10px; gap: 5px; }
	.sa-pulse__status { font-size: 10px; }
	.sa-pulse__ic { width: 13px; height: 13px; }
	.sa-pulse__av { width: 21px; height: 21px; font-size: 8px; }
	.sa-pulse__stack .sa-pulse__av + .sa-pulse__av { margin-left: -7px; }
}

@media (prefers-reduced-motion: reduce) {
	.sa-pulse__status.is-live .sa-pulse__dot { animation: none; }
}
