/* ==========================================================================
   Feed — built from the "Feed" screen of design/Epileptic News.dc.html.
   ========================================================================== */

.epi-feed {
	max-width: var(--shell);
	margin: 0 auto;
	padding: 30px var(--gutter) 80px;
}

/* --- row one: market sentiment beside the showcase band -------------------
   The heat panel that used to sit on the right became the rotating band, and
   it keeps the slot. Sentiment gets the wider share because it is a 24-bucket
   histogram and the band is one line of copy. */

/*
 * Also 50/50, so this row and the hero under it break on the same vertical.
 *
 * 🔴 The two seams are not the same kind of thing and that is the whole point:
 * this row is two cards with a 20px gap, so its divider is the CENTRE of that
 * gap; the hero is one card split edge-to-edge, so its divider is a line. Equal
 * columns in both puts the hero's line exactly on the gap's centre. Unequal
 * columns here (it was 1.05fr) left the two verticals ~90px apart — close
 * enough to look like a mistake rather than a decision.
 */
.epi-signals {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	gap: 20px;
	margin-bottom: 26px;
	align-items: stretch;
}

.epi-panel {
	border: 1px solid var(--line);
	border-radius: var(--r-panel);
	background: var(--card-gradient);
	padding: 22px 24px;
	position: relative;
	overflow: hidden;
}

.epi-panel--flat { background: var(--bg-card); }

.epi-panel__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	margin-bottom: 18px;
}

.epi-panel__eyebrow {
	display: flex;
	align-items: center;
	gap: 9px;
}

.epi-panel__count {
	font-family: var(--font-mono);
	font-size: 10px;
	color: var(--fg-faint);
	letter-spacing: 1px;
	white-space: nowrap;
}

/* --- bullish tilt + 24-bucket histogram ------------------------------------ */

.epi-tilt {
	display: flex;
	align-items: flex-end;
	gap: 26px;
}

.epi-tilt__figure {
	font-stretch: var(--stretch-head);
	font-size: 54px;
	font-weight: 800;
	letter-spacing: -2.4px;
	line-height: 0.9;
}

.epi-tilt__pct {
	font-size: 22px;
	color: #3E4553;
	letter-spacing: -1px;
}

.epi-tilt__caption {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: 1.5px;
	color: var(--fg-label);
	margin-top: 8px;
	text-transform: uppercase;
}

.epi-histogram { flex: 1; min-width: 0; }

.epi-histogram__bars {
	display: flex;
	height: 46px;
	gap: 3px;
	align-items: flex-end;
	margin-bottom: 10px;
}

.epi-histogram__bucket {
	flex: 1;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	gap: 2px;
	height: 100%;
	min-width: 0;
}

.epi-histogram__bear {
	background: var(--ui-bear);
	border-radius: 2px;
	opacity: 0.7;
}

.epi-histogram__bull {
	background: var(--ui-bull);
	border-radius: 2px;
	opacity: 0.9;
}

.epi-histogram__axis {
	display: flex;
	justify-content: space-between;
	font-family: var(--font-mono);
	font-size: 9px;
	color: var(--fg-ghost);
	letter-spacing: 1px;
}

/* ==========================================================================
   The showcase band — one full-width strip turning through Cult and token.

   Every slide is stacked in the same grid cell and cross-faded. That is why the
   band needs its own height rather than hugging its content: slides differ in
   length, and a band that resized on every turn would shove the hero down the
   page four times a minute.
   ========================================================================== */

.epi-showcase {
	position: relative;
	border: 1px solid var(--line-strong);
	border-radius: var(--r-panel);
	background:
		radial-gradient(560px 200px at 8% 0%, rgba(47, 125, 255, 0.10), transparent 62%),
		radial-gradient(460px 220px at 92% 100%, rgba(0, 232, 126, 0.07), transparent 60%),
		var(--card-gradient);
	overflow: hidden;
	/* Matches the sentiment card beside it rather than hugging its content, so
	   the row has one baseline instead of two. */
	display: flex;
	flex-direction: column;
}

.epi-showcase__viewport {
	display: grid;
	/* One cell. Every slide is placed into it, so the band is as tall as its
	   tallest slide and never reflows mid-rotation. */
	grid-template-areas: 'slide';
	flex: 1;
	min-height: 132px;
}

.epi-slide {
	grid-area: slide;
	display: grid;
	grid-template-columns: 56px minmax(0, 1fr) auto;
	align-items: center;
	gap: 18px;
	padding: 20px 22px 26px;

	/*
	 * 🔴 Only the INCOMING slide animates. The outgoing one is switched off the
	 * instant it loses the class, because `transition` here is `none` and the
	 * property only comes back on in `.is-active` below.
	 *
	 * A symmetric cross-fade was the obvious way to write this and it is wrong:
	 * two slides stacked in one grid cell, both part-transparent at the same
	 * moment, print their headlines through each other. Worse, a transition
	 * that never finishes — a background tab freezes them mid-flight — leaves
	 * that state on screen permanently. Fading in over an already-cleared cell
	 * has no frame where two slides are both legible.
	 */
	opacity: 0;
	visibility: hidden;
	transform: translateY(8px);
	z-index: 1;
	transition: none;
}

.epi-slide.is-active {
	opacity: 1;
	visibility: visible;
	transform: none;
	z-index: 2;
}

/*
 * The fade is opt-in, and the script only opts in while the tab is actually
 * being looked at. A transition started in a background tab freezes part-way
 * and stays there, so a slide changed while hidden would sit at opacity 0 until
 * the compositor happened to resume. Without the class the new slide simply
 * appears — which is the right answer for a tab nobody is watching.
 */
.epi-showcase.is-animated .epi-slide.is-active {
	transition: opacity 460ms var(--ease-lift), transform 460ms var(--ease-lift);
}

/* --- the figure ------------------------------------------------------------ */

.epi-slide__figure {
	width: 64px;
	height: 64px;
	border-radius: 16px;
	border: 1px solid var(--line-strong);
	background: var(--bg-soft);
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 5px;
	overflow: hidden;
}

.epi-slide__figure img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* The mark drawn as two squares, never typed. WordPress rewrites the emoji
   into a remote <img>, and the disable filter is not a reason to depend on it. */
.epi-slide__sq {
	width: 17px;
	height: 17px;
	border-radius: 4px;
}

.epi-slide__sq--r { background: var(--cube-red); }
.epi-slide__sq--g { background: var(--cube-green); }

/* --- the copy -------------------------------------------------------------- */

.epi-slide__body { min-width: 0; }

.epi-slide__eyebrow {
	font-family: var(--font-mono);
	font-size: 9.5px;
	letter-spacing: 1.9px;
	color: var(--fg-label);
	text-transform: uppercase;
	margin-bottom: 7px;
}

.epi-slide__title {
	font-size: 25px;
	font-weight: 800;
	font-stretch: var(--stretch-head);
	letter-spacing: -0.7px;
	line-height: 1.12;
	margin-bottom: 6px;
}

.epi-slide__text {
	font-size: 13.5px;
	line-height: 1.55;
	color: var(--fg-mute);
	/* Two lines, then ellipsis. A slide that grows a third line changes the
	   band's height and shoves the hero — the one thing this layout must not do. */
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* --- the number ------------------------------------------------------------ */

.epi-slide__stat {
	text-align: right;
	white-space: nowrap;
}

.epi-slide__num {
	display: block;
	font-family: var(--font-mono);
	font-size: 27px;
	font-weight: 600;
	letter-spacing: -1.1px;
	color: var(--fg);
}

.epi-slide__num--up   { color: var(--ui-bull); }
.epi-slide__num--down { color: var(--ui-bear); }

.epi-slide__sub {
	display: block;
	margin-top: 3px;
	font-family: var(--font-mono);
	font-size: 9.5px;
	letter-spacing: 1.5px;
	color: var(--fg-ghost);
	text-transform: uppercase;
}

.epi-slide__cta {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	margin-top: 11px;
	padding: 8px 13px;
	border-radius: var(--r-ctrl);
	border: 1px solid var(--line-accent);
	background: rgba(47, 125, 255, 0.08);
	font-family: var(--font-mono);
	font-size: 9.5px;
	letter-spacing: 1.3px;
	text-transform: uppercase;
	color: var(--ui-accent-bright);
	white-space: nowrap;
	transition: border-color 160ms ease, background 160ms ease;
}

.epi-slide__cta:hover {
	border-color: rgba(47, 125, 255, 0.65);
	background: rgba(47, 125, 255, 0.16);
	color: var(--ui-accent-bright);
}

/* --- the dots, which double as a progress bar ------------------------------ */

.epi-showcase__dots {
	position: absolute;
	right: 26px;
	bottom: 12px;
	display: flex;
	gap: 6px;
}

.epi-showcase__dot {
	position: relative;
	width: 26px;
	height: 3px;
	padding: 0;
	border: 0;
	border-radius: 2px;
	background: rgba(255, 255, 255, 0.13);
	cursor: pointer;
}

/* 🔴 A 3px-tall control is a 3px-tall tap target. The bar stays 3px because
   that is the design; the hit area is grown around it with a pseudo-element, so
   a thumb lands on it without the dots becoming visually heavier. */
.epi-showcase__dot::before {
	content: '';
	position: absolute;
	inset: -14px -3px;
}

.epi-showcase__dot:hover { background: rgba(255, 255, 255, 0.28); }

.epi-showcase__fill {
	display: block;
	width: 100%;
	height: 100%;
	border-radius: 2px;
	background: var(--ui-accent);
	transform: scaleX(0);
	transform-origin: left center;
	/* Above the hit area, or the pseudo-element paints over the progress. */
	position: relative;
	z-index: 1;
}

/* The fill is driven by the script through the Web Animations API rather than a
   CSS animation, so pausing on hover and jumping on a click are the same one
   operation on the same object. */
.epi-showcase__dot.is-active { background: rgba(47, 125, 255, 0.26); }

@media (prefers-reduced-motion: reduce) {
	.epi-slide { transition: none; }
	.epi-showcase__fill { display: none; }
}

@media (max-width: 1180px) {
	/* The row stops being a row before the panels get cramped. Sentiment needs
	   its 24 buckets and the band needs a readable line; below this they fight. */
	.epi-signals { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 1080px) {
	.epi-slide { gap: 16px; }
	.epi-slide__figure { width: 56px; height: 56px; }
}

@media (max-width: 720px) {
	.epi-showcase__viewport { min-height: 0; }
	.epi-slide {
		grid-template-columns: 44px minmax(0, 1fr);
		gap: 14px;
		padding: 18px 16px 26px;
	}
	.epi-slide__figure { width: 44px; height: 44px; border-radius: 12px; }
	.epi-slide__sq { width: 12px; height: 12px; border-radius: 3px; }
	.epi-slide__title { font-size: 19px; font-stretch: 100%; letter-spacing: -0.3px; }
	.epi-slide__text { font-size: 12.5px; }
	/* The number would be a third column on a screen that has room for two. */
	.epi-slide__stat { display: none; }
	.epi-showcase__dots { right: 16px; bottom: 10px; }
	.epi-showcase__dot { width: 18px; }
}

/* --- narrative heat pills -------------------------------------------------- */

.epi-heat {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.epi-heat__pill {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 7px 11px;
	border-radius: var(--r-chip);
	border: 1px solid var(--line-strong);
	background: rgba(255, 255, 255, 0.02);
	transition: border-color 160ms ease;
}

.epi-heat__pill:hover { border-color: rgba(255, 255, 255, 0.28); }

.epi-heat__tag {
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 500;
	color: #DDE2EC;
	letter-spacing: 0.3px;
}

.epi-heat__delta {
	font-family: var(--font-mono);
	font-size: 10px;
}

.epi-heat__delta--up   { color: var(--ui-bull); }
.epi-heat__delta--down { color: var(--ui-bear); }
.epi-heat__delta--flat { color: var(--ui-neut); }
.epi-heat__delta--new  { color: var(--ui-accent-soft); }

.epi-empty {
	font-family: var(--font-mono);
	font-size: 10.5px;
	letter-spacing: 1px;
	color: var(--fg-ghost);
	text-transform: uppercase;
}

/* --- top signal hero ------------------------------------------------------- */

/*
 * 🔴 50/50, not 1.25fr/1fr.
 *
 * The row above it — sentiment beside the showcase — splits at 1.05fr/1fr with
 * a 20px gap, so its seam sits fractionally past the middle. The hero at
 * 1.25fr/1fr put its own seam a long way right of that, and the two edges
 * disagreeing by ~90px is exactly the kind of misalignment that reads as
 * sloppy without anybody being able to say why.
 *
 * An even split lands the hero's seam on the page's centre line, which is the
 * one vertical the eye can actually check.
 */
.epi-hero {
	display: grid;
	grid-template-columns: 1fr 1fr;
	border: 1px solid var(--line-strong);
	border-radius: var(--r-hero);
	overflow: hidden;
	background: var(--bg-soft);
	margin-bottom: 26px;
	transition: border-color 200ms ease;
}

.epi-hero:hover { border-color: rgba(47, 125, 255, 0.5); }

.epi-hero__media {
	position: relative;
	min-height: 380px;
	background: var(--bg-raised);
	background-image: var(--media-hatch);
}

.epi-hero__media img,
.epi-card__media img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.epi-hero__badge {
	position: absolute;
	left: 20px;
	top: 20px;
	display: flex;
	align-items: center;
	gap: 7px;
	padding: 6px 11px;
	border-radius: 7px;
	background: rgba(8, 9, 12, 0.72);
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	border: 1px solid rgba(47, 217, 138, 0.35);
	z-index: 2;
}

.epi-hero__badge span:last-child {
	font-family: var(--font-mono);
	font-size: 9.5px;
	letter-spacing: 1.6px;
	color: var(--ui-bull);
	text-transform: uppercase;
}

.epi-hero__badge .epi-dot {
	width: 6px;
	height: 6px;
	background: var(--ui-bull);
}

.epi-hero__body {
	padding: 34px 34px 30px;
	display: flex;
	flex-direction: column;
}

.epi-hero__meta {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-bottom: 18px;
	flex-wrap: wrap;
}

.epi-chip {
	font-family: var(--font-mono);
	font-size: 9.5px;
	font-weight: 600;
	letter-spacing: 1.5px;
	color: var(--bg);
	padding: 4px 8px;
	border-radius: 5px;
	white-space: nowrap;
}

.epi-hero__source {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: 1.2px;
	color: var(--fg-label);
	text-transform: uppercase;
}

.epi-hero__age {
	font-family: var(--font-mono);
	font-size: 10px;
	color: var(--fg-ghost);
}

.epi-hero__title {
	font-size: 38px;
	line-height: 1.1;
	font-stretch: var(--stretch-head);
	letter-spacing: -1px;
	font-weight: 800;
	margin-bottom: 16px;
}

.epi-hero__title a { color: var(--fg); }
.epi-hero__title a:hover { color: var(--fg); }

.epi-hero__dek {
	font-size: 15.5px;
	line-height: 1.6;
	color: var(--fg-dim);
	margin-bottom: 24px;
	/* 52ch inside a hero panel that is already a narrow column meant the dek
	   stopped short of the headline above it. The panel sets the measure. */
}

.epi-hero__fill { flex: 1; }

.epi-read {
	border: 1px solid rgba(47, 125, 255, 0.28);
	background: rgba(47, 125, 255, 0.07);
	border-radius: 12px;
	padding: 14px 16px;
}

.epi-read__head {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-bottom: 9px;
}

.epi-read__label {
	font-family: var(--font-mono);
	font-size: 9px;
	letter-spacing: 1.6px;
	color: var(--ui-accent-soft);
	text-transform: uppercase;
}

.epi-read__conf {
	font-family: var(--font-mono);
	font-size: 9px;
	color: var(--ui-accent);
}

.epi-read__body {
	font-size: 13.5px;
	line-height: 1.55;
	color: var(--fg-soft);
}

/* --- daily call strip ------------------------------------------------------ */

.epi-call {
	display: flex;
	align-items: center;
	gap: 14px;
	flex-wrap: wrap;
	border: 1px solid rgba(47, 125, 255, 0.28);
	background: linear-gradient(90deg, rgba(47, 125, 255, 0.10), rgba(47, 125, 255, 0.02));
	border-radius: var(--r-ctrl);
	padding: 14px 18px;
	margin-bottom: 30px;
}

.epi-call__label {
	font-family: var(--font-mono);
	font-size: 9.5px;
	font-weight: 600;
	letter-spacing: 1.6px;
	color: var(--ui-accent-soft);
	text-transform: uppercase;
	white-space: nowrap;
}

.epi-call__q {
	font-size: 14.5px;
	font-weight: 500;
	color: var(--fg);
	flex: 1;
	min-width: 200px;
}

.epi-call__cta {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: 1.4px;
	color: var(--ui-accent);
	text-transform: uppercase;
	white-space: nowrap;
}

.epi-call__terms {
	font-family: var(--font-mono);
	font-size: 9px;
	letter-spacing: 1.2px;
	color: var(--fg-ghost);
	text-transform: uppercase;
	white-space: nowrap;
}

/* --- streams --------------------------------------------------------------- */

.epi-streams {
	display: grid;
	grid-template-columns: 1fr 1fr 1fr var(--rail-w);
	gap: 20px;
	align-items: start;
}

.epi-streams--norail { grid-template-columns: 1fr 1fr 1fr; }

.epi-stream__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	padding: 0 2px 12px;
	margin-bottom: 14px;
	border-bottom: 1px solid var(--line-strong);
	position: sticky;
	top: var(--chrome-h);
	background: var(--bg);
	z-index: 5;
}

.epi-stream__title {
	display: flex;
	align-items: center;
	gap: 9px;
}

.epi-stream__swatch {
	width: 9px;
	height: 9px;
	border-radius: 2px;
}

.epi-stream__label {
	font-family: var(--font-mono);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 2px;
	text-transform: uppercase;
}

.epi-stream__count {
	font-family: var(--font-mono);
	font-size: 10px;
	color: var(--fg-ghost);
}

.epi-stream__all {
	font-family: var(--font-mono);
	font-size: 9.5px;
	letter-spacing: 1.2px;
	color: var(--fg-faint);
	text-transform: uppercase;
}

.epi-stream__all:hover { color: var(--ui-accent-soft); }

/* Text this small is a 12px-tall tap target. Padding gives the thumb something
   to land on without moving the label off its baseline — the negative margin
   pulls the row back to where it was. */
@media (max-width: 720px) {
	.epi-stream__all {
		padding: 12px 8px;
		margin: -12px -8px;
		font-size: 10.5px;
	}
}

.epi-stream__list {
	display: flex;
	flex-direction: column;
	gap: 14px;
}

/* --- news card ------------------------------------------------------------- */

.epi-card {
	border: 1px solid var(--line);
	border-radius: var(--r-card);
	background: var(--bg-soft);
	overflow: hidden;
	transition: transform 180ms var(--ease-lift), border-color 180ms ease, background 180ms ease;
}

.epi-card:hover {
	transform: translateY(-3px);
	border-color: var(--line-hover);
	background: #0E1117;
}

.epi-card__media {
	position: relative;
	aspect-ratio: 16 / 9;
	background: var(--bg-raised);
	background-image: var(--media-hatch);
}

.epi-card__rule {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 2px;
	z-index: 2;
}

.epi-card__body { padding: 14px 15px 13px; }

.epi-card__title {
	font-size: 15px;
	line-height: 1.25;
	letter-spacing: -0.35px;
	font-weight: 600;
	margin-bottom: 8px;
}

.epi-card__title a { color: var(--fg); }
.epi-card__title a:hover { color: var(--fg); }

.epi-card__dek {
	font-size: 12.5px;
	line-height: 1.5;
	color: var(--fg-mute);
	margin-bottom: 13px;
}

.epi-meter {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-bottom: 11px;
}

.epi-meter__track {
	flex: 1;
	height: 3px;
	border-radius: 2px;
	background: var(--bg-well);
	overflow: hidden;
}

.epi-meter__fill { height: 100%; }

.epi-meter__score {
	font-family: var(--font-mono);
	font-size: 9.5px;
	font-weight: 600;
}

.epi-card__foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	font-family: var(--font-mono);
	font-size: 9.5px;
	letter-spacing: 1.1px;
	color: var(--fg-ghost);
	text-transform: uppercase;
}

/* --- live wire rail -------------------------------------------------------- */

.epi-wire {
	position: sticky;
	top: var(--chrome-h);
	border: 1px solid var(--line-accent);
	border-radius: var(--r-rail);
	background: var(--rail-gradient);
	overflow: hidden;
}

.epi-wire__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	padding: 15px 16px;
	border-bottom: 1px solid var(--line);
}

.epi-wire__title {
	display: flex;
	align-items: center;
	gap: 9px;
	font-family: var(--font-mono);
	font-size: 10.5px;
	font-weight: 600;
	letter-spacing: 1.8px;
	color: var(--ui-accent-soft);
	text-transform: uppercase;
}

.epi-wire__title .epi-dot {
	width: 6px;
	height: 6px;
	background: var(--ui-accent);
	animation-duration: 1.4s;
}

.epi-wire__sub {
	font-family: var(--font-mono);
	font-size: 9px;
	letter-spacing: 1px;
	color: var(--fg-faint);
}

.epi-wire__list {
	max-height: 720px;
	overflow-y: auto;
}

.epi-wire__row {
	display: block;
	padding: 13px 16px;
	border-bottom: 1px solid var(--line-soft);
	transition: background 150ms ease;
	color: inherit;
}

.epi-wire__row:hover { color: inherit; }

.epi-wire__row:hover { background: rgba(47, 125, 255, 0.06); }

.epi-wire__meta {
	display: flex;
	align-items: center;
	gap: 7px;
	margin-bottom: 7px;
}

.epi-wire__kind {
	font-family: var(--font-mono);
	font-size: 8.5px;
	font-weight: 600;
	letter-spacing: 1.2px;
	text-transform: uppercase;
	padding: 3px 6px;
	border-radius: 4px;
	border: 1px solid currentColor;
}

.epi-wire__time {
	font-family: var(--font-mono);
	font-size: 9px;
	color: var(--fg-ghost);
}

.epi-wire__fill { flex: 1; }

.epi-wire__amt {
	font-family: var(--font-mono);
	font-size: 10px;
	font-weight: 600;
}

.epi-wire__text {
	font-size: 12.5px;
	line-height: 1.45;
	color: var(--fg-body);
}

/* ==========================================================================
   Narrow. The three streams collapse before the panels do — a 1fr column of
   news cards is the last thing that still works at 900px.
   ========================================================================== */

@media (max-width: 1240px) {
	.epi-streams,
	.epi-streams--norail {
		grid-template-columns: 1fr 1fr;
	}

	.epi-wire {
		position: static;
		grid-column: 1 / -1;
	}

	.epi-wire__list { max-height: 420px; }
}

@media (max-width: 1080px) {
	.epi-hero { grid-template-columns: 1fr; }
	.epi-hero__media { min-height: 0; aspect-ratio: 16 / 9; }
	.epi-hero__body { padding: 24px 24px 22px; }
	.epi-hero__title { font-size: 30px; letter-spacing: -1px; }
}

@media (max-width: 900px) {
	.epi-signals { grid-template-columns: 1fr; }
	.epi-tilt { gap: 18px; }
}

@media (max-width: 720px) {
	.epi-feed { padding: 20px var(--gutter) 60px; }

	.epi-streams,
	.epi-streams--norail {
		grid-template-columns: 1fr;
	}

	.epi-panel { padding: 18px 16px; }

	.epi-tilt {
		flex-direction: column;
		align-items: stretch;
		gap: 16px;
	}

	.epi-histogram__bars { height: 38px; }

	.epi-hero__title { font-size: 26px; letter-spacing: -0.8px; }
	.epi-hero__dek { font-size: 14px; }

	/* Each sticky header would otherwise pin three deep on one column. */
	.epi-stream__head { position: static; }

	.epi-stream { margin-bottom: 28px; }
}

/* ==========================================================================
   Market Sentiment — the window selector.

   The panel used to be a fixed 24 hours with the story count sitting where
   these buttons are. The count moved down beside the tilt, which is where it
   belongs anyway: it qualifies the reading, not the panel.
   ========================================================================== */

.epi-range {
	display: flex;
	gap: 2px;
	padding: 2px;
	border: 1px solid var(--line);
	border-radius: 9px;
	background: rgba(8, 9, 12, 0.55);
	flex-shrink: 0;
}

.epi-range__btn {
	font-family: var(--font-mono);
	font-size: 9px;
	font-weight: 600;
	letter-spacing: 1.1px;
	text-transform: uppercase;
	color: var(--fg-faint);
	background: none;
	border: 0;
	border-radius: 7px;
	padding: 5px 8px;
	cursor: pointer;
	transition: color 160ms ease, background 160ms ease;
	white-space: nowrap;
}

.epi-range__btn:hover { color: var(--fg-soft); background: rgba(255, 255, 255, 0.04); }

.epi-range__btn.is-active {
	color: var(--fg);
	background: rgba(47, 125, 255, 0.16);
	box-shadow: inset 0 0 0 1px rgba(47, 125, 255, 0.34);
}

.epi-range__btn:focus-visible {
	outline: 2px solid var(--ui-accent);
	outline-offset: 1px;
}

/* The chart dims while a window is in flight. It does not empty: an empty
   chart and a loading chart look identical, and one of them is a fault. */
.epi-panel--sentiment.is-loading .epi-histogram { opacity: 0.45; }
.epi-histogram { transition: opacity 160ms ease; }

.epi-tilt__read { min-width: 0; }

.epi-tilt__count {
	font-family: var(--font-mono);
	font-size: 9px;
	letter-spacing: 1.1px;
	text-transform: uppercase;
	color: var(--fg-ghost);
	margin-top: 8px;
	white-space: nowrap;
}

/* The honesty line. Only rendered when the window reaches past the record —
   see Epinews_Sentiment_Series::note(). */
.epi-panel__note {
	font-size: 11.5px;
	line-height: 1.5;
	color: var(--fg-faint);
	margin: 14px 0 0;
	padding-top: 12px;
	border-top: 1px solid var(--line-soft);
	max-width: 74ch;
}

@media (max-width: 900px) {
	.epi-panel--sentiment .epi-panel__head { flex-wrap: wrap; gap: 10px; }
	.epi-range { width: 100%; justify-content: space-between; }
	.epi-range__btn { flex: 1; text-align: center; padding: 6px 4px; }
}

/* The token slide's mark, running the house strobe.

   🔴 The two squares are offset by one third of the 90ms cycle, so the pair is
   never the same colour at once. Without the offset the mark stops reading as
   two squares and becomes one flashing block — the same reason the header's two
   cubes carry a -1.1s phase offset on their spin. */
.epi-slide__figure--flash .epi-slide__sq {
	animation: epi-news-flash-bg var(--flash-cycle) steps(1, end) infinite;
}

.epi-slide__figure--flash .epi-slide__sq--g {
	animation-delay: calc(var(--flash-cycle) / -3);
}

@media (prefers-reduced-motion: reduce) {
	/* Back to the UI tier it carries everywhere else on the site. */
	.epi-slide__figure--flash .epi-slide__sq { animation: none !important; }
	.epi-slide__figure--flash .epi-slide__sq--r { background: var(--ui-bear) !important; }
	.epi-slide__figure--flash .epi-slide__sq--g { background: var(--ui-bull) !important; }
}
