/**
 * Single AI alternative — `tr-altpage`.
 *
 * Replaces modules/alternative/assets/css/single-alternative.css and the tool page's
 * shell it was layered over. Every value below is a theme token; the file introduces
 * no colour, no radius and no shadow of its own, because the design direction is the
 * system that already exists (CLAUDE.md 9.5).
 *
 * ---------------------------------------------------------------------------------
 * C-72: REWRITTEN RATHER THAN PATCHED
 * ---------------------------------------------------------------------------------
 * C-64's structure and this one disagree about the page's shape in five places —
 * masthead vs hero, one column vs main-plus-rail, compressed row vs full review,
 * static grid vs carousel, left-aligned band head vs centred — so patching would have
 * left the old rules resident and unreachable. Brief 58 asks for the opposite of that.
 * What is CARRIED OVER VERBATIM is the work that still has a consumer: the comparison
 * table, the pricing filter, `tr-altpicks`, the parent script's lightbox, and the
 * two-button set.
 *
 * ONE RENAME. The comparison table's classes were `.tr-cmp*` — the SAME namespace
 * `assets/css/compare-single.css` uses for the comparison single's own article root,
 * layout, main column and rail. The two never collided only because each stylesheet
 * is enqueued behind its own `is_singular()` gate, which makes it a latent collision
 * rather than a safe one: `.tr-cmp` here is a table, and `.tr-cmp` there is the page.
 * They are now `.tr-alttable*`, and every reference is in this file and
 * template-parts/alternative/compare-table.php — both updated in this task
 * (CLAUDE.md 9.7: rename only with every reference verified).
 *
 * ---------------------------------------------------------------------------------
 * THE STRUCTURAL IDEA: every section is a different shape, and the reviews get room
 * ---------------------------------------------------------------------------------
 *   hero          two columns, the anchor's screenshot on the right
 *   what is       prose beside one small bordered fact panel
 *   comparison    a table, scrolling inside its own box
 *   jump          one flat row of named links
 *   reviews       full-measure mini-reviews, separated by air and one rule
 *   which one     a two-column definition list, rules between rows
 *   head to head  `tr-vs-card`   — a symmetric pair with a medallion
 *   more tools    `tr-tools-card` — the directory's own identity card
 *   lists         `tr-list-card` — title-led, tools named underneath
 *   more guides   `tr-alt-card`  — anchored to one large left tile
 *   categories    `tr-catnav`    — a dense grid of boxed links
 *
 * The four card bands cost this file almost nothing, and that is the point: the shared
 * cards were each drawn as a deliberately different silhouette so a visitor can tell
 * the archives apart without reading a word. Composing the page foot out of them buys
 * variety that bespoke CSS used to buy badly. What remains here is per-band card
 * counts.
 *
 * COLOUR IS RESTRAINED, deliberately: tinted neutrals carry the page and
 * `--color-primary` appears in six places only — the primary action, the active
 * filter, the anchor table row's rule, the rank, the pros marker, and link/focus
 * states. A page with nine screenshots on it is dense enough that a second accent
 * would be noise.
 *
 * @package TiorAI
 */

/* =========================================================================
   TOKENS LOCAL TO THIS PAGE
   Derived values only — each one is an expression of a global token, kept here so
   the ratios are declared once instead of being retyped down the file.
   ========================================================================= */

.tr-altpage {
	/* The reading measure. Prose is capped at the theme's own measure; the table and
	   the screenshots are allowed the full main column. */
	--tr-altpage-measure: var(--tiorai-prose-measure, 72ch);
	--tr-altpage-hairline: 1px solid var(--border-default);
	--tr-altpage-mark: 44px;

	/*
	 * THE ONE OFFSET EVERY STICKY THING ON THIS PAGE IS MEASURED FROM.
	 *
	 * Derived from the section nav's own published tokens rather than the hardcoded
	 * `132px` C-64 used: `--tiorai-secnav-top` is the pinned header height and
	 * `--tiorai-secnav-h` the strip's own, both declared on `:root` by
	 * assets/css/unified/section-nav.css. A literal goes stale the moment the header
	 * height changes and the failure is silent — an anchor landing behind the nav.
	 */
	--tr-altpage-chrome: calc(
		var(--tiorai-secnav-top, 65px) + var(--tiorai-secnav-h, 2.875rem)
	);
	--tr-altpage-anchor-offset: calc(var(--tr-altpage-chrome) + var(--space-5));
}

/*
 * `scroll-margin-top` on every anchor target: the section nav's own links, the jump
 * list's links, and any `#tool-{slug}` a visitor arrives on from a search result all
 * land BELOW the header and the strip rather than behind them.
 */
[data-tiorai-section] {
	scroll-margin-top: var(--tr-altpage-anchor-offset);
}

/* =========================================================================
   THE MEASURE — one container model, shared with the comparison single.

   THIS IS THE SPACING CONTRACT, and it is copied rather than approximated.
   `/compare/{slug}/` resolves to: a 1280px container with NO padding of its own,
   and `padding-inline: var(--space-5)` on each section INSIDE it. That puts its
   text box at 1240px wide starting 126px from the viewport edge at 1440.

   This page used the theme's generic `.container`, which carries its own gutter, so
   the same content resolved to 1264px starting at 114px — 12px to the left of its
   sibling page and 24px wider, with a different vertical rhythm on top
   (`margin-bottom: 64px` per section against the comparison's `padding-block: 40px`).
   Measured side by side, that is what read as broken padding: two pages in the same
   navigation, one of them inset differently from the other.

   So the container is now `tr-altpage__container`, byte-for-byte the comparison's
   `tr-cmp__container`, and the gutter moves onto the sections — which is also what
   lets the section rules draw the hairline BETWEEN sections inset to the same
   `--space-5`, the way the comparison page does.
   ========================================================================= */

.tr-altpage__container {
	margin-inline: auto;
	max-width: 1280px;
	width: 100%;
}

/* =========================================================================
   THE HERO — the comparison hero's composition (brief 4, 54)
   ========================================================================= */

/*
 * THE SAME GROUND AS `/compare/`: the page surface with a single low-chroma wash of
 * the brand hue bled in from the top-left, NOT a flat `--color-bg-secondary` panel.
 * The wash is what makes the hero read as the top of the page rather than as a grey
 * box sitting on it, and at 0.045 alpha of `--color-primary-rgb` it resolves against
 * whatever surface is under it, so it is correct in both themes.
 */
.tr-altpage__hero {
	background:
		radial-gradient(120% 140% at 12% 0%, rgba(var(--color-primary-rgb), 0.045) 0%, transparent 62%),
		var(--color-bg-primary);
	border-block-end: var(--tiorai-secnav-rule, 1px) solid var(--border-default);
	padding-block: var(--space-6) var(--space-10);
}

/*
 * THE GRID IS ITS OWN CONTAINER, which is why hero.php has no wrapper div around it —
 * the comparison hero is built the same way. `minmax(0, 1fr) minmax(0, 0.85fr)` and
 * `clamp(1.75rem, 4vw, 3.5rem)`: the same ratio and the same gap, so the H1 on this
 * page and the H1 on a comparison start at the same x and wrap at the same width.
 */
.tr-altpage__hero-grid {
	align-items: center;
	display: grid;
	gap: clamp(1.75rem, 4vw, 3.5rem);
	grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
	margin-inline: auto;
	max-width: 1280px;
	padding-inline: var(--space-5);
	width: 100%;
}

/* No picture, no second track — the sibling heroes' `--single` rule. */
.tr-altpage__hero-grid--single {
	grid-template-columns: minmax(0, 1fr);
}

.tr-altpage__hero-main {
	min-width: 0;
}

.tr-altpage__hero-main .tr-breadcrumbs,
.tr-altpage__hero-main .ui-breadcrumbs {
	margin-bottom: var(--space-5);
}

.tr-altpage__eyebrow {
	margin: 0 0 var(--space-3);
	font-size: var(--font-size-sm);
	font-weight: var(--font-weight-semibold);
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--color-text-tertiary);
}

.tr-altpage__eyebrow a {
	color: inherit;
	text-decoration: none;
}

.tr-altpage__eyebrow a:hover,
.tr-altpage__eyebrow a:focus-visible {
	color: var(--color-primary);
	text-decoration: underline;
	text-underline-offset: 3px;
}

.tr-altpage__ident {
	display: flex;
	align-items: center;
	gap: var(--space-4);
}

.tr-altpage__hero-logo {
	flex: 0 0 auto;
	width: 56px;
	height: 56px;
	border-radius: var(--radius-md);
	background: var(--color-bg-primary);
	border: var(--tr-altpage-hairline);
	object-fit: contain;
	padding: 6px;
}

/*
 * NO GRADIENT ON THE TITLE. The parent clipped `--color-text-gradient` to the h1,
 * which is decorative rather than meaningful, drops to a flat fallback wherever
 * `background-clip` is unsupported, and still carried the pre-lime cyan the rest of
 * the theme has migrated away from. One solid ink, one large size.
 */
/*
 * THE SAME TYPE AS THE COMPARISON HERO, measured rather than guessed at.
 *
 * `.tr-cmp-hero__title` carries NO desktop font-size at all — it only drops to
 * `--font-size-3xl` inside a `max-width: 768px` block — so above 768px it renders at
 * the theme's own `h1` default, `--font-size-4xl` / 36px. That is the ladder
 * reproduced here: 36px desktop, 30px on a phone. The previous `clamp()` resolved to
 * 46px, ten pixels larger than the same-rank heading on a sibling page, which is the
 * single loudest way two pages in one navigation stop looking like one product.
 *
 * No gradient on the title: the parent clipped `--color-text-gradient` to the h1,
 * which is decorative rather than meaningful, drops to a flat fallback wherever
 * `background-clip` is unsupported, and still carried the pre-lime cyan.
 */
.tr-altpage__title {
	margin: 0;
	max-width: none;
	font-size: var(--font-size-4xl);
	line-height: var(--line-height-tight);
	letter-spacing: -0.02em;
	font-weight: var(--font-weight-bold);
	color: var(--color-text-primary);
	text-wrap: balance;
}

/*
 * The deck takes the theme's own paragraph metrics — `--line-height-relaxed`, no
 * measure cap — which is what the comparison lede resolves to, since it also declares
 * neither. Capping it at 62ch made this hero's sentence wrap a line earlier than the
 * identical sentence on a comparison.
 */
.tr-altpage__deck {
	margin: var(--space-4) 0 0;
	max-width: none;
	font-size: var(--font-size-base);
	line-height: var(--line-height-relaxed);
	color: var(--color-text-secondary);
}

/*
 * The labelled facts. `repeat(auto-fit, minmax(130px, 1fr))` and the same margin as
 * `tr-cmp-hero__highlights` — a GRID, not a wrapping flex row, so the columns line up
 * with each other instead of tracking the width of the value above them.
 *
 * The rule above it is gone with the flex: the comparison strip has none, and on a
 * hero whose ground is already a wash the border was a second horizontal line eleven
 * pixels from the deck.
 */
.tr-altpage__highlights {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
	gap: var(--space-4) var(--space-6);
	margin-block: var(--space-6) 0;
	width: 100%;
}

.tr-altpage__highlight {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
}

/* `2xs` / `sm` — the sizes `tr-cmp-hero__highlight` resolves to, measured at 10px/14px. */
.tr-altpage__highlight dt {
	font-size: var(--font-size-2xs);
	font-weight: var(--font-weight-medium);
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-text-tertiary);
}

.tr-altpage__highlight dd {
	margin: 0;
	font-size: var(--font-size-sm);
	font-weight: var(--font-weight-semibold);
	color: var(--color-text-primary);
	font-variant-numeric: tabular-nums;
}

.tr-altpage__highlight dd a {
	color: inherit;
	text-decoration: none;
}

.tr-altpage__highlight dd a:hover,
.tr-altpage__highlight dd a:focus-visible {
	color: var(--color-primary);
	text-decoration: underline;
	text-underline-offset: 3px;
}

.tr-altpage__hero-actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-3);
	margin-block-start: var(--space-6);
	width: 100%;
}

/*
 * THE SCREENSHOT. 16:10 with `object-position: top`, because a product screenshot's
 * meaning is in its header and first rows — a crop that keeps the middle throws away
 * the part that identifies the product.
 */
.tr-altpage__hero-shot {
	position: relative;
	margin: 0;
	border: var(--tr-altpage-hairline);
	border-radius: var(--radius-2xl);
	overflow: hidden;
	background: var(--color-bg-primary);
	box-shadow: var(--shadow-soft);
}

.tr-altpage__hero-img {
	display: block;
	width: 100%;
	aspect-ratio: 16 / 10;
	object-fit: cover;
	object-position: top;
}

/*
 * The mark, bottom-left, on its OWN opaque ground rather than directly on the image:
 * the screenshot is arbitrary, and a transparent PNG of a dark wordmark over a dark
 * UI is invisible. Bottom-left is where an app's own logo usually sits and the
 * quietest part of a top-heavy frame.
 */
.tr-altpage__hero-mark {
	position: absolute;
	inset-block-end: var(--space-4);
	inset-inline-start: var(--space-4);
	width: 48px;
	height: 48px;
	padding: 6px;
	border-radius: var(--radius-md);
	background: var(--color-bg-primary);
	border: var(--tr-altpage-hairline);
	object-fit: contain;
	box-shadow: var(--shadow-soft);
}

/* =========================================================================
   SECTION NAV — the shared `tr-section-nav`, positioned only.
   The component owns its own appearance.
   ========================================================================= */

.tr-altpage__nav {
	margin-bottom: var(--space-10);
}

/* =========================================================================
   SECTION SHELL
   ========================================================================= */

/*
 * `.tr-altpage__intro` IS GONE — C-74 moved the overview and the "why" section
 * inside the layout, so there is no full-measure band above the split any more and
 * `.tr-altpage__body` is the only wrapper left.
 */
.tr-altpage__body {
	/*
	 * NEITHER WRAPPER PADS. The sections inside them carry the whole rhythm, exactly
	 * as `.tr-cmp__body` does — a wrapper that also pads means the first section's
	 * air is the sum of two rules and the last section's is not, which is how the
	 * gaps down a page stop being equal.
	 */
	padding-block: 0;
}

/*
 * THE SECTION RHYTHM, copied from `.tr-cmp .tr-cmp-section`: 40px of vertical padding
 * and `--space-5` of horizontal, dropping to `--space-8` vertical below 768px.
 *
 * PADDING, NOT MARGIN, and that is the substantive change. Margin-bottom cannot be
 * shared with the next section, so the gap between two sections was 64px while the gap
 * between the first section and the page chrome above it was 0 — and no section could
 * carry a rule at its own top edge, because a margin has no edge to draw on. Padding
 * gives 40px above AND below every section, an identical 80px between any two of them,
 * and a border-box the `::before` hairline below can inset into.
 */
.tr-altpage__section {
	padding-block: 40px;
	padding-inline: var(--space-5);
	position: relative;
}

/*
 * THE HAIRLINE BETWEEN SECTIONS — the comparison page's own separator, same selector
 * shape and the same `inset-inline: var(--space-5)` so it stops where the text does
 * rather than running the full container width. `* + ` means the FIRST section never
 * draws one, which is what stops a rule appearing directly under the sticky nav.
 */
.tr-altpage__main > * + .tr-altpage__section::before {
	background: var(--border-default);
	content: "";
	height: 1px;
	inset-block-start: 0;
	inset-inline: var(--space-5);
	position: absolute;
}

/*
 * THE GLOBAL `section` PADDING IS NEUTRALISED HERE, and this is a measured bug fix
 * rather than a defensive reset.
 *
 * theme-unified.css:1749 sets `section { padding: 70px 0 }` — written for the
 * homepage's full-bleed bands, applied to every `<section>` on the site. Everything
 * on this page that is semantically a section inherited it: each
 * `.tr-altpage__section`, and each of the THREE blocks inside every review.
 *
 * Measured on /alternatives/poe-alternatives/ before this rule: the "Key features"
 * block reported 431px tall against 292px of actual content, and each of the eight
 * reviews carried 420px of padding nobody had asked for — 3,360px of empty page,
 * plus ~140px per page-level section. It read as erratic whitespace between blocks
 * that were otherwise 28px apart, which is exactly what it was.
 *
 * `.tr-altpage__section` and `.tr-altpage__band` are NOT in this selector: both declare
 * their own `padding-block` above, so they are excluded by having an answer rather than
 * by being listed here. Only the review's three inner blocks still need the reset.
 */
.tr-altentry__block {
	padding-block: 0;
}

/*
 * The heading, matching `.tr-cmp-section__title`: `--font-size-2xl` at
 * `--font-weight-semibold`, `margin-block: 0 var(--space-6)`. The previous
 * `clamp(1.5rem … 2rem)` at `bold` resolved two steps larger than the same heading on
 * a comparison page.
 */
.tr-altpage__section-head {
	margin-block-end: var(--space-6);
	max-width: var(--tr-altpage-measure);
}

.tr-altpage__section-title {
	margin-block: 0 var(--space-6);
	font-size: var(--font-size-2xl);
	line-height: var(--line-height-snug);
	letter-spacing: -0.01em;
	font-weight: var(--font-weight-semibold);
	color: var(--color-text-primary);
	text-wrap: balance;
}

/*
 * Inside a `__section-head` the title's own bottom margin is the head's job, so it is
 * dropped — otherwise a section with a deck carries 24px twice between the two lines.
 */
.tr-altpage__section-head .tr-altpage__section-title {
	margin-block-end: 0;
}

.tr-altpage__section-deck {
	margin: var(--space-3) 0 0;
	font-size: var(--font-size-base);
	line-height: 1.6;
	color: var(--color-text-secondary);
}

/* Long-form blocks are capped at the measure; data blocks are not. */
.tr-altpage__prose {
	max-width: var(--tr-altpage-measure);
	color: var(--color-text-secondary);
	line-height: 1.7;
}

.tr-altpage__prose > :first-child {
	margin-top: 0;
}

.tr-altpage__prose > :last-child {
	margin-bottom: 0;
}

.tr-altpage__textlink {
	font-size: var(--font-size-sm);
	font-weight: var(--font-weight-semibold);
	color: var(--color-primary);
	text-decoration: none;
	text-underline-offset: 3px;
}

.tr-altpage__textlink:hover,
.tr-altpage__textlink:focus-visible {
	text-decoration: underline;
}

/* =========================================================================
   BUTTONS
   Two only. A page that offers nine products cannot afford four button weights; the
   parent had five CTA variants whose wording changed with the pricing taxonomy.

   The HERO does not use these — it uses the theme's own `btn btn--primary` /
   `btn--outline`, like both sibling heroes. These are the entry and panel buttons.
   ========================================================================= */

.tr-altbtn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--space-2);
	min-height: 40px;
	padding: 0 var(--space-4);
	border: 1px solid transparent;
	border-radius: var(--radius-md);
	font-size: var(--font-size-sm);
	font-weight: var(--font-weight-semibold);
	line-height: 1;
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
	transition: var(--transition-fast);
}

.tr-altbtn--primary {
	background: var(--color-primary);
	color: var(--color-text-on-brand, #ffffff);
}

.tr-altbtn--primary:hover {
	background: var(--color-primary-dark);
}

.tr-altbtn--ghost {
	background: transparent;
	border-color: var(--border-default);
	color: var(--color-text-primary);
}

.tr-altbtn--ghost:hover {
	border-color: var(--color-primary);
	color: var(--color-primary);
}

/*
 * THE THIRD WEIGHT, AND WHY THE PAGE CAN NOW AFFORD IT (C-74).
 *
 * `--ghost` is the neutral secondary: a hairline box in body ink, used beside the
 * primary on every one of the nine entries. `--quiet` is the SAME box in brand ink,
 * and it exists for exactly one relationship — an internal destination sitting
 * beside an outbound primary, where the reader has to be able to tell in one glance
 * that the two go to different KINDS of place. On the anchor panel that pair is
 * "Visit Poe" and "Read the Poe review": one leaves the site, one goes deeper into
 * it, and drawing the second as body-coloured text (which is what it was) made the
 * page's only internal exit the least visible thing in the section.
 *
 * It is not a third silhouette. Same height, same radius, same border width as
 * `--ghost`; only the ink and the border tint differ, so the button family is still
 * one shape at three volumes rather than three controls.
 */
.tr-altbtn--quiet {
	background: transparent;
	border-color: rgba(var(--color-primary-rgb), 0.4);
	color: var(--color-primary);
}

.tr-altbtn--quiet:hover {
	background: rgba(var(--color-primary-rgb), 0.08);
	border-color: var(--color-primary);
}

.tr-altbtn__icon {
	display: inline-flex;
	transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}

.tr-altbtn:hover .tr-altbtn__icon {
	transform: translateX(2px);
}

.tr-altpage :is(a, button):focus-visible {
	outline: var(--tiorai-focus-ring-width, 2px) solid var(--tiorai-focus-ring-color, currentColor);
	outline-offset: var(--tiorai-focus-ring-offset, 2px);
	border-radius: var(--radius-sm);
}

/*
 * The monogram revealed by `TiorAI.MediaFallback` when a logo URL 404s. It sits in
 * the same box the image occupied, so the swap cannot shift the layout.
 */
.tr-anchor__fallback,
.tr-alttable__fallback,
.tr-altentry__fallback,
.tr-altjump__fallback,
.tr-altpicks__fallback {
	font-weight: var(--font-weight-bold);
	color: var(--color-text-tertiary);
	line-height: 1;
}

.tr-alttable__fallback,
.tr-altjump__fallback {
	font-size: var(--font-size-xs);
}

/* =========================================================================
   1. WHAT IS {ANCHOR}? — prose beside one small fact panel (brief 7)

   Not a card. The prose is not inside anything, and the panel on the right is the
   only bordered surface in the section — which is what stops this from being the
   "giant content card" brief 7 rules out.
   ========================================================================= */

/*
 * ONE COLUMN. This was `minmax(0, 1fr) 300px` with the "{Tool} at a glance" panel
 * in the second track; C-74 removed that panel as a duplicate of the rail's "Tool
 * information" card, and the section now runs inside the reading column with the
 * rail beside it — so a second track here would be a column inside a column.
 */
.tr-anchor {
	min-width: 0;
}

.tr-anchor__prose {
	min-width: 0;
}

.tr-anchor__identity {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	margin-bottom: var(--space-5);
}

.tr-anchor__mark {
	display: grid;
	place-items: center;
	flex: 0 0 auto;
	width: var(--tr-altpage-mark);
	height: var(--tr-altpage-mark);
	border: var(--tr-altpage-hairline);
	border-radius: var(--radius-md);
	background: var(--color-bg-primary);
	overflow: hidden;
}

.tr-anchor__mark img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	padding: 5px;
}

.tr-anchor__mark--initials {
	font-size: var(--font-size-sm);
}

.tr-anchor__ident-text {
	display: flex;
	flex-direction: column;
	min-width: 0;
}

.tr-anchor__name {
	font-size: var(--font-size-lg);
	font-weight: var(--font-weight-bold);
	line-height: 1.2;
	color: var(--color-text-primary);
}

.tr-anchor__label {
	font-size: var(--font-size-xs);
	font-weight: var(--font-weight-medium);
	letter-spacing: 0.03em;
	text-transform: uppercase;
	color: var(--color-text-tertiary);
}

/*
 * `.tr-anchor__why` IS GONE. The block it styled moved out of this section in C-74
 * into its own `#why` section with its own `h2` — see `.tr-altwhy` further down.
 */

.tr-anchor__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-4);
	margin-top: var(--space-6);
}

/*
 * `.tr-anchor__panel`, `__panel-title`, `__facts` and `__fact` ARE DELETED. The
 * "{Tool} at a glance" panel they drew was four-fifths a restatement of the rail's
 * "Tool information" card; its one unique row moved into that card. Git history is
 * the recovery mechanism (CLAUDE.md, "Dead styles are deleted, not archived").
 */

/* =========================================================================
   1b. WHY CHOOSE {ANCHOR} AI ALTERNATIVES? — `tr-altwhy`

   NOT A CARD, NOT A GRID, NOT AN ICON LIST. This section sits between two of the
   heaviest objects on the page — a two-column overview with a bordered fact panel
   above it, a five-column scrolling table below it — and a third boxed thing
   between them is the "every section a different background" failure this template
   has twice been corrected for. Its whole treatment is a measure, a bold lead-in
   and the space between rows.

   ONE COLUMN AT THE READING MEASURE, deliberately, where the section above it is
   two. Five one-line reasons in two columns would be a matrix a reader has to
   choose a path through; in a single file they are read in the order they are
   ranked.
   ========================================================================= */

.tr-altwhy {
	max-width: var(--tr-altpage-measure);
}

.tr-altwhy__intro {
	margin-bottom: var(--space-6);
}

/*
 * `.tr-altwhy__list` CARRIES NO RULES OF ITS OWN. It is the shared `tr-pairs`
 * block — icon plate, title, sentence beneath — and the class is only here as a
 * hook in case this section ever needs to differ from the same block in the
 * reviews below. Its former `__item` / `__lead` / `__text` rules (a 2px left rule
 * with the lead-in set inline) are deleted with the markup that used them.
 */

/* =========================================================================
   2. THE LAYOUT — main column + 340px rail (brief 8, 10)

   The comparison single's `tr-cmp__layout` and the tool single's
   `tr-toolpage__layout`, both `minmax(0, 1fr) 340px` with `align-items: start`.

   `align-items: start` is what makes the sticky rail work at all: a stretched grid
   item is as tall as its row, and a sticky element that fills its own containing
   block has nowhere to travel.
   ========================================================================= */

.tr-altpage__layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 340px;
	gap: clamp(1.75rem, 3vw, 3rem);
	align-items: start;
}

.tr-altpage__main {
	min-width: 0;
}

.tr-altrail {
	display: flex;
	flex-direction: column;
	gap: var(--space-5);
	min-width: 0;
	padding-block-end: 40px;
	/*
	 * Its own gutter, since the container no longer supplies one — the comparison
	 * rail's exact rule. Stacked below 1025px it needs both sides; beside the main
	 * column it needs only the outer one, and the layout's `gap` provides the inner
	 * (see the sticky block).
	 */
	padding-inline: var(--space-5);
}

/*
 * THE RAIL PINS above 1024px only.
 *
 * Below that the layout is a single column and a sticky rail would pin a stack of
 * widgets over the reviews themselves.
 *
 * NO HEIGHT GUARD AND NO INNER SCROLLER, and both were tried on the sibling pages
 * before this. A `min-height` gate calculated from the widgets' expected heights
 * silently disabled the feature on every laptop; a `max-height` + `overflow-y: auto`
 * bound put a second scrollbar down the inside edge of a 340px column, so a wheel
 * over the rail moved the wrong thing. So it pins, and on a viewport too short to
 * show the whole rail the last widget is simply below the fold while pinned —
 * reachable the moment the reader scrolls past the layout, which is where the rail
 * releases. That is the normal behaviour of a sidebar taller than a window.
 *
 * The site's own `overflow-x: clip` on the page wrapper matters here too: the theme
 * chose `clip` over `hidden` precisely so it does not become a scroll container and
 * break sticky descendants. This rail depends on that.
 *
 * NOTHING FOLLOWS THE RAIL IN ITS COLUMN — the five discovery bands are outside the
 * layout entirely, so the standing rule about sticky siblings is satisfied.
 */
@media (min-width: 1025px) {
	.tr-altpage__layout .tr-altrail.sidebar-base--sticky {
		/*
		 * The rail starts where the CONTENT starts. Both columns are grid items on the
		 * same row, but the main column's first section carries the 40px every section
		 * carries, so without this the first widget sat 40px above the comparison table
		 * and the two columns began at different heights.
		 *
		 * MARGIN rather than padding: a sticky element's `top` measures its MARGIN
		 * edge, so padding here would scroll away as it pins while margin keeps the two
		 * columns aligned at rest and pins correctly in motion. The comparison rail's
		 * own reasoning, and its own three declarations.
		 */
		margin-block-start: 40px;
		padding-inline-start: 0;
		position: sticky;
		top: calc(var(--tr-altpage-chrome) + var(--space-5));
	}
}

/* =========================================================================
   RAIL WIDGETS

   The card chrome is the shared `sidebar-base` shell's. What is set here is the two
   bodies this page supplies as `html`, and the `--bare` modifier that stops the
   shell wrapping a component which already draws its own card.
   ========================================================================= */

.tr-altrail__widget--bare {
	padding: 0;
	border: 0;
	background: none;
}

/*
 * BOTH OF THE JUMP WIDGET'S OWN RULES ARE DESKTOP-ONLY, and the shared boundary is
 * 1025px — the width at which `.tr-altpage__layout` still has two columns and the
 * rail is still a 340px pinned column. Below it the rail is a full-width block
 * stacked after the article, where neither rule makes sense.
 */
@media (min-width: 1025px) {
	/*
	 * THE JUMP WIDGET'S BODY RUNS EDGE TO EDGE INSIDE THE CARD.
	 *
	 * Its rows are full-width hit targets with their own padding and their own
	 * active state, so the shell's 20px inline padding would inset a highlighted row
	 * from the card's border by 20px on each side and the state would read as a
	 * floating chip rather than as a selected row. The block padding stays: the
	 * heading above still needs its air, and so does the last row above the card's
	 * edge.
	 *
	 * A NEGATIVE MARGIN, not `padding: 0` on the widget — the widget's own title
	 * lives in the same box and has to keep the shell's inset.
	 */
	.tr-altrail__widget--jump .tr-altjump {
		margin-inline: calc(var(--space-5) * -1 + var(--space-1));
	}

	/*
	 * NO CAP AND NO SCROLLER. One was tried — `max-height: min(52vh, 460px)` with
	 * `overflow-y: auto`, on the argument that a fifteen-tool page would push the
	 * widgets under it off the fold. It is removed: a scrollbar inside a pinned card
	 * inside a scrolling page is three nested scroll surfaces, the wheel picks the
	 * wrong one, and the list stops showing how many alternatives the page has —
	 * which is the one thing an index is for. The list runs its natural height and
	 * the rail is as tall as it is.
	 */
}

/*
 * BELOW 1025 THE ROWS GO TWO ABREAST. The rail is the full page measure there, so
 * nine 40px rows in a single file is 360px of list for eight short names — and a
 * list that tall is the reason the widgets under it are never reached. Two columns
 * halve it without shrinking a single hit target.
 *
 * `auto-fill` with a 200px floor, so a 360px phone gets one column back rather than
 * two 170px ones with every name wrapped.
 */
@media (max-width: 1024px) {
	.tr-altrail__widget--jump .tr-altjump__list {
		grid-template-columns: repeat(auto-fill, minmax(min(100%, 200px), 1fr));
		gap: 2px var(--space-3);
	}
}

/*
 * THE ANCHOR'S FACT CARD IS `tr-toolfacts` NOW, and its rules live in
 * assets/css/shared-blocks.css.
 *
 * `.tr-altfacts` was this page's own label/value/chip list. The TOOL single's rail
 * carries the identical widget, titled "Tool information", from its own page
 * stylesheet — two implementations of one card one click apart. C-74 made this page
 * render that component instead; see inc/shared-blocks.php for why the parent's
 * copy could not simply be enqueued here, and template-parts/alternative/rail.php
 * for the rows.
 */

/* "About this guide" — the byline, the dates and the freshness line — MOVED to
   `assets/css/shared-blocks.css` in C-76, where the List rail can reach it too.
   This file declares that sheet as a dependency, so the rules still print first
   and this page is unchanged. */

/* =========================================================================
   3. THE COMPARISON TABLE and 4. THE JUMP LIST MOVED (C-76).

   `tr-alttable` and `tr-altjump` now live in `assets/css/shared-blocks.css`,
   because the List single draws both and could not reach them inside this
   65 KB page stylesheet. This file already declares that sheet as a dependency,
   so the rules still print before anything here and the alternatives page is
   unchanged — verified by measuring the table's computed box, header, row and
   cell before and after the move.

   Page-scoped rules for these components that are NOT shared stay in this file:
   the `.tr-altrail__widget--jump` wrappers, the grouped `__fallback` rule and
   the reduced-motion entry. They dress the component for THIS rail; the
   component itself is shared.
   ========================================================================= */


/* =========================================================================
   5. THE PRICING FILTER
   ========================================================================= */

.tr-altfilter {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-2);
	margin-bottom: var(--space-8);
}

.tr-altfilter__btn {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	min-height: 36px;
	padding: 0 var(--space-3);
	border: var(--tr-altpage-hairline);
	border-radius: var(--radius-full);
	background: transparent;
	font-size: var(--font-size-sm);
	font-weight: var(--font-weight-medium);
	color: var(--color-text-secondary);
	cursor: pointer;
	transition: var(--transition-fast);
}

.tr-altfilter__btn:hover {
	border-color: var(--color-primary);
	color: var(--color-text-primary);
}

.tr-altfilter__btn.is-active {
	background: var(--color-primary);
	border-color: var(--color-primary);
	color: var(--color-text-on-brand, #ffffff);
}

.tr-altfilter__count {
	font-size: var(--font-size-xs);
	font-variant-numeric: tabular-nums;
	opacity: 0.7;
}

/* =========================================================================
   6. THE DETAILED REVIEWS — `tr-altentry` (brief 14-26)

   ONE COLUMN AT FULL MEASURE. Spacing and a single rule separate the entries; no
   entry is a card, and no block inside one is a card either. That is the whole
   correction: the shape C-64 was right to reject was three NESTED bordered surfaces
   per entry, and the answer to that is fewer surfaces, not less content.
   ========================================================================= */

.tr-altlist {
	margin: 0;
	padding: 0;
	list-style: none;
}

.tr-altentry {
	/* Generous, and deliberately more than the gap between page sections: the reader
	   has to be able to see where one review ends without a border doing it. */
	padding-block: var(--space-10);
	border-top: var(--tr-altpage-hairline);
}

.tr-altentry:first-child {
	border-top: 0;
	padding-block-start: 0;
}

.tr-altentry:last-child {
	padding-block-end: 0;
}

/*
 * THE HEAD (brief 15). Rank, mark, name — and it is a flex row rather than a grid
 * because the badge has to be able to sit hard right on a wide column and wrap under
 * the name on a narrow one.
 */
.tr-altentry__head {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	padding-block: var(--space-3);
	margin-bottom: var(--space-5);
	/*
	 * THE PAGE'S OWN GROUND, so the bar is INVISIBLE AT REST — and it still has to
	 * be a paint rather than `transparent`, because this bar is `position: sticky`
	 * and content scrolls UNDER a sticky element rather than being pushed by it.
	 * Transparent, the screenshot below would show through the tool's name while
	 * the bar is pinned.
	 *
	 * `--surface-base` is what `body` itself is painted with
	 * (theme-unified.css: `body { background-color: var(--surface-base) }`), so
	 * this matches the page in both themes by construction rather than by a value
	 * copied across. It replaces `--color-bg-primary` (#0B0F17), which is one step
	 * LIGHTER than the page (#070B12) and therefore drew a visible band behind
	 * every entry's rank and name.
	 */
	background: var(--surface-base);
	border-bottom: var(--tr-altpage-hairline);
}

/*
 * THE HEAD PINS while its own review is on screen (brief 16).
 *
 * `position: sticky` pins within the PARENT's box, and the parent here is the `<li>`
 * — so the bar travels down its own review and RELEASES exactly where that review
 * ends. It cannot ride into the next entry, which is what makes this safe without a
 * scroll listener, an IntersectionObserver or any script at all.
 *
 * `top` clears the site header and the section nav, so the three never overlap
 * (brief 48). `z-index: 3` keeps it above its own review's screenshot and prose while
 * staying far below the section nav's own `--tiorai-secnav-z: 190`, so the page-level
 * strip always wins.
 *
 * AN OPAQUE BACKGROUND IS LOAD-BEARING, not decoration: content scrolls UNDER a
 * sticky element rather than being pushed by it, so a transparent bar would show the
 * screenshot through the tool's name.
 *
 * DESKTOP ONLY. On a phone the header, the nav strip and a pinned entry bar would
 * take a third of the viewport between them, which is the crowding brief 16 and 46
 * both say to disable rather than preserve.
 */
@media (min-width: 1025px) {
	.tr-altentry__head {
		position: sticky;
		top: var(--tr-altpage-chrome);
		z-index: 3;
	}
}

.tr-altentry__rank {
	flex: 0 0 auto;
	font-size: var(--font-size-xl);
	font-weight: var(--font-weight-bold);
	font-variant-numeric: tabular-nums;
	line-height: 1;
	letter-spacing: -0.02em;
	color: var(--color-primary);
}

.tr-altentry__mark {
	display: grid;
	place-items: center;
	flex: 0 0 auto;
	width: var(--tr-altpage-mark);
	height: var(--tr-altpage-mark);
	border: var(--tr-altpage-hairline);
	border-radius: var(--radius-md);
	background: var(--color-bg-primary);
	overflow: hidden;
}

.tr-altentry__mark img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	padding: 5px;
}

.tr-altentry__mark--initials {
	font-size: var(--font-size-sm);
}

.tr-altentry__title {
	margin: 0;
	min-width: 0;
	flex: 1 1 auto;
	font-size: var(--font-size-2xl);
	font-weight: var(--font-weight-bold);
	line-height: 1.2;
	letter-spacing: -0.02em;
	color: var(--color-text-primary);
}

.tr-altentry__title a {
	color: inherit;
	text-decoration: none;
}

.tr-altentry__title a:hover,
.tr-altentry__title a:focus-visible {
	color: var(--color-primary);
	text-decoration: underline;
	text-underline-offset: 4px;
}

.tr-altentry__badge {
	flex: 0 0 auto;
	padding: 4px var(--space-3);
	border-radius: var(--radius-full);
	background: var(--tiorai-badge-bg-brand, var(--color-bg-tertiary));
	font-size: var(--font-size-xs);
	font-weight: var(--font-weight-semibold);
	letter-spacing: 0.02em;
	color: var(--color-text-primary);
}

/* The vendor, the price and the category — one quiet line under the head. */
.tr-altentry__tags {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--space-2) var(--space-4);
	margin: 0 0 var(--space-5);
	font-size: var(--font-size-sm);
	color: var(--color-text-tertiary);
}

.tr-altentry__price {
	font-weight: var(--font-weight-semibold);
	color: var(--color-text-primary);
	font-variant-numeric: tabular-nums;
}

.tr-altentry__plan-name {
	font-weight: var(--font-weight-normal);
	color: var(--color-text-tertiary);
}

.tr-altentry__cat {
	color: var(--color-text-tertiary);
}

/*
 * THE SCREENSHOT (brief 17). Full width of the reading column, 16:10, with
 * `object-position: top` so the crop keeps the part of a product UI that identifies
 * it. C-64 had this at a fixed 260px in a side column.
 */
.tr-altentry__shot {
	position: relative;
	margin: 0 0 var(--space-6);
	border: var(--tr-altpage-hairline);
	border-radius: var(--radius-xl);
	overflow: hidden;
	background: var(--color-bg-secondary);
}

.tr-altentry__shot-img {
	display: block;
	width: 100%;
	aspect-ratio: 16 / 10;
	object-fit: cover;
	object-position: top;
}

.tr-altentry__zoom {
	position: absolute;
	inset-block-end: var(--space-3);
	inset-inline-end: var(--space-3);
	display: grid;
	place-items: center;
	width: 36px;
	height: 36px;
	padding: 0;
	border: var(--tr-altpage-hairline);
	border-radius: var(--radius-full);
	background: var(--color-bg-primary);
	color: var(--color-text-secondary);
	cursor: pointer;
	opacity: 0;
	transition: var(--transition-fast);
}

.tr-altentry:hover .tr-altentry__zoom,
.tr-altentry__zoom:focus-visible {
	opacity: 1;
}

/* Touch has no hover, so the control is always visible there. */
@media (hover: none) {
	.tr-altentry__zoom {
		opacity: 1;
	}
}

.tr-altentry__summary {
	margin: 0 0 var(--space-5);
	max-width: var(--tr-altpage-measure);
	font-size: var(--font-size-base);
	line-height: 1.7;
	color: var(--color-text-secondary);
}

/*
 * BEST FOR and the vs line (brief 19, 20). Two labelled single-line facts, sharing
 * one treatment: an uppercase label and a value. They read as a pair because they
 * are a pair — what this tool is for, and how it differs from the one being replaced.
 */
.tr-altentry__bestfor,
.tr-altentry__diff {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--space-2) var(--space-3);
	margin: 0 0 var(--space-3);
	max-width: var(--tr-altpage-measure);
	font-size: var(--font-size-sm);
	line-height: 1.6;
}

.tr-altentry__diff {
	margin-bottom: var(--space-7);
}

.tr-altentry__label {
	flex: 0 0 auto;
	font-size: var(--font-size-xs);
	font-weight: var(--font-weight-semibold);
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--color-text-tertiary);
}

.tr-altentry__bestfor-value {
	font-weight: var(--font-weight-semibold);
	color: var(--color-text-primary);
}

.tr-altentry__diff-value {
	color: var(--color-text-secondary);
}

/*
 * THE THREE BLOCKS — features, pros/cons, use cases (brief 21, 22, 23).
 *
 * NOT CARDS. Each is a section with a heading and a left inset rule, which groups it
 * as clearly as a border would while keeping the entry to ONE surface. C-64's note
 * that "a card inside a card is always wrong" is correct and is honoured here; what
 * it got wrong was concluding that the content had to go with the cards.
 */
.tr-altentry__block {
	margin-bottom: var(--space-7);
}

/*
 * NO TYPE OVERRIDES. This is an `<h4>` and it now takes the theme's own `h4`
 * (theme-unified.css: `--font-size-xl` / `--font-weight-semibold`) rather than
 * being pushed down to `--font-size-base`. Only the margin and the ink are set
 * here, and both are position rather than typography.
 */
.tr-altentry__block-title {
	margin: 0 0 var(--space-4);
	color: var(--color-text-primary);
}

/*
 * THE THREE BLOCKS' BODIES ARE THE SHARED COMPONENTS NOW (C-74).
 *
 * `.tr-altentry__features` / `__cases` were a two-column list of items with a 2px
 * left rule each; `.tr-altentry__pc*` was two columns of `+` and `−` glyph bullets.
 * The COMPARISON single draws the same three objects — a named thing with a
 * sentence under it, and two labelled lists of claims — as `tr-pairs` and `tr-pc`,
 * with a tinted 32px plate per row. A reader meets both pages one click apart and
 * the two treatments did not look related.
 *
 * Every rule that drew them is deleted rather than kept alongside. What is left
 * here is only what this page's WIDTH requires, and both are the components' own
 * documented opt-ins rather than overrides of them:
 *
 *   --tr-pairs-columns   two, because the reading column is ~836px and six short
 *                        definitions in single file is a screen of scrolling. The
 *                        comparison stays at one inside its ~360px column.
 *   .tr-pc--split        the two lists side by side, same argument.
 *
 * The measure cap applies to both: a features row is a title and a sentence, and a
 * sentence set to 836px is past the readable measure the rest of this column holds.
 */
.tr-altentry__pairs {
	--tr-pairs-columns: 2;

	max-width: var(--tr-altpage-measure);
}

.tr-altentry__block--pc .tr-pc {
	max-width: var(--tr-altpage-measure);
}

.tr-altentry__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-3);
	margin-top: var(--space-7);
}

.tr-altlist__empty {
	margin: var(--space-10) 0 0;
	padding: var(--space-8);
	border: 1px dashed var(--border-default);
	border-radius: var(--radius-lg);
	text-align: center;
	color: var(--color-text-tertiary);
}

/* =========================================================================
   7. WHICH ONE IS RIGHT FOR YOU — `tr-altpicks`

   A two-column definition list with a rule between rows. NOT a card grid, and that
   is the whole design decision: this sits between nine reviews and four card bands,
   and another bordered surface in that position is what turned the page it replaces
   into one repeated shape. The situation is the term, the tool and its own sentence
   are the definition.
   ========================================================================= */

.tr-altpicks {
	margin: 0;
	border-top: var(--tr-altpage-hairline);
}

.tr-altpicks__row {
	display: grid;
	grid-template-columns: minmax(0, 13rem) minmax(0, 1fr);
	gap: var(--space-4) var(--space-8);
	padding-block: var(--space-5);
	border-bottom: var(--tr-altpage-hairline);
}

/* The situation. Sized down and weighted up: it is a label, not a heading. */
.tr-altpicks__case {
	margin: 0;
	font-size: var(--font-size-sm);
	font-weight: var(--font-weight-semibold);
	line-height: 1.4;
	color: var(--color-text-primary);
}

.tr-altpicks__answer {
	margin: 0;
	min-width: 0;
}

.tr-altpicks__tool {
	margin: 0 0 var(--space-1);
}

.tr-altpicks__link {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	/* ≥24px tall including the tile, so the row is a WCAG 2.2 AA target. */
	padding-block: var(--space-1);
	font-weight: var(--font-weight-semibold);
	color: var(--color-text-primary);
	text-decoration: none;
}

.tr-altpicks__link:hover,
.tr-altpicks__link:focus-visible {
	color: var(--color-primary);
}

.tr-altpicks__mark {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 24px;
	height: 24px;
	border: var(--tr-altpage-hairline);
	border-radius: var(--radius-base);
	overflow: hidden;
	background: var(--color-bg-primary);
}

.tr-altpicks__mark img {
	width: 100%;
	height: 100%;
	object-fit: contain;
}

.tr-altpicks__mark--initials,
.tr-altpicks__fallback {
	font-size: var(--font-size-xs);
}

.tr-altpicks__text {
	margin: 0;
	max-width: var(--tr-altpage-measure);
	font-size: var(--font-size-sm);
	line-height: 1.65;
	color: var(--color-text-secondary);
}

/* =========================================================================
   7b. THE SHARE ROW — the shared `tr-share-row`, unboxed here (brief 10)

   THE COMPONENT DRAWS A RULE ABOVE AND A RULE BELOW ITSELF
   (assets/css/unified/share-row.css: `border-top` + `border-bottom` on
   `.tr-share-row`). On the three pages it was built for — Resource, Glossary,
   Prompt — that is right: it closes a single body of prose and the rules are the
   only thing separating it from what follows.

   ON THIS PAGE IT IS THE FIFTH HORIZONTAL RULE IN 400px. The reading column above
   it ends with the picks table, which already draws a rule per row; every
   `.tr-altpage__section` after the first draws its own hairline; and the first
   discovery band immediately below draws `border-block-start`. The share row sat
   boxed between two of those, reading as a bordered panel someone had inserted
   rather than as the end of the article.

   SO THE RULES COME OFF AND THE SPACE STAYS. `padding-block` is untouched, and
   `margin-block` is untouched — the separation is entirely vertical space now,
   which is what §13 asks for and what the sections above it already do.

   SCOPED TO `.tr-altpage__share`, the class this page passes to the shared part.
   Nothing here reaches the component's other three consumers.
   ========================================================================= */

.tr-altpage__share {
	border-block: 0;

	/*
	 * AND THE GUTTER EVERY SIBLING HAS. `.tr-share-row` is a direct child of
	 * `.tr-altpage__main` but it is not a `.tr-altpage__section`, so it never
	 * picked up that class's `padding-inline` — measured: the three sections above
	 * it inset their content by 20px and the share row's heading and button box
	 * started 20px further out, flush with the column edge. The borders used to
	 * frame that as a deliberate full-width band; with them gone it just reads as
	 * a row that lost its padding.
	 *
	 * Padding rather than margin, so the row's own background (it has none today)
	 * would still span the column if it ever gains one.
	 */
	padding-inline: var(--space-5);
}

/* =========================================================================
   8. THE FIVE DISCOVERY BANDS (brief 28-38)

   Full measure, below the layout, so the rail has ended before the first one starts.
   Each opens with the shared centred `tr-section-head` and scrolls the shared cards
   in the child's `tr-shelf` over the parent's `tr-carousel`.

   What is set here is the RHYTHM and the per-band card count. Everything else — the
   arrows, their disabled states, the snapping, the edge fades, the cards themselves —
   belongs to the components.
   ========================================================================= */

/*
 * The bands keep a deeper rhythm than the reading sections — `--space-12` against 40px
 * — because they are full-bleed and separated by a border rather than by a hairline
 * inset to the measure. That is the comparison page's own split too:
 * `.tr-cmp-section--related` takes `padding-block: var(--space-12)` where its reading
 * sections take 40px.
 */
.tr-altpage__band {
	padding-block: var(--space-12);
	border-block-start: var(--tr-altpage-hairline);
}

/* The gutter, on the band's container, matching every other row on the page. */
.tr-altpage__band > .tr-altpage__container {
	padding-inline: var(--space-5);
}

/*
 * The band surfaces alternate. Not decoration: five consecutive full-width card rows
 * read as one endless strip otherwise, and a tint every other band gives the eye a
 * boundary without a heavier rule between them.
 */
.tr-altpage__band--tools,
.tr-altpage__band--related {
	background: var(--color-bg-secondary);
}

.tr-altpage__band .tr-sectionhead {
	margin-bottom: var(--space-10);
}

/*
 * PER-BAND CARD COUNTS. `--tiorai-carousel-visible` is the shared carousel's own
 * knob, so these are configuration rather than overrides. The counts differ because
 * the cards do: `tr-tools-card` is the narrowest of the four, `tr-vs-card` carries
 * two logos and a medallion side by side and needs the most room.
 */
/*
 * THE ARROWS GET A LANE, and the two tokens below are what make `tr-shelf--lane`
 * work on a page that is not an archive.
 *
 * Without the lane the component pins its arrow discs INSIDE the track, over the
 * first and last card — measured here: the left disc sat on top of "Poe AI models
 * comparison: Full Comparison 2026" and clipped the title. `/compare/` hit the same
 * thing and solved it in C-67/C-68 with this modifier, which pulls the shelf out to
 * the container gutter and pads a 64px lane back in, so the discs sit on the page
 * ground BESIDE the cards. Reusing it is the point (brief 44); a second set of arrow
 * offsets here would be the fork CLAUDE.md 9.3 rules out.
 *
 *   --tiorai-archive-gutter  the lane's negative margin resolves against this. It is
 *                            declared by the ARCHIVE SHELL, which this page is not,
 *                            so without a value here the margin computes to zero and
 *                            the arrows sit back on the cards — the exact thing the
 *                            lane exists to prevent. Same reason compare-single.css
 *                            declares it for its own two bands.
 *   --tiorai-carousel-fade   the colour the partial-card gradient dissolves TO. The
 *                            component's default names the archive's intro surface,
 *                            and a fade to the wrong colour is a visible vertical
 *                            seam down both edges of the row. Below 1025px the lane
 *                            is off and the fades are live, so this matters at
 *                            exactly the widths the lane does not cover.
 */
.tr-altpage__shelf {
	--tiorai-carousel-gap: var(--space-5);
	--tiorai-archive-gutter: var(--space-5);
	--tiorai-carousel-fade: var(--color-bg-primary);
}

/* The two tinted bands fade to their own ground, not to the page's. */
.tr-altpage__band--tools .tr-altpage__shelf,
.tr-altpage__band--related .tr-altpage__shelf {
	--tiorai-carousel-fade: var(--color-bg-secondary);
}

.tr-altpage__shelf--compare,
.tr-altpage__shelf--lists,
.tr-altpage__shelf--related {
	--tiorai-carousel-visible: 3;
}

.tr-altpage__shelf--tools {
	--tiorai-carousel-visible: 4;
}

/*
 * Cards fill their cell, so a shelf of cards with different body lengths is a row of
 * equal-height cards rather than a ragged one. The shelf item is a flex cell of a
 * fixed width; this makes its single child fill it.
 */
.tr-altpage__shelf .tr-shelf__item > * {
	height: 100%;
}

/* =========================================================================
   A SHORT BAND IS CENTRED (brief 11)

   THE PROBLEM, MEASURED ON THIS PAGE. The bands are sized in CARDS, not in
   fractions: `--tiorai-carousel-visible` is 3 or 4, so a track that holds four
   1,264px-wide slots and is given two cards leaves half the row empty on the right.
   `/alternatives/poe-alternatives/` renders 6 head-to-heads, 2 tools, 1 list and 4
   guides — three of its five bands are short, and each of them read as a row that
   had failed to load rather than as a row with two things in it.

   `justify-content: safe center` IS THE WHOLE FIX, and the `safe` keyword is why
   this is not the trap it looks like. On a track that DOES overflow, plain `center`
   pushes the overflow equally to both sides and the left-hand cards end up at a
   negative scroll offset that a scroll container cannot reach — the first card
   becomes permanently unreachable. `safe` tells the browser to fall back to
   `flex-start` in exactly that case, so a full band scrolls from its first card
   as before and only a short one centres.

   Browsers without `safe` (pre-93 Chrome, pre-15.4 Safari) drop the declaration
   entirely and keep `flex-start`, which is today's behaviour. There is no
   `justify-content: center` fallback anywhere here on purpose: falling back to the
   unsafe value would trade a cosmetic gap for an unreachable card.

   THE CARDS THEMSELVES ARE UNTOUCHED. This centres the GROUP inside the track; it
   sets no width, no text alignment and no per-card rule, so a two-card band is the
   same two cards the four-card band draws (brief 12).
   ========================================================================= */

.tr-altpage__shelf .tr-shelf__track {
	justify-content: safe center;
}

/*
 * THE CATEGORY GRID, same problem and a different mechanism. `tr-catnav__grid` is
 * `repeat(var(--tiorai-catnav-columns), minmax(0, 1fr))`, so one term becomes one
 * tile stretched across a quarter of the page with three empty columns beside it.
 *
 * `auto-fit` with a MAX as well as a min is what lets the tracks size to their
 * content instead of dividing the row, and `justify-content: center` then centres
 * however many there are. Safe is not needed: a grid row wraps rather than
 * overflowing, so there is no unreachable-content case to guard against.
 *
 * Scoped to `.tr-altpage__catnav` — the class this page passes the shared component
 * — so `/tools/` and `/alternatives/` keep the fixed grid they are designed around.
 */
.tr-altpage__catnav .tr-catnav__grid {
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 300px));
	justify-content: center;
}

/*
 * And its trailing "All categories" link with it. The component left-aligns it,
 * which is correct under a full-width archive grid and wrong under a centred group
 * of one tile — it read as an orphan in the bottom-left corner of the band. Every
 * other band on this page closes with a centred link (`.tr-altpage__band-foot`).
 */
.tr-altpage__catnav .tr-catnav__more {
	text-align: center;
}

/*
 * TWO CLASSES ON PURPOSE. These have to beat the per-band single-class rules above
 * AND `tr-shelf`'s own responsive steps, so they are scoped to the band. At equal
 * specificity source order would decide it, and this file's order relative to
 * shelf.css is set by an enqueue dependency rather than by anything visible here.
 */
@media (max-width: 1200px) {
	.tr-altpage__band .tr-altpage__shelf--tools {
		--tiorai-carousel-visible: 3;
	}
}

@media (max-width: 1024px) {
	.tr-altpage__band .tr-altpage__shelf {
		--tiorai-carousel-visible: 2.3;
	}
}

@media (max-width: 640px) {
	.tr-altpage__band .tr-altpage__shelf {
		--tiorai-carousel-gap: var(--space-4);
		--tiorai-carousel-visible: 1.15;
	}
}

.tr-altpage__band-foot {
	margin: var(--space-8) 0 0;
	text-align: center;
}

.tr-altpage__band-all {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	font-size: var(--font-size-sm);
	font-weight: var(--font-weight-semibold);
	color: var(--color-primary);
	text-decoration: none;
}

.tr-altpage__band-all:hover,
.tr-altpage__band-all:focus-visible {
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* =========================================================================
   THE PARENT SCRIPT'S LIGHTBOX
   modules/alternative/assets/js/alternative.js appends this overlay to <body>
   unconditionally once the grid is found, so it needs a resting state here or it
   would render as a stray block at the end of the document. Restyled rather than
   re-implemented — see inc/alternative-single.php on why the script is reused.
   ========================================================================= */

.alt-lightbox {
	position: fixed;
	inset: 0;
	z-index: 9999;
	display: none;
	place-items: center;
	padding: var(--space-8);
	background: rgb(0 0 0 / 0.82);
}

.alt-lightbox.is-open {
	display: grid;
}

.alt-lightbox__inner {
	max-width: min(1100px, 92vw);
}

.alt-lightbox__img {
	display: block;
	max-width: 100%;
	max-height: 78vh;
	border-radius: var(--radius-lg);
}

/*
 * The one literal colour in this file, and it is deliberate rather than an oversight
 * of CLAUDE.md 9.5.
 *
 * This caption sits on `rgb(0 0 0 / 0.82)` — a scrim that is BLACK IN BOTH THEMES,
 * because a lightbox exists to remove the page from view. Every text token that could
 * go here is theme-reactive: `--color-text-secondary` is #475569 in light, which is
 * unreadable on black, and the gray scale is explicitly INVERTED between themes
 * (DESIGN.md 1.7), so `--color-gray-200` would flip to a dark value exactly where it
 * must not. A fixed near-white is the only value that is correct on a fixed dark
 * ground.
 */
.alt-lightbox__caption {
	margin: var(--space-3) 0 0;
	text-align: center;
	font-size: var(--font-size-sm);
	color: #e2e8f0;
}

.alt-lightbox__close {
	position: absolute;
	inset-block-start: var(--space-5);
	inset-inline-end: var(--space-5);
	display: grid;
	place-items: center;
	width: 40px;
	height: 40px;
	padding: 0;
	border: 1px solid rgb(255 255 255 / 0.25);
	border-radius: var(--radius-full);
	background: rgb(255 255 255 / 0.08);
	color: #ffffff;
	cursor: pointer;
}

.alt-lightbox__close:hover {
	background: rgb(255 255 255 / 0.16);
}

/* =========================================================================
   RESPONSIVE (brief 46, 47)

   The breakpoints are the theme's canonical six (CLAUDE.md, Breakpoint Standard) and
   the complement pairs are N / N+1: the rail and both sticky behaviours are gated at
   `min-width: 1025px`, and everything that collapses does so at `max-width: 1024px`.
   ========================================================================= */

@media (max-width: 1024px) {
	/*
	 * ONE COLUMN, RAIL LAST. The rail's widgets are page furniture — share,
	 * provenance, was-this-useful — so below the reviews is where they belong on a
	 * phone. Putting them above would push the comparison table a screen down.
	 */
	.tr-altpage__layout {
		grid-template-columns: minmax(0, 1fr);
	}

	.tr-altpage__hero-grid {
		grid-template-columns: minmax(0, 1fr);
	}

	/*
	 * THE SCREENSHOT GOES AFTER THE TEXT in the hero. A phone should reach "Visit
	 * {tool}" without scrolling past a 16:10 image first — the tool page's own rule.
	 * `order` is safe here because the two are siblings in a one-column grid and the
	 * DOM order already puts the actions before the figure, so nothing reorders
	 * relative to the tab sequence.
	 */
	.tr-altpage__hero-shot {
		order: 2;
	}

	.tr-anchor {
		grid-template-columns: minmax(0, 1fr);
	}

	.tr-altpicks__row {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--space-2);
	}
}

@media (max-width: 768px) {
	.tr-altpage__hero {
		padding-block: var(--space-5) var(--space-8);
	}

	/* The comparison hero's own step down, at the same breakpoint and to the same token. */
	.tr-altpage__title {
		font-size: var(--font-size-3xl);
		max-width: none;
	}

	.tr-altpage__band {
		padding-block: var(--space-12);
	}

	.tr-altentry {
		padding-block: var(--space-8);
	}

	/*
	 * The head wraps: rank and mark on one line with the name, the badge below. At
	 * 360px a badge like "Best open source" beside a two-word tool name leaves the
	 * name three characters wide.
	 */
	.tr-altentry__title {
		font-size: var(--font-size-xl);
	}

	.tr-altentry__badge {
		order: 3;
	}
}

@media (max-width: 640px) {
	/*
	 * THE PHONE STEP IS AT 640, NOT 768, because that is where
	 * `.tr-cmp .tr-cmp-section` takes its own — `padding-block: var(--space-8)` (32px)
	 * and `padding-inline: var(--space-4)` (16px), with the hairline inset to match.
	 * Measured before this block: at 390px the comparison's text started 16px from the
	 * edge and this page's started at 20px, and the vertical rhythm stepped down a
	 * breakpoint early.
	 */
	.tr-altpage__section,
	.tr-altpage__share {
		padding-inline: var(--space-4);
	}

	.tr-altpage__section {
		padding-block: var(--space-8);
	}

	.tr-altpage__main > * + .tr-altpage__section::before {
		inset-inline: var(--space-4);
	}

	.tr-altrail,
	.tr-altpage__band > .tr-altpage__container {
		padding-inline: var(--space-4);
	}

	.tr-altpage__hero-grid {
		padding-inline: var(--space-4);
	}

	.tr-altpage__highlights {
		gap: var(--space-3) var(--space-5);
	}

	/*
	 * The zoom control is removed rather than shrunk on a phone: the lightbox opens
	 * a `max-height: 78vh` image, which on a 375px-wide screen is very close to the
	 * screenshot already inline above it, so the control costs a tap target and
	 * returns nothing.
	 */
	.tr-altentry__zoom {
		display: none;
	}
}

/* =========================================================================
   MOTION
   ========================================================================= */

@media (prefers-reduced-motion: reduce) {
	.tr-altbtn,
	.tr-altbtn__icon,
	.tr-altentry__zoom,
	.tr-altfilter__btn,
	.tr-altjump__link {
		transition: none;
	}

	.tr-altbtn:hover .tr-altbtn__icon {
		transform: none;
	}

	/*
	 * The pinned bars are removed under reduced motion. A sticky element is
	 * continuous movement relative to the content behind it, which is exactly what
	 * this preference asks to be spared — and the page loses nothing structural,
	 * because the section nav's links and the jump list are both still there.
	 */
	.tr-altentry__head {
		position: static;
	}
}

/* =========================================================================
   PRINT
   ========================================================================= */

@media print {
	.tr-altpage__nav,
	.tr-altfilter,
	.tr-altrail,
	.tr-altpage__band,
	.tr-altentry__zoom,
	.alt-lightbox {
		display: none !important;
	}

	.tr-altpage__layout,
	.tr-altpage__hero-grid,
	.tr-anchor {
		display: block;
	}

	.tr-altentry {
		break-inside: avoid;
	}

	.tr-altentry__head {
		position: static;
	}
}
