.tsp-sidebar{display:flex;flex-direction:column;gap:var(--tsp-sidebar-gap,32px);width:100%}/* MANDATORY wrapper standard: container-type lives HERE, never on the section (see DEVELOPERS.md) */.tsp-sidebar-wrap{container-type:inline-size;width:100%}
.tsp-sidebar__section{display:flex;flex-direction:column;gap:14px}
.tsp-sidebar__heading{margin:0;padding-bottom:8px;border-bottom:2px solid var(--tsp-sidebar-accent-color,#ed1c24);font-weight:800;color:var(--tsp-sidebar-heading-color,#172033)}
.tsp-sidebar__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--tsp-sidebar-story-gap,14px)}
.tsp-sidebar__item{display:flex;gap:12px;align-items:flex-start}
/* v1.10.13: row thumbnails are landscape 4:3, not square. --tsp-sidebar-thumb is
   the WIDTH; height follows the ratio, so 96px -> 96x72. Grid, card and numbered
   override this rule at 0,2,0 and are deliberately unaffected. */
.tsp-sidebar__item-image{flex:0 0 var(--tsp-sidebar-thumb,96px);display:block;aspect-ratio:4/3;border-radius:6px;overflow:hidden;background:linear-gradient(135deg,#e9e6dd,#d8d4c8)}
/* v1.10.619 — the missing-image slot is PAPER, not a cool grey.
   This box was #eef1f4, a blue-grey, while every other empty image slot on
   the platform is the warm paper tone: .tsp-cat__ph on archives, Latest
   Stories and search, and --tsp-band-bg on the cross-edition strip. The
   divergence only shows while an image loads or when one is missing, which
   is exactly when the reader is looking at the box rather than the picture.
   Canonical value lives on .tsp-cat__ph in templates/assets/css/category.css;
   repeated literally here because this project has no token sheet by
   deliberate decision (the v1.11.0 token refactor was reverted).
   Deliberately NOT changed: the video card (#222) and the overlay card and
   review hero (dark gradients). Those carry white text or a play control and
   are dark by design, not by neglect. */
.tsp-sidebar__item-image img{width:100%;height:100%;object-fit:cover;display:block}
.tsp-sidebar__item-body{flex:1;min-width:0}
/* v1.10.13 SHARED STORY-TITLE CONTRACT - one rule, one class, all four sidebar
   blocks, all five layouts. The values are the modern News Grid standard card's
   own (blocks.css: .tsp-news-card h3 = 18px / 1.25, family and weight inherited
   from the theme heading, break-word). Layout-specific title sizes were REMOVED
   rather than out-specified, so no !important is needed and nothing outranks
   this. --tsp-sidebar-title-size keeps the "Story title size" control live. */
.tsp-sidebar__item-body .tsp-story-title{margin:0;line-height:1.25;overflow-wrap:break-word}
.tsp-sidebar__item-body .tsp-story-title a{color:var(--tsp-sidebar-title-color,#172033);text-decoration:none}
.tsp-sidebar__item-body .tsp-story-title a:hover{color:var(--tsp-sidebar-accent-color,#ed1c24)}
/* Meta matches the News Grid's .tsp-eb time (12px, weight and line-height left
   at the theme's). Colour stays on this block's own Meta colour control - the
   News Grid declares no meta colour, so there is no reference value to copy. */
.tsp-sidebar__item-body time{display:block;margin-top:4px;font-size:12px;color:var(--tsp-sidebar-meta-color,#667085)}
.tsp-sidebar-empty{padding:20px;border:1px dashed #ccd0d4;text-align:center;color:#667085;font-size:.9rem}
.tsp-sidebar-editor-preview{border:1px solid #dcdcde;padding:12px}
.tsp-sidebar-editor-preview__label{font-size:11px;font-weight:700;text-transform:uppercase;color:#646970;margin-bottom:8px}
.tsp-sidebar__section--compact .tsp-sidebar__list{gap:10px}
/* v1.10.13: compact's four own rules - 8px gap, a hardcoded 48px thumbnail that
   made the Thumbnail size control dead here, a .82rem title that made the Story
   title size control dead here, and .68rem meta - are removed. Compact is
   Latest Stories' default layout, so those four were the main reason the four
   sidebar blocks did not look like one system. It now uses the shared contract
   (18px/1.25 title, 12px meta, 96x72 thumbnail, 12px gap) like every other row
   layout. Only its tighter story spacing is layout-specific and kept above. */
.tsp-sidebar__section--numbered .tsp-sidebar__list{counter-reset:tsp-sidebar-rank}
.tsp-sidebar__section--numbered .tsp-sidebar__item{counter-increment:tsp-sidebar-rank}
/* Numbered has no image - the box holds the rank counter - so it keeps its
   square badge and its previous 76px sizing, per the v1.10.13 exclusion list. */
.tsp-sidebar__section--numbered .tsp-sidebar__item-image{position:relative;background:transparent;display:flex;flex:0 0 var(--tsp-sidebar-thumb,76px);aspect-ratio:1/1}
.tsp-sidebar__section--numbered .tsp-sidebar__item-image img{display:none}
.tsp-sidebar__section--numbered .tsp-sidebar__item-image::before{content:counter(tsp-sidebar-rank);display:flex;align-items:center;justify-content:center;width:100%;height:100%;font-size:1.6rem;font-weight:800;color:var(--tsp-sidebar-accent-color,#ed1c24);background:#f1f2f4}
.tsp-sidebar__section--grid .tsp-sidebar__list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
.tsp-sidebar__section--grid .tsp-sidebar__item{flex-direction:column;gap:8px}
.tsp-sidebar__section--grid .tsp-sidebar__item-image{flex:none;width:100%;aspect-ratio:4/3}
/* v1.10.13: grid's .8rem title cap removed - it uses the shared contract too.
   Grid keeps its own full-width 4:3 cell image (rule above), so it is excluded
   from the 96x72 row-thumbnail geometry, not from the typography. */
/* v1.10.178: `min()` rather than a flat 24px. This tier tightens the SECTION gap
   on narrow screens, and a literal value silently overrode any component that
   had already asked for something smaller — the Telugu strip's 10px came back as
   24px at 390px only. min() keeps the intent (never looser than 24 when narrow)
   while letting a smaller component value win. Default sidebars are unchanged:
   min(24px, 32px) is 24px, exactly what this rule did before. */
@container (max-width:520px){.tsp-sidebar{gap:min(24px, var(--tsp-sidebar-gap, 32px))}}

.editor-styles-wrapper .tsp-sidebar-editor-preview a{pointer-events:none}
.editor-styles-wrapper .tsp-sidebar-editor-preview{width:100%;padding:0;border:0;box-sizing:border-box}
.editor-styles-wrapper .tsp-sidebar-editor-preview__label{margin-bottom:8px}

/* C2: shared Section Heading styles */.tsp-section-heading{font-weight:800;line-height:1.25;margin:0 0 12px;color:var(--tsp-sidebar-heading-color,#172033);display:block}.tsp-section-heading--align-center{text-align:center}.tsp-section-heading--align-right{text-align:right}.tsp-section-heading--classic{border-bottom:2px solid var(--tsp-sidebar-accent-color,#ed1c24);padding-bottom:8px}.tsp-section-heading--modern span{background:linear-gradient(transparent 60%,rgba(237,28,36,.18) 60%)}.tsp-section-heading--underline span{border-bottom:3px solid var(--tsp-sidebar-accent-color,#ed1c24);padding-bottom:6px}.tsp-section-heading--accent-left{border-left:4px solid var(--tsp-sidebar-accent-color,#ed1c24);padding-left:10px}.tsp-section-heading--accent-bottom{position:relative;padding-bottom:10px}.tsp-section-heading--accent-bottom::after{content:'';position:absolute;left:0;bottom:0;width:44px;height:3px;background:var(--tsp-sidebar-accent-color,#ed1c24)}.tsp-section-heading--accent-bottom.tsp-section-heading--align-center::after{left:50%;transform:translateX(-50%)}.tsp-section-heading--filled span{background:var(--tsp-sidebar-accent-color,#ed1c24);color:#fff;padding:5px 12px;display:inline-block;border-radius:3px}.tsp-section-heading--minimal{font-weight:600;letter-spacing:.04em;text-transform:uppercase;font-size:14px;color:var(--tsp-sidebar-meta-color,#667085)}/* C2: Latest Stories layout extensions (scoped so legacy blocks untouched) */.tsp-latest-stories .tsp-sidebar__section--img-right .tsp-sidebar__item{flex-direction:row-reverse}.tsp-latest-stories .tsp-sidebar__section--divided .tsp-sidebar__item{padding-bottom:12px;border-bottom:1px solid #eceff3}.tsp-latest-stories .tsp-sidebar__section--divided .tsp-sidebar__item:last-child{border-bottom:0;padding-bottom:0}/* v1.10.13: the Image ratio control now sets the BOX ratio, not the <img> ratio. It used to force a ratio on the image with height:auto INSIDE a fixed-ratio box, which letterboxed or pillarboxed every non-matching choice against the grey placeholder; now the box takes the chosen ratio and the image still fills it with object-fit:cover. 0,3,0 beats both the base rule and the narrow tier, so an explicit choice wins at every width. */.tsp-latest-stories .tsp-sidebar__section--ratio-16-9 .tsp-sidebar__item-image{aspect-ratio:16/9}.tsp-latest-stories .tsp-sidebar__section--ratio-4-3 .tsp-sidebar__item-image{aspect-ratio:4/3}.tsp-latest-stories .tsp-sidebar__section--ratio-square .tsp-sidebar__item-image{aspect-ratio:1/1}.tsp-latest-stories .tsp-sidebar__list[style*='--tsp-sidebar-clamp'] h3{display:-webkit-box;-webkit-line-clamp:var(--tsp-sidebar-clamp,2);-webkit-box-orient:vertical;overflow:hidden}.tsp-latest-stories .tsp-sidebar__item-category{color:var(--tsp-sidebar-accent-color,#ed1c24);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.tsp-latest-stories .tsp-sidebar__item-author{color:var(--tsp-sidebar-meta-color,#667085);font-size:12px;margin-left:8px}.tsp-latest-stories .tsp-sidebar__item-excerpt{margin:6px 0 0;font-size:13px;color:var(--tsp-sidebar-meta-color,#667085)}.tsp-sidebar__section--card .tsp-sidebar__item{display:block}.tsp-sidebar__section--card .tsp-sidebar__item-image{display:block;width:100%;flex:0 0 auto;aspect-ratio:16/9;margin-bottom:8px}.tsp-sidebar__section--card .tsp-sidebar__item-image img{width:100%;height:100%;aspect-ratio:auto;object-fit:cover;border-radius:0}@container (max-width:520px){.tsp-latest-stories .tsp-nav-btn{width:44px;height:44px}}

/* v1.5.1: shared corner radius */.tsp-latest-stories .tsp-sidebar__section:not(.tsp-sidebar__section--card) .tsp-sidebar__item-image img{border-radius:var(--tsp-sidebar-radius,6px)}.tsp-sidebar__section--card .tsp-sidebar__item{border-radius:var(--tsp-sidebar-radius,10px);overflow:hidden}.tsp-sidebar__section--card .tsp-sidebar__item-body{padding:0 2px 4px}

/* v1.5.2: canonical sidebar baseline for Latest Stories */.tsp-latest-stories .tsp-sidebar__item-body{min-width:0}.tsp-latest-stories .tsp-sidebar__item-body h3{overflow-wrap:break-word}.tsp-latest-stories .tsp-sidebar__item-category{display:inline-block;max-width:100%}.tsp-latest-stories .tsp-sidebar__item-body time{display:block;margin-top:4px}

/* v1.9.0: mobile rules + text protection (tiers now legal via wrapper) */.tsp-sidebar__item-category{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.tsp-sidebar__item-body time{white-space:nowrap}@container (max-width:520px){.tsp-sidebar__section--grid .tsp-sidebar__list{grid-template-columns:1fr 1fr !important}}@container (max-width:380px){.tsp-sidebar__section--grid .tsp-sidebar__list{grid-template-columns:1fr !important}}

/* v1.10.13 SHARED NARROW-CONTAINER TIER, replacing the v1.10.7 stacked-only one.
   A sidebar column measures 300-520px even on a desktop viewport, so this stays
   a @container tier on .tsp-sidebar-wrap - never @media.

   The 16px title is NOT an invented exception: it is the modern News Grid's own
   narrow step (blocks.css: @container (max-width:520px){.tsp-news-card h3{font-
   size:16px}}), so matching the reference means matching its responsive step
   too. min() keeps a deliberately smaller saved value smaller - a saved 12px
   stays 12px here, a saved 24px renders 16px in a narrow column and its full
   24px above 520px. Same shape for the thumbnail: 96px -> 80px (80x60 at 4:3).

   These are base-level selectors (0,1,0) on purpose. Grid, card and numbered
   already override the image box at 0,2,0 and grid overrides the row gap at
   0,2,0, so all three keep their own geometry here with no :not() chains and no
   !important. Meta stays 12px - the reference does not shrink it. */
@container (max-width:520px){.tsp-sidebar__item{gap:10px}.tsp-sidebar__item-image{flex:0 0 min(var(--tsp-sidebar-thumb,96px),80px)}
/* v1.10.637 - WCAG 2.2 AA target size (2.5.8) on phones.
   A headline that fits on ONE line left a 15px-tall tap target sitting 20px
   from the NEXT card's thumbnail, which links to a DIFFERENT article - so a
   slightly low thumb opened the wrong story. Measured on every phone profile
   in both editions; multi-line headlines were already over 24px, which is why
   it only showed on short ones and only at some widths.
   The anchor becomes the whole heading line and is carried to 24px by padding;
   the equal negative margin keeps the card's outer geometry byte-for-byte what
   it was, so nothing moves. Replaces an empty rule that sat here doing nothing. */
.tsp-sidebar__item-body .tsp-story-title a{display:block;box-sizing:border-box;min-height:24px;padding-block:2px;margin-block:-2px}}

/* v1.10.20: Briefing rail numerals — zero-padded and gold. Scoped to
   .tsp-latest-stories on purpose, matching the existing "Latest Stories layout
   extensions" precedent above: any OTHER block using the numbered layout keeps
   its plain accent-coloured 1-5 and is untouched by this release. The rank
   colour is its own variable because --tsp-sidebar-accent-color also drives the
   heading rule, title hover and category label. 0,3,0 + pseudo-element beats the
   base rule, and the fallback chain means an unset rankColor lands on the gold. */
.tsp-latest-stories .tsp-sidebar__section--numbered .tsp-sidebar__item-image::before{content:counter(tsp-sidebar-rank,decimal-leading-zero);color:var(--tsp-sidebar-rank-color,#c8a24a);background:transparent;font-size:1.5rem;letter-spacing:.02em}

/* ==========================================================================
   v1.10.30 — "Rank columns" preset (`rank-columns`), for the homepage
   "What Everyone's Reading" band.

   A NEW preset rather than a variation of --numbered: the site's Customizer
   Additional CSS has repurposed .tsp-sidebar__section--numbered for the Scope
   Briefing rail (its own grid, its own ::before numeral, and a
   .tsp-sidebar:has(--numbered) rule that shrinks the section heading to a 12px
   eyebrow). Reusing it here would inherit all of that. Every rule below is
   scoped to --rank-columns, so the v1.10.15 presets stay ADDITIVE ONLY.

   The numeral is .tsp-sidebar__item::before driven by a counter, NOT the image
   anchor that --numbered uses. That anchor only exists when a story has a
   thumbnail, and this preset is a text list — so hanging the rank off it would
   drop the numbering the moment images were turned off.
   ========================================================================== */
.tsp-sidebar__section--rank-columns .tsp-sidebar__list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:30px;row-gap:0;counter-reset:tsp-rank}
.tsp-sidebar__section--rank-columns .tsp-sidebar__item{counter-increment:tsp-rank;display:grid;grid-template-columns:auto 1fr;gap:14px;align-items:center;padding:14px 0;border-top:1px solid #e8e5de}
/* v1.10.52: the prototype's `.wer-item .num` is `font-family:var(--serif)` —
   the numeral is display type, not UI type. Ours inherited the sans stack, so
   the rail read as a plain numbered list rather than the editorial rank column
   the prototype draws. `line-height:1` matches it too; 22px on 22px was fine
   but the prototype states the ratio, so state it the same way. */
.tsp-sidebar__section--rank-columns .tsp-sidebar__item::before{content:counter(tsp-rank);font-family:var(--ts-display);font-size:22px;line-height:1;font-weight:700;color:var(--tsp-sidebar-rank-color,#C9CCD3)}
/* Text list by design, matching the prototype — the numeral owns the left
   column. Same stance as --numbered, which also hides its thumbnail. */
.tsp-sidebar__section--rank-columns .tsp-sidebar__item-image{display:none}
.tsp-sidebar__section--rank-columns .tsp-sidebar__item-body{display:flex;flex-direction:column;min-width:0}
.tsp-sidebar__section--rank-columns .tsp-story-title{font-size:var(--ts-title-dense);line-height:var(--ts-lh-dense);font-weight:600}
.tsp-sidebar__section--rank-columns .tsp-story-title a{color:var(--tsp-sidebar-title-color,#172033)}
/* The kicker sits BELOW the headline in this preset. Section_Renderer emits it
   before the title, so it is reordered visually rather than by changing shared
   markup — the DOM order still reads category-then-headline for assistive
   technology, which is the more useful order there anyway. */
.tsp-sidebar__section--rank-columns .tsp-sidebar__item-category{order:2;margin-top:5px;font-size:9px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--tsp-sidebar-accent-color,#ed1c24)}
.tsp-sidebar__section--rank-columns .tsp-sidebar__item-body time{order:3}
@media (max-width:781px){
	.tsp-sidebar__section--rank-columns .tsp-sidebar__list{grid-template-columns:1fr}
}

/* v1.10.60 Correction 2 — the --classic section headings.

   v1.10.59 Part B put the fix in blocks.css, but the rule that actually wins on
   these is in THIS file: `.tsp-section-heading{color:var(--tsp-sidebar-heading-color,#172033)}`
   at the same (0,1,0), in a stylesheet enqueued after blocks.css. Source order
   again — so the correction belongs here, after the rule it has to beat.

   That covers the H2 carrying the class directly, which is the shape the three
   remaining headings use: "What Everyone's Reading", "Latest Stories" and
   "Telugu Highlights" (H2.tsp-section-heading.tsp-section-heading--classic).

   Once this ships, the Customizer --ts-title-ink / --tsp-title-color block can
   be emptied outright: nothing routes heading colour through it any more, so the
   plugin is the single source of truth. Dark-scorecard #fff rules are untouched. */
.tsp-section-heading,
.tsp-section-heading--classic,
.tsp-nav-header .tsp-section-heading{color:var(--ts-ink,#16181F)}

/* v1.10.76 — typography test: The Scope Briefing post titles.
   Was 18px/700. Scoped to --numbered so the four other rails that share
   .tsp-story-title (rank-columns, compact, stacked, Latest Stories) are
   untouched. Family stays the display serif; the section heading is not
   targeted. */
.tsp-sidebar__section--numbered .tsp-story-title,
.tsp-sidebar__section--numbered .tsp-story-title a{font-size:14px;font-weight:600}

/* ==========================================================================
   v1.10.77 — §10 The Scope Briefing, §15/16/19 rails.
   ========================================================================== */

/* §10 Briefing story headlines — 15px/600.
   v1.10.422: the family moves to the display serif. v1.10.77 put these in the
   UI voice on the reasoning that "these are scanned, not read"; the owner's
   typography unification reverses it — a story headline is a story headline
   wherever it appears, and a rail that sets its headlines in the navigation
   face is the split this pass exists to remove. Size, weight, leading and
   tracking are unchanged: this is a family pass, not a rescale. */
.tsp-sidebar__section--numbered .tsp-story-title,
.tsp-sidebar__section--numbered .tsp-story-title a{font-family:var(--ts-font-display);font-size:15px;font-weight:600;line-height:1.42;letter-spacing:normal}

/* §10 numerals — Georgia, red, 22px, tight. */
.tsp-sidebar__section--numbered .tsp-sidebar__item::before,
.tsp-sidebar__section--numbered .tsp-sidebar__item-image::before{font-family:var(--ts-font-display);font-size:22px;font-weight:700;line-height:1}

/* §15/16/19 the other rails — 13.5px/600, one value rather than the three
   near-identical sizes these had (§30).
   v1.10.422: display serif, for the same reason as the Briefing above. Most
   Viewed, Latest Stories and the stacked rails all render real headlines. */
.tsp-sidebar__section--rank-columns .tsp-story-title,
.tsp-sidebar__section--compact .tsp-story-title,
.tsp-sidebar__section--stacked .tsp-story-title{font-family:var(--ts-font-display);font-size:var(--ts-title-dense);font-weight:600;line-height:var(--ts-lh-dense)}

/* Rail metadata — 11.5px/400. */
.tsp-sidebar__item-meta,.tsp-sidebar__item-body time{font-family:var(--ts-font-ui);font-size:11.5px;font-weight:400;line-height:1.4}

/* §10/§11 rail headings stay in the UI voice at 12px/700 uppercase. §11 is
   explicit that small sidebar headings must NOT become Georgia — only true
   editorial section headings do. */
.tsp-sidebar__heading{font-family:var(--ts-font-ui);font-size:12px;font-weight:700;letter-spacing:.8px;text-transform:uppercase;line-height:1.3}

/* v1.10.132 — the Telugu rail's cross-site link is a real touch target.

   Measured 232x26 at 390 and 768. It is `display:flex`, so the WCAG 2.5.8
   inline-text exception does not cover it — unlike the card's headline links,
   which are inline inside an <h3> and are constrained by their line-height.

   Grown with padding and a min-height, leaving the 11px type alone: the size is
   the shared header's and the audit is about the hit area. Scoped to this rail
   rather than every `.tsp-nav-viewall` on the site — widening it to the shared
   header is a reasonable follow-up, but it is not this change's blast radius. */
@media (max-width: 782px) {
	.tsp-sidebar--telugu .tsp-nav-viewall {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
		padding-block: 4px;
	}
}

/* ==========================================================================
   v1.10.133 — "Compact Telugu Strip" layout preset.

   A reduced editorial card row: landscape image, headline, timestamp. No
   kicker — that is dropped in the MARKUP by Section_Renderer, not hidden here,
   so a screen reader is not read a label the design does not show.

   RESPONSIVE MODEL: @container, per the wrapper standard — container-type
   lives on .tsp-sidebar-wrap, so every rule below targets a DESCENDANT of it
   and never the wrapper itself.

   WHY auto-fit RATHER THAN FIXED COLUMN COUNTS. The brief asked for 5 cards on
   large desktop, 4 on normal desktop and 2 on tablet. Writing those as
   `repeat(5, 1fr)` etc. would leave EMPTY TRACKS whenever the feed returns
   fewer items than the row wants — a hole where a card should be, which is the
   padded-row problem in a different costume. `auto-fit` collapses unused
   tracks, so three real items make three cards that fill the width.

   The 210px minimum is chosen to land on the requested counts at a 16px gap,
   since auto-fit fits floor((W + gap) / (min + gap)) columns:

     container 1200 -> floor(1216/226) = 5   (large desktop)
     container  900 -> floor( 916/226) = 4   (normal desktop)
     container  700 -> floor( 716/226) = 3   (between the two named steps)
     container  560 -> floor( 576/226) = 2   (tablet)
     container  390 -> floor( 406/226) = 1   (mobile, and any narrow sidebar)

   So a narrow sidebar degrades to a single column of full-width landscape
   cards rather than a horizontal scroller or a row of unreadably small ones.
   ========================================================================== */
.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__list {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
	gap: 16px;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* The card: image above the text, not the shared row layout. */
.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item {
	display: flex;
	flex-direction: column;
	gap: 0;
	padding: 0;
	border: 0;
	min-width: 0;
}

.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item + .tsp-sidebar__item {
	border-top: 0;
}

.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item-image {
	display: block;
	width: 100%;
	aspect-ratio: 16 / 10;
	overflow: hidden;
	border-radius: 6px;
	margin: 0 0 10px;
	flex: none;
}

.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item-image img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item-body {
	min-width: 0;
	padding: 0;
}

/* v1.10.442 — a story with no image is a TEXT card, not a broken one.
 *
 * Grid items stretch to the row height, so a card whose story carries no image
 * kept the height its neighbours needed and left every pixel of it in one lump
 * beneath the headline. On English staging at 390 that was ~200px of white
 * under two lines of Telugu, directly above a "View all" link — it reads as an
 * image that failed to load, and a reader has no way to tell the difference.
 *
 * Centring the body distributes the slack instead of pooling it, so the card
 * presents as deliberately text-only. The headline is allowed a little more
 * size because there is room for it and nothing else is competing — this is the
 * one place in the strip where that is true, so it is scoped to the modifier
 * rather than changing the preset's type scale.
 *
 * No placeholder image: these items come from the cross-site feed, so there is
 * no attachment for the missing-media chain to resolve, and a stock graphic
 * would be inventing content for a story that has none. */
/* v1.10.469 — centring alone was not enough; the card still read as broken.
 *
 * v1.10.442 distributed the slack instead of pooling it, which was an
 * improvement and still left the real problem in place: measured on staging the
 * card is 219x250 at 1440 and 348x290 at 390, holding 65px and 43px of content
 * respectively — 74% of the box empty. Worse, centred text in a bare card sits
 * at a different height from the imaged cards beside it, whose text starts under
 * a 137px photo, so the row read as misaligned rather than as a design.
 *
 * Giving the card an actual surface is what makes the space deliberate: a
 * bordered panel is a text card, the same footprint as its neighbours, and the
 * headline takes the room that is genuinely free. Still no placeholder graphic —
 * 5 of these 12 stories carry `featured_media: 0` at source, and inventing a
 * stock image for them would be inventing content. */
.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item--noimg {
	justify-content: center;
	padding: 14px;
	border: 1px solid var(--tsp-hairline, #E8E5DE);
	border-radius: 6px;
	background: var(--tsp-noimg-bg, #FAF9F7);
}

/* The body carries `flex: 1 1 0%` from the shared card rules, so it absorbs
   the whole card and the centring above has nothing left to move — verified on
   staging, where the modifier and `justify-content: center` both computed
   correctly and the text still sat hard against the top. Letting the body take
   its content height hands the slack back to the parent, which is the box that
   knows how to share it. */
.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item--noimg .tsp-sidebar__item-body {
	flex: 0 0 auto;
}

/* v1.10.471 — the panel above was arriving open at the top.
 *
 * `.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item + .tsp-sidebar__item`
 * (0,3,0) sets `border-top: 0` to stop stacked rows doubling their rules, and it
 * outranks the (0,2,0) modifier rule that paints the panel. Every card except
 * the first therefore drew right, bottom and left only — a three-sided box.
 *
 * It measured 1px on English staging because the first card there happens to be
 * the image-less one, so the sibling selector never matched it. The Telugu
 * edition, whose first card carries an image, showed 0px/1px/1px/1px.
 *
 * Matching the sibling rule's specificity restores the edge without weakening
 * the rule itself, which is still doing its job for the imaged rows. */
.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item + .tsp-sidebar__item--noimg {
	border-top: 1px solid var(--tsp-hairline, #E8E5DE);
}

/* +1px was too timid for a card with 185px of free height. The headline is the
   only content here and nothing competes with it, so it takes the space; the
   balance keeps the last line from stranding a single word under a centred
   block. Scoped to the modifier, so the preset's type scale is untouched. */
.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item--noimg .tsp-story-title {
	font-size: calc(var(--tsp-sidebar-title, 15px) + 4px);
	line-height: 1.4;
	text-wrap: balance;
}

/* +4px closed the desktop gap but not the phone one: at 390 the rail shows a
   single 348px-wide card and the panel was still 74% empty after the first
   pass. A card that wide carries a much larger headline than a 219px desktop
   column can, so the narrow layout gets its own step.
   `@container`, not `@media` — the wrap carries `container-type: inline-size`
   and the card is a descendant of it, which is the only way this matches. */
@container (max-width: 520px) {
	.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item--noimg .tsp-story-title {
		font-size: calc(var(--tsp-sidebar-title, 15px) + 9px);
	}
}

/* Bold editorial headline. Telugu resolves through the shared type tokens —
   every stack already ends in the matching Noto Telugu face, so no font is
   named here. */
.tsp-sidebar__section--compact-telugu-strip .tsp-story-title {
	margin: 0;
	font-size: var(--tsp-sidebar-title, 15px);
	font-weight: 700;
	line-height: 1.35;
}

.tsp-sidebar__section--compact-telugu-strip .tsp-story-title a {
	color: var(--tsp-title-color, var(--ts-ink, #16181f));
	text-decoration: none;
}

/* Subtle timestamp beneath. */
.tsp-sidebar__section--compact-telugu-strip time {
	display: block;
	margin-top: 6px;
	font-size: 12px;
	line-height: 1.3;
	color: var(--tsp-meta-color, var(--ts-muted, #676E7B));
}

/* ------------------------------------------------------------------
   Section header: heading left, cross-site link right, thin red rule.

   `:has()` is used because the header is a SIBLING of the layout scope —
   `aside.tsp-sidebar > .tsp-nav-header` sits beside
   `section.tsp-sidebar__section--…` — so there is no ancestor carrying the
   preset. This keeps the treatment to blocks actually using the preset without
   a PHP change or a second class threaded through the renderer. `:has()` is
   already relied on elsewhere in this project's CSS.
   ------------------------------------------------------------------ */
.tsp-sidebar:has(.tsp-sidebar__section--compact-telugu-strip) .tsp-nav-header {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 16px;
	flex-wrap: wrap;
	padding-bottom: 8px;
	margin-bottom: 16px;
	border-bottom: 2px solid var(--tsp-accent, #c8102e);
}

.tsp-sidebar:has(.tsp-sidebar__section--compact-telugu-strip) .tsp-nav-header .tsp-section-heading {
	margin: 0;
	min-width: 0;
}

/* The link wraps rather than pushing the row wider — the brief asks for a
   clean header at every width and no overflow. */
.tsp-sidebar:has(.tsp-sidebar__section--compact-telugu-strip) .tsp-nav-viewall {
	white-space: nowrap;
	max-width: 100%;
	overflow-wrap: anywhere;
}

/* v1.10.196 — View All sits on the heading line, left of the arrows.
   The renderer places it inside `.tsp-nav-header__actions` for this preset
   (`HEADER_VIEWALL_LAYOUTS`), so nothing here reorders a flex column.

   `align-items: center` overrides the header's `baseline` for this group only:
   the group's baseline comes from the View All text, which would hang the two
   40px circular buttons off that text's baseline instead of centring them on it.
   The 16px gap is the separation between View All and Previous.

   The `margin: 0` is the whole cost of the move: `viewall_html()` prints its own
   `.tsp-nav-viewall-row` wrapper wherever it lands, and that wrapper carries the
   `margin-top: 14px` that used to space it away from the list below. */
.tsp-sidebar:has(.tsp-sidebar__section--compact-telugu-strip) .tsp-nav-header__actions {
	display: flex;
	align-items: center;
	gap: 16px;
	flex: 0 0 auto;
}
.tsp-sidebar:has(.tsp-sidebar__section--compact-telugu-strip) .tsp-nav-header__actions .tsp-nav-viewall-row {
	margin: 0;
}

/* v1.10.134 — the strip's cross-site link is a touch target too.

   v1.10.132 scoped this to `.tsp-sidebar--telugu`, which is the TEMPLATE rail.
   A block using the Compact Telugu Strip has no such class, so its link stayed
   at 26px — caught by the strip self-test at 768. Keyed off the preset instead,
   so it follows the layout rather than the surface. */
@media (max-width: 782px) {
	.tsp-sidebar:has(.tsp-sidebar__section--compact-telugu-strip) .tsp-nav-viewall {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
		padding-block: 4px;
	}
}

/* ==========================================================================
   v1.10.197 — phone widths keep View All BELOW the cards.

   WHY. v1.10.196 put View All on the heading line, which is right on desktop and
   tablet. Measured at 390px it does not fit: the row needs 376px (heading 147 +
   actions 213 + 16px gap) against 350px available — 26px short, with the arrows
   at their 44px touch size. Squeezing it in was tried and rejected: View All at
   12px with 10px gaps lands at exactly 0px of slack, and still wraps at 360px. A
   composition that survives only at one device width is not a composition.

   SO the phone keeps the approved presentation — heading and arrows on one line,
   View All centred under the cards — and it is done WITHOUT a second link. The
   markup is unchanged; only the layout moves. `display: contents` dissolves the
   header and its actions group so their children become items of the aside's own
   grid, which can then place the SAME anchor node on a row of its own below the
   viewport. One View All, one Previous, one Next in the DOM at every width.

   The cost of dissolving `.tsp-nav-header` is that its box stops painting, so the
   red rule it carried becomes a 2px grid row of its own — the same rule in the
   same place, and the viewport's styling is left alone. Measured against the
   pre-196 baseline the result is exact: rule at 52px, cards at 80px, 24px from
   the cards to the View All row.

   480px, not 782px: the header stops fitting below ~416px, and 768 is part of the
   approved desktop/tablet result that must not move.
   ========================================================================== */
@media (max-width: 480px) {
	.tsp-sidebar:has(.tsp-sidebar__section--compact-telugu-strip) {
		display: grid;
		grid-template-columns: minmax(0, 1fr) auto;
		row-gap: 0;
	}

	/* Dissolve the two wrappers so their children join the grid above. */
	.tsp-sidebar:has(.tsp-sidebar__section--compact-telugu-strip) .tsp-nav-header,
	.tsp-sidebar:has(.tsp-sidebar__section--compact-telugu-strip) .tsp-nav-header__actions {
		display: contents;
	}

	/* Row 1 — heading left, arrows right, exactly as before. */
	.tsp-sidebar:has(.tsp-sidebar__section--compact-telugu-strip) .tsp-nav-header .tsp-section-heading {
		grid-column: 1;
		grid-row: 1;
		align-self: center;
	}
	.tsp-sidebar:has(.tsp-sidebar__section--compact-telugu-strip) .tsp-nav-header__actions .tsp-nav-controls {
		grid-column: 2;
		grid-row: 1;
		justify-self: end;
	}

	/* Row 2 — the rule the dissolved header used to draw, as a row of its own.
	   NOT a `border-top` on the viewport: that element carries `border-radius: 8px`
	   for its scroll container, so a border on it renders with curled ends instead
	   of the straight full-width rule the design has. A dedicated 2px row is also
	   the only version that leaves the viewport's own styling completely alone. */
	.tsp-sidebar:has(.tsp-sidebar__section--compact-telugu-strip)::before {
		content: "";
		grid-column: 1 / -1;
		grid-row: 2;
		height: 2px;
		margin-top: 8px;
		background: var(--tsp-accent, #c8102e);
	}

	/* Row 3 — the cards. */
	.tsp-sidebar:has(.tsp-sidebar__section--compact-telugu-strip) .tsp-nav-viewport {
		grid-column: 1 / -1;
		grid-row: 3;
		margin-top: 26px;
	}

	/* Row 4 — the same anchor, back under the cards. The selector carries the
	   `__actions` ancestor so it outranks that group's `margin: 0` reset, which
	   still matches here: `display: contents` removes the box, not the element. */
	.tsp-sidebar:has(.tsp-sidebar__section--compact-telugu-strip) .tsp-nav-header__actions .tsp-nav-viewall-row {
		grid-column: 1 / -1;
		grid-row: 4;
		margin-top: 24px;
	}
}



/* ==========================================================================
   v1.10.145 — the Compact Telugu Strip sits in the homepage container.

   MEASURED CAUSE. v1.10.135 gave this preset `alignfull` so it could escape a
   ~757px Gutenberg column and fit more than three cards. The block has since
   been moved to the top level of the page, so that workaround now does harm:
   at a 1690px window the section spanned 0->1690 while Hero (265->1022), The
   Scope Briefing (->1425) and the National grid (content 265->1425) all stopped
   at the shared 1200px content boundary.

   THE CANONICAL CONTAINER, reused rather than re-derived. typography.css gives
   every homepage section `max-width: var(--tsp-wrap)`, `margin-inline: auto`
   and `padding-inline: var(--tsp-gutter)` — 1200px and 20px. `.tsp-eb-wrap`
   (National) takes all three. `.tsp-sidebar-wrap` takes the first two but has
   its gutter zeroed, because it is normally used INSIDE a Gutenberg column that
   supplies its own padding.

   At the top level that zeroed gutter is what would leave this section's cards
   20px to the left of National's. So the strip restores the gutter — from the
   same token, not a number — and inherits the width and centring it already
   had. No breakout, no alignment class, no width of its own.
   ========================================================================== */
.entry-content .tsp-sidebar-wrap.tsp-sidebar-wrap--strip {
	padding-inline: var(--tsp-gutter, 20px);
	box-sizing: border-box;
}

/* --------------------------------------------------------------------------
   v1.10.178 — the empty band above "View All".

   ROOT CAUSE, and it is not a stray margin. `.tsp-sidebar` is a flex column
   with `gap: var(--tsp-sidebar-gap, 32px)`. That 32px exists for a REAL
   sidebar, where the flex children are whole stacked sections and 32px between
   them is correct. This layout is `--single`: its flex children are the
   heading, the carousel viewport and the View All row — three parts of ONE
   component — so the section gap was being spent inside the component instead
   of between components.

   Measured at 1600 before the change, and the arithmetic closes exactly:

     heading 50 + margin 16 + GAP 32
     + viewport 229.3 + GAP 32
     + row margin 14 + row 28.4          = 401.7px, the aside's exact height

   So of the 46px between the last card and View All, 32px was this gap and
   only 14px was the row's own margin. Turning the gap down is therefore the
   fix at source; a negative margin on the row would have cancelled a symptom
   and left the same 32px sitting under the heading.

   10px lands the card-to-View-All distance at 24px (10 + the row's existing
   14px margin), inside the 20-30px target, and leaves the heading 26px of air
   instead of 48px. Height is still entirely content-driven: nothing here sets
   a height, a min-height or a row template, so a story with a third title line
   simply makes the section taller.

   Scoped to `--strip`, which the renderer emits for `compact-telugu-strip` and
   nothing else, so Trending, Most Viewed, the Briefing and every real sidebar
   keep the 32px section rhythm.
   -------------------------------------------------------------------------- */
.tsp-sidebar-wrap--strip .tsp-sidebar {
	--tsp-sidebar-gap: 10px;
}

/* ==========================================================================
   v1.10.153 — THE SCOPE BRIEFING preset
   --------------------------------------------------------------------------
   A NEW preset with NEW selectors, deliberately not a variation of
   `--numbered`. The site Customizer's "Batch 1F/1G" blocks own `--numbered`
   (51 rules, 12 of them !important) and wp-custom-css prints after this file,
   so a variation would inherit all of it and lose every tie. Nothing below
   uses !important; nothing below matches a Customizer selector.

   Newsroom, not cinema: flatter panel, tighter rows, urgent red kickers. The
   Scope Verdict band lower on the page stays the richer cinematic dark
   product, so this deliberately does NOT reuse its gradients or gold rules
   beyond the rank numerals.
   ========================================================================== */

/* No `height:100%` on the wrapper: the column's height is content-derived, so a
   percentage here resolves to auto and only reintroduces the feedback loop the
   min-height above exists to avoid. */
.tsp-sidebar-wrap--briefing { display: flex; }
.tsp-sidebar-wrap--briefing > .tsp-sidebar { flex: 1 1 auto; }

.tsp-sidebar-wrap--briefing .tsp-sidebar {
	/* v1.10.180 — LIGHT PANEL.
	   The approved reference makes the Briefing the bright, high-readability
	   surface beside the cinematic Hero, rather than a second dark box. Only
	   the palette and the rank/kicker treatment change: the grid, the row
	   height, the carousel and the min-height that meets the Hero's bottom edge
	   are all kept exactly as they were. */
	--tsp-brief-line: #ECE9E3;
	--tsp-brief-rule: #E8E5DE;
	--tsp-brief-ink: var(--ts-ink, #16181F);
	--tsp-brief-muted: var(--ts-muted, #676E7B);
	--tsp-brief-tint: rgba(200, 16, 46, .045);
	--tsp-brief-pad: 20px;
	/* v1.10.640 — the Hero-matching floor MOVED to the bottom of this file.
	   It belongs only to the tier where the Hero sits beside the Briefing and
	   only to a panel with the rows to fill it; unconditional here, it forced a
	   441px card around 208px of content on every phone and tablet. See
	   "THE BRIEFING IS AS TALL AS THE STORIES IT HAS". */
	display: flex;
	flex-direction: column;
	gap: 0;
	padding: var(--tsp-brief-pad);
	border-radius: var(--tsp-card-radius, 10px);
	/* White, a hairline border and no shadow — the panel reads as an editorial
	   surface, not a card competing with the Hero. */
	background: #fff;
	border: 1px solid var(--tsp-brief-rule);
	color: var(--tsp-brief-ink);
}

/* -------------------------------------------------------------- header ---- */

.tsp-sidebar-wrap--briefing .tsp-nav-header {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	/* Wraps rather than collides. The wordmark is `nowrap`, and in the 379px
	   panel the homepage currently gives this block the heading (~205px), View
	   All (90px) and the arrows (66px) need ~387px — so the wordmark ran
	   underneath View All. Wrapping drops the actions onto their own line when
	   they cannot fit and keeps the reference's single row once the column is
	   widened. */
	flex-wrap: wrap;
	gap: 6px 14px;
	margin: 0 0 14px;
}
.tsp-sidebar-wrap--briefing .tsp-nav-header__titles { min-width: 0; flex: 1 1 auto; }
.tsp-sidebar-wrap--briefing .tsp-nav-header__actions { margin-left: auto; }

.tsp-sidebar-wrap--briefing .tsp-section-heading {
	display: flex;
	align-items: center;
	gap: 9px;
	margin: 0;
	font-family: var(--ts-display, Georgia, serif);
	font-weight: 700;
	/* Sized to stay on ONE line. The heading shares its row with View All and
	   the arrows, which left it a 273px column on staging — at 22px the
	   wordmark wrapped to two lines. `nowrap` states the intent rather than
	   relying on the measurement holding, and the narrow tier below releases it
	   for containers too small to honour it. */
	font-size: clamp(15px, 1.25vw, 19px);
	line-height: 1.2;
	letter-spacing: .01em;
	white-space: nowrap;
	color: var(--tsp-brief-ink);
	border: 0;
	padding: 0;
}
/* The four-point star from the reference. */
.tsp-sidebar-wrap--briefing .tsp-section-heading::before {
	content: "\2726";
	flex: 0 0 auto;
	font-size: .85em;
	line-height: 1;
	color: var(--ts-red, #C8102E);
}
.tsp-sidebar-wrap--briefing .tsp-briefing__sub {
	margin: 5px 0 0;
	padding-left: 25px; /* aligns under the wordmark, past the star */
	font-family: var(--ts-ui, inherit);
	font-size: 12px;
	line-height: 1.3;
	color: var(--tsp-brief-muted);
}

.tsp-sidebar-wrap--briefing .tsp-nav-controls { flex: 0 0 auto; gap: 6px; }
.tsp-sidebar-wrap--briefing .tsp-nav-btn {
	width: 30px;
	height: 30px;
	border-radius: 50%;
	border: 1px solid var(--tsp-brief-rule);
	background: #fff;
	color: var(--tsp-brief-ink);
}
.tsp-sidebar-wrap--briefing .tsp-nav-btn:hover:not(:disabled),
.tsp-sidebar-wrap--briefing .tsp-nav-btn:focus-visible:not(:disabled) {
	background: var(--ts-red, #C8102E);
	border-color: var(--ts-red, #C8102E);
	color: #fff;
}
.tsp-sidebar-wrap--briefing .tsp-nav-btn:disabled { opacity: .3; }
/* Touch devices get a full-size target regardless of how wide the panel is. */
@media (pointer: coarse) {
	.tsp-sidebar-wrap--briefing .tsp-nav-btn { width: 44px; height: 44px; }
}
.tsp-sidebar-wrap--briefing .tsp-nav-btn:focus-visible { outline: 2px solid var(--ts-red, #C8102E); outline-offset: 2px; }

/* View All sits on the heading line. The renderer places it inside the header
   for this preset, so nothing here has to reorder a flex column. */
.tsp-sidebar-wrap--briefing .tsp-nav-header__actions {
	display: flex;
	align-items: center;
	gap: 12px;
	flex: 0 0 auto;
}
.tsp-sidebar-wrap--briefing .tsp-nav-header__actions .tsp-nav-viewall-row { margin: 0; }
.tsp-sidebar-wrap--briefing .tsp-nav-viewall {
	font-family: var(--ts-ui, inherit);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--ts-red, #C8102E);
	text-decoration: none;
	white-space: nowrap;
}
.tsp-sidebar-wrap--briefing .tsp-nav-viewall:hover,
.tsp-sidebar-wrap--briefing .tsp-nav-viewall:focus-visible { color: var(--ts-red, #C8102E); }

/* The viewport sizes to its rows — it must NOT absorb the panel's slack.
   With `flex:1 1 auto` it grew to fill the aside, which handed the row track a
   definite height; the five `auto` rows then filled it at 157px each and the
   panel ran to 886px. Sizing to content keeps rows intrinsic, and the panel
   still reaches the Hero's height through the shared min-height above. */
.tsp-sidebar-wrap--briefing .tsp-nav-viewport { flex: 0 0 auto; min-height: 0; }

/* --------------------------------------------------------------- rows ----- */

/* No percentage heights on the section or the list. Both resolved against a
   chain that ended at a content-derived column height, so the five `auto` rows
   stretched to 157px each and the panel settled at 913px. The rows stay
   intrinsic; the panel's height comes from the shared min-height above, which
   is a fixed value and cannot feed back. */
.tsp-sidebar__section--scope-briefing .tsp-sidebar__list {
	counter-reset: tsp-brief-rank;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* The shared carousel already models exactly what this panel needs: with
   `--tsp-nav-rows` set to the page size it stacks five stories in one column
   and pages to 6-10. So the grid is KEPT, not replaced — two things are
   adjusted:
     - the rows spread across the panel height, so its bottom edge meets the
       Hero's instead of leaving a gap;
     - the row gap goes, because these rows are separated by hairlines.
   Specificity has to clear `.tsp-sidebar--single.tsp-nav-enabled
   .tsp-sidebar__list` (0,3,0) from section-nav.css, which is why the wrapper
   is named here. That stylesheet's `display:grid !important` is left alone —
   this preset wants the grid.

   `align-content` is deliberately LEFT as the `start` that section-nav.css
   sets. Both alternatives were tried and both inflated the panel to ~886px:
   `1fr` rows resolved against max-content, and `space-between` let the five
   `auto` tracks resolve to 157px each. The rows stay intrinsic and any slack
   sits at the foot of the panel, which the shared min-height already sizes. */
.tsp-sidebar-wrap--briefing .tsp-sidebar--single.tsp-nav-enabled .tsp-sidebar__list {
	/*
	 * The track gets a FIXED height, and the rows divide it.
	 *
	 * Content-derived sizing could not be made to settle here: with the track
	 * height coming from its own rows, `auto` resolved every row to 157px and
	 * the panel ran to 886px. `1fr`, `max-content` and `align-content` were each
	 * measured and none of them broke the circularity, and it is not the
	 * Customizer — the same numbers appear with wp-custom-css disabled.
	 *
	 * Deriving the height from `--tsp-unit-min-h` instead removes the loop at
	 * its source: the value is a constant, so the rows can share it without
	 * feeding anything back. It also delivers what the design actually asks for
	 * — five even rows whose last one ends level with the Hero.
	 */
	/*
	 * An EXPLICIT row height, and no height on the track itself.
	 *
	 * Anything content-derived here misbehaves: `auto`, `max-content` and
	 * `minmax(min-content,1fr)` each resolved every row to ~157px and ran the
	 * panel past 800px, because the track's height and its rows define each
	 * other. Dividing a fixed track height gave 60px rows instead, which — with
	 * the row content measuring 73px — clipped the timestamp and the second
	 * headline line. That was the missing text on staging.
	 *
	 * Naming the row height ends both failures: it is a constant, so nothing
	 * feeds back, and it is set above the measured content so nothing is cut.
	 * The panel's height then simply follows its five rows.
	 */
	/* 96px = measured content. The row body is 73px (kicker 16 + two-line
	   headline 34 + timestamp 16, plus its margins) and the item adds 20px of
	   vertical padding, so 93px is the floor; 96 leaves a little air. Undersizing
	   this does not crop — there is no overflow here any more — it makes the body
	   spill past its own row and sit out of line with its rank numeral. */
	grid-template-rows: repeat(var(--tsp-nav-rows, 5), var(--tsp-brief-row, 96px));
	row-gap: 0;
}

/* v1.10.424 — on desktop the row is a MINIMUM, not a fixed height.
 *
 * The comment above is candid that undersizing this "makes the body spill past
 * its own row", and that is what has been happening: measured at 1024, 1366,
 * 1440 and 1920, with the ORIGINAL 14.5px two-line headlines, every one of the
 * five rows overflowed by 8-9px and four of them had a date painted over by the
 * next row's kicker badge. 96px was computed for a two-line headline at a size
 * the rail no longer uses, and a fixed track cannot absorb a longer one.
 *
 * `minmax(..., auto)` keeps 96px as the floor — short rows are unchanged, so
 * the rhythm the fixed value was protecting survives — and lets a row that
 * needs more take it, instead of hanging out of the bottom. Measured after:
 * spill 0 and collisions 0 at every desktop width, with no headline truncated.
 *
 * The cost is real and belongs in the report rather than buried here: the rail
 * grows ~177px at 1366 and 1440, and the hero beside it grows with it, because
 * the two share a grid row that sizes to the taller of them. Holding the old
 * height instead would mean dropping back to two lines, which truncates four of
 * five headlines — the brief rules that out explicitly.
 *
 * Desktop only. The phone rail below 480 is a different, verified case: a
 * re-tuned 152px track with a four-line clamp, already measured at zero spill,
 * and it does not need this. */
@media (min-width: 782px) {
	/* Same selector as the rule above, deliberately. That one is (0,4,0); a
	   shorter selector here would simply lose and the fix would look applied
	   while changing nothing. */
	.tsp-sidebar-wrap--briefing .tsp-sidebar--single.tsp-nav-enabled .tsp-sidebar__list {
		grid-template-rows: repeat(var(--tsp-nav-rows, 5), minmax(var(--tsp-brief-row, 96px), auto));
	}
}

.tsp-sidebar__section--scope-briefing .tsp-sidebar__item {
	counter-increment: tsp-brief-rank;
	position: relative;
	display: grid;
	/* rank | body | thumbnail
	   v1.10.182: the rank track was 42px around a 26px circle and the gap 12px,
	   which spent 28px of a 387px panel on air. The headline column is what pays
	   for that — measured at 191.6px, where a real headline needs three to four
	   lines and the two-line clamp then ellipses it. The circle and the
	   thumbnail keep their sizes; only the slack around them is recovered. */
	/* v1.10.273: rank | THUMBNAIL | body. The approved reference reads
	   NUMBER -> IMAGE -> CONTENT, so the tracks are reordered - the thumbnail
	   column moves ahead of the headline column. Done by swapping the grid
	   tracks and the two children's grid-column assignments, NOT by
	   row-reverse: the DOM order already is image-then-body, so reversing
	   would have flipped it away from the reading order it already has. */
	grid-template-columns: 30px 96px minmax(0, 1fr);
	align-items: center;
	gap: 0 9px;
	/* No `overflow:hidden`: it was clipping the timestamp and the second
	   headline line whenever the content exceeded the old fixed row budget.
	   The headline's own line-clamp already bounds the tallest element, so
	   nothing here needs to crop. */
	min-height: 62px;
	padding: 9px 10px 9px 12px;
	border-bottom: 1px solid var(--tsp-brief-line);
	border-left: 3px solid transparent;
	border-radius: 4px;
	transition: background-color .18s ease;
}
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:last-child { border-bottom: 0; }

/* Rank numeral — a scanning anchor, never louder than the headline. */
/*
 * All three cells are pinned to ROW 1.
 *
 * Column alone was not enough. The markup order is rank -> thumbnail (column 3)
 * -> body (column 2), so by the time the body is placed the auto-placement
 * cursor has already passed column 2 and grid opened a second row for it. The
 * item became a two-row grid (48px + 73px) and the text sat a half-row below
 * its own numeral — the misalignment visible on staging.
 */
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item::before,
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-body,
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-image { grid-row: 1; }

.tsp-sidebar__section--scope-briefing .tsp-sidebar__item::before {
	/* v1.10.180: a compact OUTLINED CIRCLE with a plain digit, per the reference,
	   replacing the 26px gold serif numeral the dark panel used. Plain `decimal`
	   rather than `decimal-leading-zero` — the reference reads 1..5, and "01" in
	   a 26px circle has nowhere to go. A counter still supplies the number, so
	   no markup changes and the rank cannot drift from the row order. */
	content: counter(tsp-brief-rank);
	grid-column: 1;
	justify-self: start;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	border: 1.5px solid var(--tsp-brief-rule);
	border-radius: 50%;
	box-sizing: border-box;
	font-family: var(--ts-ui, inherit);
	font-size: 12px;
	font-weight: 700;
	line-height: 1;
	color: var(--tsp-brief-ink);
	white-space: nowrap;
}

.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-body { grid-column: 3; min-width: 0; }

/* v1.10.180: a filled red BADGE, per the reference, rather than red text on the
   panel. `inline-block` so the badge hugs its label — a block-level badge would
   run the full body column and read as a bar. Kept small: 9.5px on a 3px radius,
   so it stays a kicker and never competes with the headline. */
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-category {
	display: inline-block;
	margin: 0 0 5px;
	padding: 2px 6px;
	border-radius: 3px;
	font-family: var(--ts-ui, inherit);
	font-size: 9.5px;
	font-weight: 700;
	letter-spacing: .07em;
	line-height: 1.35;
	text-transform: uppercase;
	background: var(--ts-red, #C8102E);
	color: #fff;
}

/* v1.10.424 — the family and size that used to sit here are gone.
 *
 * They were dead: a later rule in this file declares both at equal specificity
 * and wins on source order, so this said `--ts-ui` and 13.5px while the page
 * rendered the display serif at the dense size. Two rules disagreeing about one
 * component is how the next person edits the one that does nothing.
 *
 * THE CLAMP was the live part of this rule, and it was one line short. Measured
 * on staging at 14.5px: two of five Briefing headlines were cut at 1366 and
 * 1440, losing ~48 characters, and four of five at 320. Three lines fixes all
 * of it at ZERO height cost — the rows are sized by the thumbnail beside them,
 * so the text had the room all along and the clamp was throwing it away. */
.tsp-sidebar__section--scope-briefing .tsp-story-title {
	margin: 0;
	font-weight: 700;
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
/* The anchor carries the visible colour and measures white on staging; the
   heading itself is set too so the row never depends on the link's rule
   surviving a theme change. */
.tsp-sidebar__section--scope-briefing .tsp-story-title { color: var(--tsp-brief-ink); }
.tsp-sidebar__section--scope-briefing .tsp-story-title a {
	color: var(--tsp-brief-ink);
	text-decoration: none;
}
.tsp-sidebar__section--scope-briefing .tsp-story-title a:hover,
.tsp-sidebar__section--scope-briefing .tsp-story-title a:focus-visible {
	color: var(--ts-red, #C8102E);
}

.tsp-sidebar__section--scope-briefing time {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	margin-top: 5px;
	font-family: var(--ts-ui, inherit);
	font-size: 11px;
	color: var(--tsp-brief-muted);
}
.tsp-sidebar__section--scope-briefing .tsp-sidebar__clock { flex: 0 0 auto; opacity: .8; }

/* Thumbnail: fixed landscape box, so a portrait upload cannot stretch a row. */
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-image {
	grid-column: 2;
	display: block;
	width: 96px;
	height: 52px;
	overflow: hidden;
	border-radius: 5px;
	background: #eef1f4;
}
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-image img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* v1.10.662 — crop from above centre, so the tile keeps the FACE.
	 *
	 * The box above is 96x52, about 1.85:1, and it is deliberately fixed: the
	 * five uniform 104px rows are frozen at 1.10.517 and a portrait upload must
	 * not be able to reshape one. So this row cannot stop cropping — a whole
	 * portrait inside 96x52 would be a ~29px sliver. What it CAN stop is
	 * cropping the wrong part of the picture.
	 *
	 * `object-fit:cover` defaults to `50% 50%`, which centres the visible band
	 * and spends the overflow equally off the top and the bottom. Against a
	 * 1.85:1 window a 4/3 original loses about 28% of its height, half of it
	 * from the top — which is exactly where a news subject's head is. Reported
	 * by the owner on the Briefing's story 1.
	 *
	 * 30% holds the band high enough to keep a head at this ratio. It sits
	 * above the 38-42% used by category.css and scope-verdict.css because those
	 * crop into far squarer boxes and have much less overflow to spend.
	 *
	 * GEOMETRY IS UNTOUCHED: this changes which pixels are shown, never the
	 * size of the box, so the frozen row height and column tracks cannot move.
	 */
	object-position: center 30%;
	display: block;
	transition: transform .25s ease;
}
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:hover .tsp-sidebar__item-image img { transform: scale(1.04); }

/* Hover / focus: lift the row a little, nothing more. */
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:hover,
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:focus-within {
	background: rgba(0, 0, 0, .028);
}

/* ------------------------------------------------- the lead story, #01 ---- */

.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:first-child {
	border-left-color: var(--ts-red, #C8102E);
	/* Restrained burgundy wash, not a red card. */
	background: linear-gradient(90deg, rgba(200, 16, 46, .17) 0%, rgba(200, 16, 46, .05) 55%, rgba(200, 16, 46, 0) 100%);
}
/* The lead story's rank ring and numeral go red, which is what marks it as
   current without turning the row into a red card.

   v1.10.573: this rule MOVED to the active-state block further down, where the
   row's own active chrome is declared. Keeping the ring here and the border and
   wash there is what split the active state in half and left the numeral behind
   on every row but the first. */
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:first-child:hover,
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:first-child:focus-within {
	background: linear-gradient(90deg, rgba(200, 16, 46, .24) 0%, rgba(200, 16, 46, .08) 55%, rgba(200, 16, 46, 0) 100%);
}

/* ---------------------------------------------------------- responsive ---- */

/* Tablet: keep the panel beside the Hero but buy the headline room. */
@container (max-width: 420px) {
	/* 74px cropped the row at this tier — measured content is ~78px. */
	.tsp-sidebar-wrap--briefing .tsp-sidebar { --tsp-brief-pad: 16px; --tsp-brief-row: 96px; }
	/* NOTE: this tier is the one that renders on DESKTOP. The panel is ~387px
	   wide beside the Hero, so a 420px container query is permanently on there;
	   the base rule above only takes over when the Briefing is stacked full
	   width. Anything meant to reach the desktop desk has to be set here. */
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item {
		/* Same slack recovery as the base rule: the rank track loses 4px and each
		   gap 1px, and the row 2px of side padding, all of it handed to the
		   headline column — measured 191.6px before, ~205px after. The 26px rank
		   circle and the 76px thumbnail are unchanged. */
		/* v1.10.274: thumbnail track ahead of the headline, matching the base rule. */
		grid-template-columns: 30px 76px minmax(0, 1fr);
		gap: 0 9px;
		padding: 10px 6px;
	}
	/* v1.10.182: `font-size: 21px` here was left over from the gold serif numeral
	   this preset used before the outlined circle. A 21px digit inside a 26px
	   ring nearly fills it; the circle sizes its own type, so the override goes. */
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-image { width: 76px; height: 48px; }
	.tsp-sidebar__section--scope-briefing .tsp-story-title { font-size: var(--ts-title-brief); }
	/* v1.10.424: a fourth line where the rail is narrow.
	 *
	 * The existing four-line rule sits in `@container (max-width: 300px)`, which
	 * never fires — measured at a 320px viewport the rail container is wider
	 * than 300, so the base three-line clamp applied and four of five headlines
	 * were still cut. This tier does fire, at 320 and 390 and on the ~418px
	 * desktop rail.
	 *
	 * Allowing a fourth line costs nothing where it is not needed: a clamp is a
	 * ceiling, not a height, so rows that fit in two or three are unchanged.
	 * Measured at 320 and 390: page height +0. */
	.tsp-sidebar__section--scope-briefing .tsp-story-title { -webkit-line-clamp: 4; }
}

/* Narrow (stacked under the Hero on phones): the thumbnail goes, because the
   rank, kicker, headline and time are what the panel is for. Rows also stop
   sharing height — stacked, they should size to their content. */
/* 300px, not 330px. At 330 this tier fired on the 1024px DESKTOP layout, where
   the 33.33% column leaves a 328px panel, and dropped the thumbnails there —
   while a 390px phone, whose stacked panel is 350px wide, kept them. Exactly
   backwards. Container width does not track viewport width here, so the
   threshold has to sit below every side-by-side case. */
@container (max-width: 300px) {
	/* Stacked and thumbnail-free, the headline gets a third line, so the row
	   needs the height back. */
	.tsp-sidebar-wrap--briefing .tsp-sidebar { --tsp-brief-row: 104px; }
	/* Only HERE is the panel too narrow to hold the wordmark on one line.
	   Releasing it at 420px was wrong: staging's 379px panel fits the 19px
	   wordmark in ~175px and was wrapping purely because of this rule. */
	.tsp-sidebar-wrap--briefing .tsp-section-heading { white-space: normal; }
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item {
		/* v1.10.425: the rank column and the side padding give the headline
		   18px back. At 320 the thumbnail is already hidden here and the
		   headline still had only 170px against the 186px a three-line fit
		   needs, so four of five ran to four lines. 34>24 on the rank and 8>4
		   on the inline padding clears it without touching the type or the
		   vertical tap target. */
		grid-template-columns: 24px minmax(0, 1fr);
		/* Comfortable tap target on touch. */
		min-height: 56px;
		padding: 13px 4px;
	}
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-image { display: none; }
	/* The thumbnail is hidden at this tier, so the body takes the second track
	   rather than the third it occupies while an image column exists. */
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-body { grid-column: 2; }
	.tsp-sidebar__section--scope-briefing .tsp-story-title { -webkit-line-clamp: 4; }
}

@media (prefers-reduced-motion: reduce) {
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item,
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-image img { transition: none; }
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:hover .tsp-sidebar__item-image img { transform: none; }
}

/* ==========================================================================
   v1.10.160 — Hero + Briefing as ONE unit, and the Briefing hover state
   --------------------------------------------------------------------------
   THE GAP. Measured on staging: both panels carry `margin: 0` and
   `padding: 0`, and their columns carry `margin: 0` too. The white strip
   between them was entirely `column-gap: 24px` on `.wp-block-columns` — the
   Gutenberg block gap, which is page content this plugin does not own.

   So the rule below is scoped with `:has()` to a columns block that contains
   BOTH new presets. No other `.wp-block-columns` on the page — the Andhra
   Pradesh / Telangana pair, or any future one — can match it, and no negative
   margins are involved. Removing the gap rather than out-measuring it also
   means the ratio stays whatever the editor saved.
   ========================================================================== */

.wp-block-columns:has(.tsp-hero-wrap--cinematic):has(.tsp-sidebar-wrap--briefing) {
	column-gap: 0;
}

/* Meeting edges go square so the two read as one panel; the outer corners keep
   the card radius. Logical properties, so an RTL locale flips them correctly. */
.wp-block-columns:has(.tsp-hero-wrap--cinematic):has(.tsp-sidebar-wrap--briefing) .tsp-hero--cinematic {
	border-start-end-radius: 0;
	border-end-end-radius: 0;
}
.wp-block-columns:has(.tsp-hero-wrap--cinematic):has(.tsp-sidebar-wrap--briefing) .tsp-sidebar-wrap--briefing .tsp-sidebar {
	border-start-start-radius: 0;
	border-end-start-radius: 0;
}

/* Only once they are actually side by side. Stacked, each panel keeps its own
   full radius. 700px is the columns block's own width, not the viewport. */
@media (max-width: 781px) {
	.wp-block-columns:has(.tsp-hero-wrap--cinematic):has(.tsp-sidebar-wrap--briefing) .tsp-hero--cinematic,
	.wp-block-columns:has(.tsp-hero-wrap--cinematic):has(.tsp-sidebar-wrap--briefing) .tsp-sidebar-wrap--briefing .tsp-sidebar {
		border-radius: var(--tsp-card-radius, 10px);
	}
}

/* ------------------------------------------------- Briefing ACTIVE state ---
   The row already lifted its background, but the red left accent never
   appeared: `border-left-color` was only set on `:first-child`, so hovering
   any other row changed nothing at the edge. Both states now set it.

   `:focus-within` covers keyboard users reaching the headline link, which is
   the only focusable thing in a row.

   v1.10.573 — ONE LIST FOR THE WHOLE ACTIVE STATE.

   That earlier fix moved the row's chrome onto `:hover`/`:focus-within` and
   left its companion behind: the rank ring and numeral were recoloured by a
   separate `:first-child::before` rule further up the file. So from #2 down, a
   row would take the red accent and the burgundy wash while its numeral kept
   the resting pale ring and dark ink — the indicator read as missing against
   the active treatment, and was only ever right at #1, which is why it looked
   correct on load and broke the moment the pointer moved.

   Splitting an active state across two selectors is the bug, so the selector
   list is now shared: whatever makes a row active makes its ring active.
   `.is-active` and `[aria-current]` are included so that a programmatic
   selection — a Hero-synchronised row, or an auto-advanced one — lights the
   numeral through the same path rather than needing a second rule. Nothing
   emits them today; they cost nothing and they are the reason this cannot
   split again. */
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:hover,
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:focus-within,
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item.is-active,
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item[aria-current] {
	border-left-color: var(--ts-red, #C8102E);
	background: linear-gradient(90deg, rgba(200, 16, 46, .13) 0%, rgba(200, 16, 46, .04) 58%, rgba(200, 16, 46, 0) 100%);
}

/* The ring and the numeral, on exactly the same states — plus `:first-child`,
   which is the resting active row. Declared after the base `::before` so it
   wins on order rather than on specificity, and it sets only colour: the
   circle's size, position and `content` counter are untouched, so the number
   cannot move or vanish. */
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:first-child::before,
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:hover::before,
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:focus-within::before,
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item.is-active::before,
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item[aria-current]::before {
	border-color: var(--ts-red, #C8102E);
	color: var(--ts-red, #C8102E);
}
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:focus-within {
	outline: 2px solid var(--ts-red, #C8102E);
	outline-offset: -2px;
}
/* #01 keeps a stronger wash than a hovered neighbour, so its priority reads
   even while another row is hovered. Declared after, so it wins the tie. */
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:first-child:hover,
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:first-child:focus-within {
	background: linear-gradient(90deg, rgba(200, 16, 46, .26) 0%, rgba(200, 16, 46, .09) 58%, rgba(200, 16, 46, 0) 100%);
}

/* ==========================================================================
   v1.10.162 — Briefing polish pass, measured against the approved reference
   ========================================================================== */

/* PANEL PADDING. Measured 1px on staging although `--tsp-brief-pad` resolved to
   16px: an external rule sets `padding:1px` on the carousel-enabled sidebar and
   was outranking the preset's own declaration, which is why the heading sat
   against the panel edge. Naming the wrapper and both sidebar classes clears it
   without !important. */
.tsp-sidebar-wrap--briefing .tsp-sidebar.tsp-sidebar--single {
	padding: var(--tsp-brief-pad, 20px);
}

/* HEADER BREATHING ROOM, per the reference: the wordmark sits down from the
   edge rather than against it. */
.tsp-sidebar-wrap--briefing .tsp-sidebar { --tsp-brief-pad: 22px; }

/* v1.10.426 — the panel's side gutters, on phones only.
 *
 * 22px of panel padding plus a 1px border was costing 46px of every row, and on
 * a 320px screen that is a sixth of the whole viewport spent on empty margin
 * before a headline starts. Measured: the headline column was 188px at both 320
 * AND 375 — the wider screen bought nothing, because the extra width went to the
 * thumbnail rather than the text.
 *
 * INLINE only. `--tsp-brief-pad` sets all four sides, and taking it down
 * globally would pull the wordmark up against the top edge — the "header
 * breathing room" the rule above exists for. The block padding is untouched.
 *
 * 12px chosen from rendered evidence, not preference. Sweeping 14 / 12 / 10:
 * 14px leaves the fifth headline on four lines at 320; 12px clears every
 * four-line headline at 320, 375, 390 and 430; 10px buys four more pixels and
 * one extra two-line headline at 430, which is not worth the panel looking
 * pinched. The Briefing keeps a visible, deliberate gutter.
 *
 * The rank column is deliberately NOT narrowed. The ranking circle renders
 * 26px inside a 20px track, so it is already the widest thing in that column —
 * there is no slack there, and taking any would crop the circles. Everything
 * recovered goes to the headline. */
@media (max-width: 480px) {
	.tsp-sidebar-wrap--briefing .tsp-sidebar.tsp-sidebar--single {
		padding-inline: 12px;
	}
}
.tsp-sidebar-wrap--briefing .tsp-nav-header { margin-block: 4px 16px; }
.tsp-sidebar-wrap--briefing .tsp-briefing__sub { margin-top: 6px; }

/* THE / SCOPE / BRIEFING. Only the middle word is red; the renderer wraps it in
   a real span so the heading stays one readable string for assistive tech. */
.tsp-sidebar-wrap--briefing .tsp-briefing__accent { color: var(--ts-red, #C8102E); }

/* STORY HEADLINE TYPOGRAPHY. Declared on the ANCHOR as well as the <h3>,
   because the theme sets a family on the anchor itself — setting it only on the
   heading leaves the rendered glyphs untouched. That mechanism is why both
   selectors are here and it still applies.

   v1.10.422: the family is the display serif. The earlier note here argued the
   Briefing should read as "news UI sans" to stay distinct from the Hero; the
   owner's unification says the opposite — the Briefing is the publication's
   named editorial product and its headlines belong to the display system.
   Hero and Briefing remain distinct by SCALE, which is the honest difference
   between a 36px lead and a 13px rail line. */
.tsp-sidebar__section--scope-briefing .tsp-story-title,
.tsp-sidebar__section--scope-briefing .tsp-story-title a {
	font-family: var(--ts-display, Georgia, serif);
	/* v1.10.424: the Briefing's own token at 16px, one step above the rest of
	   the dense tier. v1.10.423 moved it off a hardcoded 13px to the shared
	   dense size; an accessibility review found it still tight, and this is the
	   one component measured to take 16px for nothing — its rows are sized by
	   the thumbnail, so neither the rail nor the page grows by a pixel. */
	font-size: var(--ts-title-brief);
	line-height: var(--ts-lh-dense);
	font-weight: 700;
	letter-spacing: -.005em;
}

/* ONLY ONE ROW EVER LOOKS ACTIVE.
   #01 is a DEFAULT, not a selection: as soon as any row is hovered or holds
   focus, the list neutralises #01 unless #01 is itself that row. Pure CSS via
   `:has()` on the list — no JavaScript is added for a visual state. */
.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:has(.tsp-sidebar__item:hover) .tsp-sidebar__item:first-child:not(:hover),
.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:has(.tsp-sidebar__item:focus-within) .tsp-sidebar__item:first-child:not(:focus-within) {
	border-left-color: transparent;
	background: none;
}

/* v1.10.574: …including its RANK RING, which this rule did not reach.
   The same half-a-state that hid the numeral in 1.10.573, mirrored: the
   neutraliser gave back #01's accent and wash but left its ring red, so once the
   ring started following the active row, TWO rows read as active at once.
   Measured while row 2 was hovered — at 1440 both #1 and #2 were red at 390 and
   only #2 at desktop, because a `@media (min-width:1024px) and (hover:hover)`
   block further down already reset the ring and nothing did below that tier.
   Stated here so it holds at every width and on touch, with the resting values
   the base rule uses, so a neutralised #01 is indistinguishable from rows 2-5. */
.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:has(.tsp-sidebar__item:hover) .tsp-sidebar__item:first-child:not(:hover)::before,
.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:has(.tsp-sidebar__item:focus-within) .tsp-sidebar__item:first-child:not(:focus-within)::before {
	border-color: var(--tsp-brief-rule);
	color: var(--tsp-brief-ink);
}

/* ==========================================================================
   v1.10.234 — TRENDING SHOWCASE (`trending-showcase`)
   References: Images/trending_desktop.png, _tablet.png, _mobile.png,
               _small_mobile.png

   The homepage Trending preview. One preset, four deliberately different
   compositions, all reading the SAME markup the shared section renderer already
   emits — image, category kicker, headline, <time> with the clock glyph. No new
   elements, and the ranking is a CSS counter exactly as `rank-columns` does it,
   so nothing about the number is invented data: it is the position of the story
   in the editor's curated list.

   Container queries throughout, on .tsp-sidebar-wrap (the mandatory wrapper),
   never @media. Tiers key off the CONTAINER width, which at the reference
   viewports works out as:
       viewport 1440 -> container ~1200   3x2 cards
       viewport 1024 -> container  ~984   2-col compact rows  (tablet reference)
       viewport  390 -> container  ~350   ranked feed
       viewport  320 -> container  ~280   ranked feed, tightened
   ========================================================================== */

.tsp-sidebar__section--trending-showcase .tsp-sidebar__list {
	counter-reset: tsp-trend;
	display: grid;
	list-style: none;
	margin: 0;
	padding: 0;
}

.tsp-sidebar__section--trending-showcase .tsp-sidebar__item {
	counter-increment: tsp-trend;
	min-width: 0;
}

/* v1.10.286 — the rank is a red rounded-square BADGE in every tier, which is
   what trending2_desktop / _tablet / _mobile / _small_mobile all show. It used
   to be a serif numeral here and a badge only on desktop; the numeral read as a
   different component at the tier boundary. Desktop overlays this badge on the
   image, the smaller tiers set it beside the thumbnail — position is the only
   thing that changes, so the badge itself is defined once.

   Plain `counter()`, not decimal-leading-zero: the references show 1..5, and
   "01" in a 22px box forces the digits down to an unreadable size. */
.tsp-sidebar__section--trending-showcase .tsp-sidebar__item::before {
	content: counter(tsp-trend);
	display: flex;
	align-items: center;
	justify-content: center;
	min-width: 24px;
	height: 24px;
	border-radius: 6px;
	background: var(--tsp-accent, #C8102E);
	font-family: var(--ts-font-ui, inherit);
	font-size: 13px;
	font-weight: 700;
	line-height: 1;
	color: #fff;
	font-variant-numeric: tabular-nums;
}

.tsp-sidebar__section--trending-showcase .tsp-sidebar__item-image {
	display: block;
	overflow: hidden;
	background: #eee;
}

.tsp-sidebar__section--trending-showcase .tsp-sidebar__item-image img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.tsp-sidebar__section--trending-showcase .tsp-sidebar__item-body { min-width: 0; }

.tsp-sidebar__section--trending-showcase .tsp-sidebar__item-category {
	display: block;
	font-family: var(--ts-font-ui, inherit);
	font-weight: 800;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--tsp-accent, #C8102E);
}

/* v1.10.422: display serif — Trending renders story headlines. */
.tsp-sidebar__section--trending-showcase .tsp-story-title {
	margin: 0;
	font-family: var(--ts-font-display, Georgia, serif);
	font-weight: 700;
}

.tsp-sidebar__section--trending-showcase .tsp-story-title a {
	color: var(--tsp-sidebar-title-color, #172033);
	text-decoration: none;
	transition: color .18s ease;
}

.tsp-sidebar__section--trending-showcase .tsp-story-title a:hover,
.tsp-sidebar__section--trending-showcase .tsp-story-title a:focus-visible {
	color: var(--tsp-accent, #C8102E);
}

.tsp-sidebar__section--trending-showcase time {
	display: flex;
	align-items: center;
	gap: 5px;
	font-family: var(--ts-font-ui, inherit);
	color: var(--ts-muted, #676E7B);
}

.tsp-sidebar__section--trending-showcase .tsp-sidebar__clock { flex: 0 0 auto; opacity: .85; }

/* The standfirst under the heading. */
.tsp-trend__sub {
	margin: 4px 0 0;
	font-family: var(--ts-font-ui, inherit);
	font-size: 13.5px;
	line-height: 1.45;
	color: var(--ts-muted, #676E7B);
}

/* ------------------------------------------------ desktop: 3 x 2 cards ---- */

/* 1000px of container, not the site's usual 861: at a 1024px viewport the
   container is ~984, and the tablet reference is explicit that 1024 is still
   the two-column compact layout. Keying off 1000 puts the switch where the
   reference puts it rather than where the default desktop breakpoint sits. */
@container (min-width: 1000px) {
	.tsp-sidebar__section--trending-showcase .tsp-sidebar__list {
		grid-template-columns: repeat(5, minmax(0, 1fr));
		gap: 14px;
	}

	/* v1.10.284 — five across, per trending2_desktop.png. The rank stops being a
	   serif numeral beside the story and becomes a red badge ON the image, which
	   is what makes the ranking read at a glance across five narrow cards. */
	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item {
		position: relative;
		display: block;
		background: #fff;
		border: 1px solid var(--tsp-hairline, #E8E5DE);
		border-radius: 10px;
		overflow: hidden;
		padding: 0 0 14px;
	}

	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item-image {
		aspect-ratio: 16 / 10;
		margin-bottom: 10px;
	}

	/* Anchored to the card, not the image — the image is the card's first child
	   and bleeds to its top edge, so a fixed offset lands on the image without
	   depending on the aspect ratio resolving first. */
	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item::before {
		content: counter(tsp-trend);
		position: absolute;
		top: 8px;
		left: 8px;
		z-index: 2;
		min-width: 26px;
		height: 26px;
		display: flex;
		align-items: center;
		justify-content: center;
		border-radius: 7px;
		background: var(--tsp-accent, #C8102E);
		font-family: var(--ts-font-ui, inherit);
		font-size: 14px;
		font-weight: 700;
		color: #fff;
	}

	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item-body {
		padding: 0 12px;
	}

	/* The category reads as a chip here rather than a kicker, matching the
	   reference's weight. Kept in normal flow instead of overlaid on the image:
	   it lives inside the body element, so overlaying it would mean positioning
	   against an aspect-ratio box it is not a child of. */
	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item-category {
		display: inline-block;
		font-size: 9.5px;
		line-height: 1;
		padding: 5px 8px;
		border-radius: 4px;
		background: var(--tsp-accent, #C8102E);
		color: #fff;
		letter-spacing: .08em;
	}

	/* Three lines at 13px, not two at 14.5px. The reference's headlines are short
	   enough to land in two; the real curated ones are not, and two lines cut them
	   mid-phrase ("Opens with Strong…"), which reads cheap on a premium card. */
	.tsp-sidebar__section--trending-showcase .tsp-story-title {
		margin-top: 7px;
		font-size: 13px;
		line-height: 1.34;
		display: -webkit-box;
		-webkit-line-clamp: 3;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.tsp-sidebar__section--trending-showcase time { margin-top: 8px; font-size: 11.5px; }
}

/* ------------------------------------- tablet: 2 columns of compact rows --- */

/* The reference deliberately gets DENSER here rather than simply narrower: two
   columns of horizontal rows, thumbnail left. All five stories stay on one
   screen instead of becoming five tall cards. */
@container (min-width: 561px) and (max-width: 999px) {
	/* v1.10.286 — COLUMN flow, not row flow. trending2_tablet.png ranks 1-2-3
	   down the left column and 4-5 down the right; row flow put 1-2 across the
	   top, which makes a ranked list read in the wrong direction. Three explicit
	   rows keep the split at 3/2 for the pinned five stories, and reading down
	   each column now matches DOM order. */
	.tsp-sidebar__section--trending-showcase .tsp-sidebar__list {
		grid-auto-flow: column;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		grid-template-rows: repeat(3, auto);
		column-gap: 20px;
		row-gap: 0;
	}

	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item {
		display: grid;
		grid-template-columns: auto 96px minmax(0, 1fr);
		gap: 12px;
		align-items: stretch;
		padding: 12px 0;
		border-top: 1px solid var(--tsp-hairline, #E8E5DE);
	}

	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item::before { align-self: start; }

	/* Top of each column opens it, so neither carries a divider. With three
	   rows in column flow those are children 1 and 4 — `3n+1` states that as a
	   rule rather than hard-coding the two indices. */
	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item:nth-child(3n+1) {
		border-top: 0;
		padding-top: 0;
	}

	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item::before {
		min-width: 22px;
		height: 22px;
		font-size: 12px;
	}

	/* The thumbnail fills its row rather than holding a fixed ratio. A three-line
	   headline makes the text column ~90px tall; at 16/10 (and still at 4/3) the
	   96px-wide image came out 60-72px and left a band of dead white under every
	   picture. Stretching it squares the row off top and bottom. Both cards in a
	   grid row share that row's height, so the two columns stay level. */
	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item-image {
		aspect-ratio: auto;
		height: 100%;
		min-height: 72px;
		border-radius: 6px;
	}

	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item-category { font-size: 9.5px; }

	/* Three lines, as on desktop. The real curated headlines run 50-81 chars
	   against ~32 chars a line here, so a two-line clamp cut four of the five. */
	.tsp-sidebar__section--trending-showcase .tsp-story-title {
		margin-top: 4px;
		font-size: 13px;
		line-height: 1.32;
		display: -webkit-box;
		-webkit-line-clamp: 3;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.tsp-sidebar__section--trending-showcase time { margin-top: 5px; font-size: 11px; }
}

/* --------------------------------------------- phone: ranked feed rows ----- */

@container (max-width: 560px) {
	.tsp-sidebar__section--trending-showcase .tsp-sidebar__list {
		grid-template-columns: minmax(0, 1fr);
		gap: 0;
	}

	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item {
		display: grid;
		grid-template-columns: auto 88px minmax(0, 1fr);
		gap: 12px;
		align-items: stretch;
		padding: 11px 0;
		border-top: 1px solid var(--tsp-hairline, #E8E5DE);
	}

	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item:first-child {
		border-top: 0;
		padding-top: 0;
	}

	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item::before {
		align-self: start;
		min-width: 22px;
		height: 22px;
		font-size: 12px;
	}

	/* Fills the row — see the tablet tier. At 88px wide a 4/3 thumb was 66px
	   against a ~102px row, which read as an undersized afterthought. */
	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item-image {
		aspect-ratio: auto;
		height: 100%;
		min-height: 66px;
		border-radius: 6px;
	}

	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item-category { font-size: 9.5px; }

	/* Three lines. Two cut four of the five real headlines at 390; the title
	   column is ~216px here, so three lines clear even the 81-char one without
	   the row growing enough to break the scanning rhythm. */
	.tsp-sidebar__section--trending-showcase .tsp-story-title {
		margin-top: 3px;
		font-size: 13px;
		line-height: 1.3;
		display: -webkit-box;
		-webkit-line-clamp: 3;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.tsp-sidebar__section--trending-showcase time { margin-top: 4px; font-size: 11px; }
}

/* ------------------------------------------- small phone: tighten only ----- */

/* Same ranked feed, narrower everything.

   v1.10.286 — the chevron is GONE. It was built against the superseded
   trending_small_mobile.png; the approved trending2_small_mobile.png has no
   such affordance, and dropping it returns ~19px to the headline, which is the
   single tightest column in the whole preset. */
@container (max-width: 330px) {
	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item {
		grid-template-columns: auto 64px minmax(0, 1fr);
		gap: 9px;
		padding: 10px 0;
	}

	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item::before {
		min-width: 20px;
		height: 20px;
		border-radius: 5px;
		font-size: 11.5px;
	}

	.tsp-sidebar__section--trending-showcase .tsp-sidebar__item-image { min-height: 56px; }

	/* FOUR lines here, not three. 280px of container leaves the headline about
	   178px, and at that measure the longest curated headline still came up one
	   line short — it shipped cut at "in a Stunning…", the exact mid-phrase cut
	   the desktop tier was fixed to avoid. This is the only tier narrow enough
	   to need the fourth line. */
	.tsp-sidebar__section--trending-showcase .tsp-story-title {
		font-size: 12.5px;
		-webkit-line-clamp: 4;
	}

	.tsp-sidebar__section--trending-showcase time { font-size: 10.5px; }
}

/* ==========================================================================
   v1.10.288 — తెలుగు HIGHLIGHTS rail header

   `Article_Parts::telugu_rail()` puts the heading and the destination link in a
   shared `.tsp-nav-header`, which is `display:grid`. That header was built for a
   full-width homepage section. Dropped into a 320px template rail it broke:

       viewall  "TELUGU.TELUGUSCOPE.COM →"  white-space:nowrap  ->  244px
       heading  gets whatever is left                           ->   64px
       heading  inherits overflow-wrap:break-word               ->  HIG
                                                                    HLI
                                                                    GHT
                                                                    S

   a 144px-tall column of vertical letters. Measured on staging at 1440.

   Scoped to `.tsp-sidebar--telugu`, which is a TEMPLATE-only class — it appears
   zero times on the homepage, so none of the frozen homepage headers can be
   touched by any of this.

   Two independent guarantees, because one alone is not enough:
     1. `overflow-wrap: normal` on the heading — a word is never split, so
        vertical letters become impossible rather than merely unlikely;
     2. `flex-wrap: wrap` on the header — when both parts cannot share a line the
        link drops to its own line instead of crushing the heading.
   The type is also brought down to sidebar scale so that, at the widths this
   rail actually gets, they do fit on one line as the reference shows.
   ========================================================================== */

.tsp-sidebar--telugu .tsp-nav-header {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	column-gap: 10px;
	row-gap: 2px;
}

.tsp-sidebar--telugu .tsp-nav-header > * { min-width: 0; }

.tsp-sidebar--telugu .tsp-nav-header .tsp-section-heading,
.tsp-sidebar--telugu .tsp-nav-header h2 {
	flex: 0 1 auto;
	margin: 0;
	font-size: 15px;
	line-height: 1.25;
	overflow-wrap: normal;
	word-break: normal;
	hyphens: none;
}

.tsp-sidebar--telugu .tsp-nav-viewall--header {
	flex: 0 1 auto;
	white-space: nowrap;
	font-size: 9.5px;
	letter-spacing: .04em;
}











/* ==========================================================================
   v1.10.366 — THE SCOPE BRIEFING HEADER, ONE ROW ON PHONES
   ========================================================================== */

/* THE COLUMN GAP, NOT THE WRAP. At 390 the header measured 85px because the
   wordmark's min-content (201px), "View All" (90px) and the 14px column gap
   come to 305 in a 304px row — it wrapped by a single pixel. Closing the gap to
   8px on phones puts both on one line and takes the header to 40px.

   `flex-wrap: nowrap` was tried first and was wrong. The wrap above it is a
   deliberate collision guard: the wordmark is `nowrap`, so when the row is
   genuinely too narrow the actions must drop to their own line or the heading
   runs underneath them. Forcing one row instead clipped the wordmark outright —
   measured at 360, "The Scope Briefing" rendered 170px wide against 201px of
   text. Moving the threshold keeps the guard: the row is single where it fits
   (390 and up) and still wraps where it does not (320, 360), which costs those
   two widths the saving and is the correct trade against a cut heading.

   Viewport-scoped, NOT container-scoped, and deliberately: the desk components
   use `@container` because a desk is narrow at every width, but this must not
   fire on the desktop briefing, which is a narrow column by design. */
@media (max-width: 781.98px) {

	.tsp-sidebar-wrap--briefing .tsp-nav-header {
		column-gap: 8px;
	}
}

/* ==========================================================================
   v1.10.371 — THE SCOPE BRIEFING, HEADLINES THAT FINISH ON PHONES
   ========================================================================== */

/* All five headlines were being cut at 390. Measured: the row is a
   `30px 76px 163px` grid with 9px gaps, the title is 13.5px/1.34 and the clamp
   is 2 — and every live headline needs three or four lines in a 163px column.
   "Minister Urges Officials to Achieve Swarna Kadapa 2047 Dev…" cut a proper
   noun; "…added to the prohibited…" lost its object. A panel billed as "5
   stories you need to know" has to let the reader know them.

   Width first, then the clamp. The rank track is 30px around a 26px circle and
   the thumbnail is 76px, so four pixels of rank, ten of thumbnail and one from
   each gap return 16px to the headline — 163px becomes ~179px — before a single
   line is added. The thumbnail stays large enough to identify the story.

   WHY THE NESTED CONTAINER QUERY. There is an existing `@container (max-width:
   300px)` tier that hides the thumbnail entirely and gives the headline the
   full row. That tier is live at 320 (the panel is ~232px there) but not at 375
   or 390 (the panel is 302px — it misses the 300px switch by two pixels, which
   is the whole reason these headlines cut). Re-declaring the three-track grid
   unconditionally would re-introduce a thumbnail column into a tier designed
   without one, so the track change is fenced above 300px and only the clamp is
   unconditional — which is safe, because that tier already sets 3.

   `@media`, not `@container`, for the outer scope: the desktop briefing panel
   measures 418px, so `@container (max-width: 420px)` fires on DESKTOP. A
   container query here is not a mobile query. */
/* The clamp runs the whole phone range: there is no width below the desktop
   breakpoint where two lines are enough.

   THE ROW HAS TO GROW WITH IT. The list is a fixed grid --
   `repeat(5, var(--tsp-brief-row, 96px))` -- and the item is `overflow:
   visible`, so a third line does not make the row taller, it makes the content
   hang out of the bottom of it. Shipping the clamp alone put each row's date
   17px below its own row, where the NEXT row's kicker badge painted straight
   over it: five collisions down the panel, clearly visible at 360 and 375 and
   invisible to every height measurement, because the row still measured 96 and
   the section still measured 597.

   116px is the measured minimum that brings the spill to zero at every phone
   width. It costs the panel 100px, which is what five headlines that actually
   read are worth. Fenced above 300px so the existing thumbnail-free tier keeps
   the 104px it was tuned to. */
@media (max-width: 781.98px) {
	.tsp-sidebar__section--scope-briefing .tsp-story-title {
		-webkit-line-clamp: 3;
	}

	@container (min-width: 300.02px) {
		.tsp-sidebar-wrap--briefing .tsp-sidebar {
			--tsp-brief-row: 116px;
		}
	}
}

/* v1.10.424 — the phone rail keeps the dense size, and the row is re-tuned.
 *
 * THE SPILL WAS ALREADY HAPPENING. Measured on staging at the ORIGINAL 13.5px,
 * before any of this typography work: 26px of spill at 320, 32px at 360, 11px
 * at 375 and 390, with three to four rows whose date was painted over by the
 * next row's kicker. The 116px above was tuned against a shorter headline set
 * and the panel has been colliding since. Every height measurement still read
 * 580, which is exactly why it survived.
 *
 * 16px makes it worse, so the Briefing does NOT take 16px here. A 2D sweep of
 * size against row height across 320 / 360 / 375 / 390 found 360 to be the
 * binding width — its rail is 302px, two pixels above the tier that would drop
 * the thumbnail and give the headline the full row:
 *
 *     15.0px + 140px   clean at 320, 360, 375, 390
 *     15.5px + 152px   clean at 320, 360, 375, 390
 *     16.0px + 152px   still 3px of spill and three collisions at 360
 *
 * So the phone rail runs at the dense size and 152px: the collisions go to
 * zero, and the headline is still 2px larger than it was before this work.
 * Desktop keeps the full 16px, where it costs nothing.
 *
 * Fenced at 480 rather than 782 because 600 and 768 do not spill — their
 * headlines fit in two lines — and a taller row there would only add dead
 * space. Both container tiers are set: the ~232px rail at 320 has no thumbnail
 * and its own row value, and it spills too. */
@media (max-width: 480px) {
	.tsp-sidebar-wrap--briefing {
		--ts-title-brief: var(--ts-title-dense);
	}

	/* A fourth line, once the row above has the height to hold it. Measured
	   against the re-tuned 152px row: spill stays at zero, the panel does NOT
	   grow — 760px either way — and truncation goes from four headlines to none
	   at 320, 375 and 390, and from five to two at 360. The row was already
	   paying for the space; the clamp was simply not spending it. */
	.tsp-sidebar__section--scope-briefing .tsp-story-title {
		-webkit-line-clamp: 4;
	}

	.tsp-sidebar-wrap--briefing .tsp-sidebar {
		--tsp-brief-row: 152px;
	}

	@container (min-width: 300.02px) {
		.tsp-sidebar-wrap--briefing .tsp-sidebar {
			--tsp-brief-row: 152px;
		}
	}
}

/* The WIDTH reclaim is fenced to phones, and the image is resized with its
   track rather than only the track.

   Both halves were learned by measuring. Changing the track alone left the
   image at its own declared width -- 76px in a 66px track at 390, and 96px in
   it from 600 up -- so the picture overflowed and sat on the headline: 2px at
   390, and 22px at 600 and 781. Grid tracks do not clip their contents.

   And the reclaim is only wanted where the headline is short of room. At 600+
   the headline column is already 562px with nothing to fix, and the wider tier
   deliberately shows a 96px thumbnail; shrinking that to 66 would be a
   downgrade bought for nothing. So the reclaim stops at 520px, and above it the
   original tracks and thumbnail stand. */
@media (max-width: 520px) {
	@container (min-width: 300.02px) {
		/* v1.10.425 — the headline column was 20px short of a three-line fit.
		 *
		 * Measured on staging at 375 and 390: the Briefing headline needs 186px
		 * to land on three lines and the row was handing it 164-179, so four of
		 * five ran to four lines. The shortfall is small and it is geometry, not
		 * type — so the rank column, the thumbnail and the gap each give a
		 * little back rather than the headline getting smaller.
		 *
		 * 26>20 rank, 66>50 thumbnail, 8>7 gap returns 24px, which clears 186 at
		 * 375 and leaves real margin at 390 and 430. The thumbnail stays large
		 * enough to identify a story; the tier above still shows 96px. */
		.tsp-sidebar__section--scope-briefing .tsp-sidebar__item {
			grid-template-columns: 20px 50px minmax(0, 1fr);
			column-gap: 7px;
		}
		.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-image {
			width: 50px;
		}
	}
}

/* ==========================================================================
   v1.10.375 — THE SCOPE BRIEFING WORDMARK, 13.5px ON PHONES
   ========================================================================== */

/* The header row had exactly ZERO slack. Measured on a real iPhone 13 Pro Max
   viewport in WebKit: wordmark 244px + "View All" 90px + 8px gap = 342px, in a
   342px row. It fits by nothing at all, so any narrowing of the effective
   viewport — Safari page zoom being the obvious one, since nothing here sets
   `-webkit-text-size-adjust` — tips it over and `flex-wrap` drops the link onto
   a row of its own.

   That is what the device report described: a detached "View All", dead space
   after the subtitle, and a long run-in to story 1. Measured at 375: header
   85px instead of 40, subtitle-to-story-1 67px instead of 21, panel 742 instead
   of 697. The heading's `clamp()` floor of 15px is the binding constraint —
   shrinking the LINK instead was tested and changes nothing, because the link
   was never what filled the row.

   13.5px carries the single row down to 375, which covers the device at its
   native 428 and through roughly 114% Safari zoom. Below about 370 a single row
   is geometrically impossible: at 344 the row is 258px and the wordmark alone
   wants ~244px, so no type size short of illegible would seat the link beside
   it. The two-row fallback stands there deliberately, and nothing else about
   the panel changes — rows, clamps, thumbnails, numbering, the active red
   treatment and the link's own dimensions are all untouched, as is desktop. */
@media (max-width: 781.98px) {
	.tsp-sidebar-wrap--briefing .tsp-section-heading {
		font-size: 13.5px;
	}
}

/* ==========================================================================
   v1.10.427 — Scope Briefing width utilisation.

   The owner sees unused space to the right of the headlines on desktop. The
   headline column is NOT the culprit: measured, the text already fills its
   track to the pixel (0px slack at every desktop width). The width is going to
   the panel's own chrome before the track is even computed.

   At 1366 the 464px panel spends 46px on aside padding and border, 22px on the
   row's own inline padding, 30px on a rank column holding a 26px circle, 18px
   on two gaps and 96px on the thumbnail — leaving 249px of the 464 for the
   headline, which is why three lines was the normal outcome.

   Recovered here, cheapest first, and each value has a reason:
     aside padding   22 > 14   the panel keeps a clear gutter, not a margin
     row padding     12/10 > 8 also fixes an asymmetry nobody intended
     rank track      30 > 26   the circle IS 26px border-box, so this is exact
     column gap       9 > 8
     thumbnail       96 > 88   still a legible crop at this size

   Result at 1366 and 1440: headline 249 > 285px and FOUR of five headlines land
   on two lines instead of one. The panel also gets shorter — 656 > 589 — so the
   width recovery costs no vertical space at all.

   The Hero <-> Briefing gutter was inspected as asked and left alone: it
   measures 0px. Hero 696 + Briefing 464 already equals the 1160px content
   width at 1366, so there is nothing there to take, and the parent grid is
   untouched.
   ========================================================================== */

@media (min-width: 481px) {
	.tsp-sidebar-wrap--briefing .tsp-sidebar.tsp-sidebar--single {
		padding-inline: 14px;
	}
}

/* Container-based, not viewport-based: the panel's width is what decides this,
   and it is ~394px beside the Hero at 1024 but 682px stacked at 768. The
   existing tiers already switch on the container, and this keeps that. */
@container (min-width: 420.02px) {
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item {
		grid-template-columns: 26px 88px minmax(0, 1fr);
		column-gap: 8px;
		padding-inline: 8px;
	}
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-image {
		width: 88px;
	}
}

/* The narrower desktop tier keeps its 76px thumbnail — at a 394px panel that
   picture is already small, and the rank track and padding are where the slack
   is.
 *
 * The `@media (min-width: 481px)` fence is load bearing and was added after
 * measuring, not before. A phone's Briefing panel is 307px at 375 and 322px at
 * 390 — squarely inside this 300-420px container range — so without the fence
 * this desktop rule reached the phones and replaced their deliberate 50px
 * thumbnail with a 76px one. Measured: the headline fell from 208px to 174px at
 * 375 and back to four lines, undoing the previous patch. The container query
 * describes the PANEL; the media query says which device the panel is on. */
@media (min-width: 481px) {
	@container (min-width: 300.02px) and (max-width: 420px) {
		.tsp-sidebar__section--scope-briefing .tsp-sidebar__item {
			grid-template-columns: 26px 76px minmax(0, 1fr);
			column-gap: 8px;
		}
	}
}

/* ==========================================================================
   v1.10.428 — Scope Briefing mobile spacing: separate the rank from the picture.

   The owner is right that the number and thumbnail touch, and the cause is not
   the gap — it is the rank TRACK. The circle is drawn as a ::before and renders
   26px wide inside a 20px track, so it overflows 6px into the column gap that
   follows it. A declared 7px gap therefore paints as FOUR pixels of separation,
   which is why rows read as (1)[IMAGE] rather than (1) [IMAGE].

   Measured before, per row, at 360-430:
     edge > rank     6px
     rank > image    4px   <- the complaint
     image > head    7px
     headline      193-263px, right slack 0

   Fixed by sizing the track to the circle rather than by widening the gap:
     rank track   20 > 26px   the circle is 26px, so it now fits its own column
     column gap    7 > 10px
     row padding   6 > 2px   this alone funds it; the thumbnail is NOT touched
     panel padding 12 > 10px  still a deliberate outer gutter, not edge-to-edge

   After: rank > image 13px, image > headline 10px, and the headline column is
   UNCHANGED at 208 / 223 / 263px.

   The thumbnail was briefly taken to 46px to fund this and then put back. Its
   box declares aspect-ratio 4/3 but an explicit height:48px overrides that, so
   narrowing the width silently reshaped the box from 50x48 to 46x48 — no
   distortion, object-fit is cover, but a shape change all the same, and the
   brief lists the thumbnail ratio under Preserve. Two pixels of row padding buy
   the same result and leave the picture exactly as it was.

   That is the honest ceiling: in a ~310px row you can have correct separation
   at no cost to the headline, but not correct separation AND a materially wider
   headline. The width is simply not there.

   Typography, the rank-circle design, the thumbnail aspect ratio, the active
   row's red treatment, dates, ordering and desktop are all untouched: this
   block is fenced to phones and changes only tracks, gaps and padding.
   ========================================================================== */
@media (max-width: 480px) {
	.tsp-sidebar-wrap--briefing .tsp-sidebar.tsp-sidebar--single {
		padding-inline: 10px;
	}

	/* The tier that carries a thumbnail. */
	@container (min-width: 300.02px) {
		.tsp-sidebar__section--scope-briefing .tsp-sidebar__item {
			grid-template-columns: 26px 50px minmax(0, 1fr);
			column-gap: 10px;
			padding-inline: 2px;
		}
	}

	/* The narrowest tier hides the thumbnail, so only the rank column and the
	   gap matter — but the circle was overflowing its 24px track here too. */
	@container (max-width: 300px) {
		.tsp-sidebar__section--scope-briefing .tsp-sidebar__item {
			grid-template-columns: 26px minmax(0, 1fr);
			column-gap: 10px;
		}
	}
}

/* ==========================================================================
   v1.10.476 — THE PHONE ROW STOPS PAYING FOR A FOURTH LINE
   --------------------------------------------------------------------------
   Measured on staging at 390 before this block: row 152px, body 114px. Every
   row carried ~38px it never used, five times over, and the panel ran to 875px.
   The 152px was sized for a four-line clamp that the real headlines do not
   reach — the five stories set 3, 3, 3, 2 and 3 lines.

   WHY THE HEADLINE IS NOT GETTING WIDER INSTEAD. That was tried first and
   measured, by widening the headline track in the live DOM and counting lines:

       225px (today)  3 3 3 2 3
       245px          3 3 3 2 3      <- the whole available reclaim buys nothing
       255px          3 3 3 2 2
       275px          2 2 3 2 2      <- where "mostly two lines" actually starts

   Two-line headlines need ~275px, which is +50. Panel padding, both gaps and
   the rank track together return about +20 — not enough to cross a single
   threshold — and the rest could only come from the 26px rank circle, the 50px
   thumbnail or the page gutter, all of which the brief protects. So the width
   is spent where it does change something (+12px, which tips headlines at 430)
   and the real gain is taken vertically, where 38px per row was going spare.

   The clamp drops 4 -> 3 for the same reason: nothing reaches four lines, and
   leaving the allowance there is what made the row tall in the first place.
   Three lines remain available for genuinely long copy, which is what the brief
   asks for. No typography changes: the headline stays at 15.5px.
   ========================================================================== */
@media (max-width: 480px) {
	/* Fits three lines exactly: kicker 17 + 5, headline 3x21.7 = 65, timestamp
	   4 + 16 = 107, plus 20px of item padding. 128 leaves a pixel of air. */
	.tsp-sidebar-wrap--briefing .tsp-sidebar { --tsp-brief-row: 128px; }

	@container (min-width: 300.02px) {
		.tsp-sidebar-wrap--briefing .tsp-sidebar { --tsp-brief-row: 128px; }
	}

	/* Nothing renders four lines; the allowance only bought height. */
	.tsp-sidebar__section--scope-briefing .tsp-story-title {
		-webkit-line-clamp: 3;
	}

	/* +12px to the headline: 3px off each panel side, 2px off each gap, 2px off
	   the rank track. The circle is 22px inside a 24px track, so it still has
	   its own room — this is the track, not the badge. */
	.tsp-sidebar-wrap--briefing .tsp-sidebar.tsp-sidebar--single {
		padding-inline: 7px;
	}

	@container (min-width: 300.02px) {
		.tsp-sidebar__section--scope-briefing .tsp-sidebar__item {
			grid-template-columns: 24px 50px minmax(0, 1fr);
			column-gap: 8px;
		}
	}
}

/* ==========================================================================
   v1.10.482 — THE BRIEFING MEETS THE HERO
   --------------------------------------------------------------------------
   With the standfirst rendering (hero v1.10.481) the Hero became the taller
   column: measured at 1536, card 732 against a 674 Briefing. The mismatch
   simply changed sign — it used to finish 83px short, now it overshoots by 58.

   The Gutenberg columns already stretch to the tallest sibling; the Briefing
   WRAP was not taking that height because it is a block inside the column, so
   the panel stopped at its own content height. Passing the height through the
   wrap to the panel makes the two cards end level.

   THE LIST IS PINNED AT `flex: 0 0 auto`, AND THAT IS THE WHOLE SAFETY OF THIS.
   The panel is a flex column. If the list were allowed to grow it would take
   the slack, the five rows would divide a larger track, the rows would get
   taller, the content would get taller, and the panel would grow again — the
   exact feedback loop documented at the top of this file, which once settled
   the panel at 888px instead of 440. Fixed-basis list, and the spare height
   lands harmlessly beneath the last row.
   ========================================================================== */
.tsp-sidebar-wrap--briefing { height: 100%; }
.tsp-sidebar-wrap--briefing .tsp-sidebar { height: 100%; }
.tsp-sidebar-wrap--briefing .tsp-sidebar__list { flex: 0 0 auto; }

/* ==========================================================================
   v1.10.486 — ONE META LINE: THE BRIEFING ROW
   --------------------------------------------------------------------------
   Audited on the deployed page, the 113px row spends its height like this:

     item padding      9 + 9   = 18
     category         17 + 5   = 22
     headline         45  (two lines, 16px — the content)
     timestamp         4 + 16  = 20
                              --- 105 (+ rounding = 113)

   The headline is 45 of it. The two pieces of metadata are 42 — nearly as much
   as the story — and they are stacked one above the other with the headline in
   between, so each costs a full line of the row.

   A category and a date are both short, both metadata, and belong on the same
   line. Putting them there removes one line per row and takes ~20px out of each
   of five rows without touching type, thumbnail, ranking or reading order.

   DONE IN CSS, NOT MARKUP. Grid areas re-flow the three existing children in
   place, so the renderer, the DOM order and the accessibility tree are all
   unchanged — the timestamp still follows the headline for a screen reader,
   it simply paints beside the category. Scoped to `--scope-briefing`, so the
   Trending rail, the cross-edition strip and every other sidebar preset that
   shares `.tsp-sidebar__item-body` are untouched.
   ========================================================================== */
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-body {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	grid-template-areas:
		"kicker when"
		"title  title";
	align-items: center;
	column-gap: 10px;
	row-gap: 5px;
}

.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-category {
	grid-area: kicker;
	margin: 0;
}

.tsp-sidebar__section--scope-briefing .tsp-story-title {
	grid-area: title;
	margin: 0;
}

.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-body time {
	grid-area: when;
	justify-self: start;
	margin: 0;
}

/* The row no longer needs to be tall enough for three stacked blocks. */
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item {
	padding-block: 8px;
}

/* v1.10.489 — the phone row stops reserving the line it no longer holds.
   `--tsp-brief-row` is a FIXED grid track (the file explains at length why it
   cannot be content-derived without the panel feeding back on itself), so One
   Meta Line freed a whole line inside a row that still measured 128.

   SIZE THIS AGAINST THREE LINES, NOT TWO. v1.10.488 set 92px off a row whose
   headline happened to wrap to two lines. This breakpoint clamps the title to
   THREE (see the clamp above -- there is no phone width where two are enough),
   and four of the five live headlines use all three. Measured at 390: 8px top
   padding + a 22px meta line + 5px gap + a three-line 65px headline + 8px
   bottom padding = 103. At 92 the body overhung its own row by 2.9px on every
   three-line story and crossed into the next row's box -- the v1.10.424
   collision again, in miniature, and invisible to the section height because
   the item is `overflow: visible` and the row still measured 92.

   104 restores the symmetric 8px below the last line and still returns 24px a
   row against the 128 this replaced. */
@media (max-width: 480px) {
	.tsp-sidebar-wrap--briefing .tsp-sidebar { --tsp-brief-row: 104px; }
	@container (min-width: 300.02px) {
		.tsp-sidebar-wrap--briefing .tsp-sidebar { --tsp-brief-row: 104px; }
	}
}

/* ==========================================================================
   v1.10.495 — THE DESKTOP SCOPE BRIEFING IS A RANKED EDITORIAL INDEX.

   Five equal rows, 01-05, and exactly one photograph: the active story's.
   #01 is active until the pointer or the keyboard says otherwise.

   THE INACTIVE ROW GIVES THE WIDTH BACK. This is the point, and it is why the
   mechanism is `display` and `grid-template-columns` rather than `visibility`
   or `opacity`: those hide the thumbnail while it still occupies its column,
   which leaves the headline indented behind an empty gutter and reads as a
   broken card rather than a text index. An inactive row drops the column
   entirely and the headline reclaims all 96px of it.

   HEIGHT STILL CANNOT MOVE. Row height is a FIXED grid track
   (`--tsp-brief-row`), and the headline is clamped to two lines, so the text
   is the same height whether it is 286px wide or 382px. Removing a COLUMN
   cannot change a fixed ROW. That is what keeps the component's outer height
   identical in all five active states -- it is structural, not tuned.

   NO SPECIFICITY WAR. #01's default is conditioned on nothing else being
   engaged, so the default rule and the engaged rule are never both true for
   different rows. An earlier attempt fought this out with `:has()` plus
   `:not()` overrides and lost: the item-level rules applied while the
   descendant image rules did not, on staging, with the selector verifiably
   matching. Conditioning the default removes the contest instead of trying to
   win it.

   SCOPE. Desktop only. Every rule is inside `min-width: 1024px`, so the
   approved phone composition -- five thumbnails, circular ranks, #01 washed --
   cannot be reached. The 782-1023 touch band keeps its existing behaviour too.
   ========================================================================== */

@media (min-width: 1024px) {

	/* A rhythm, not a list. Fixed track: nothing below can change it. */
	.tsp-sidebar-wrap--briefing .tsp-sidebar { --tsp-brief-row: 76px; }
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item { padding-block: 7px; }

	/* Two lines, always. One story running to three made its row 106px against
	   its neighbours' 96 -- a broken rhythm, and fatal to an index whose whole
	   identity is the ranking. */
	.tsp-sidebar__section--scope-briefing .tsp-story-title {
		font-size: 15px;
		line-height: 1.4;
		-webkit-line-clamp: 2;
	}

	/* THE COMPACT SHAPE IS THE DEFAULT. Rank, then content. No third column. */
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item {
		grid-template-columns: 26px minmax(0, 1fr);
	}
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-image {
		display: none;
	}

	/* THE ACTIVE SHAPE. Rank, photograph, content. */
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:not(:has(.tsp-sidebar__item:focus-within)) .tsp-sidebar__item:first-child,
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:focus-within {
		grid-template-columns: 26px 88px minmax(0, 1fr);
	}
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:not(:has(.tsp-sidebar__item:focus-within)) .tsp-sidebar__item:first-child .tsp-sidebar__item-image,
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:focus-within .tsp-sidebar__item-image {
		display: block;
	}

	/* The wash, the rail and the ranking numeral travel with it. */
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:focus-within {
		border-left-color: var(--ts-red, #C8102E);
		background: linear-gradient(90deg, rgba(200, 16, 46, .17) 0%, rgba(200, 16, 46, .05) 55%, rgba(200, 16, 46, 0) 100%);
	}
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:focus-within::before {
		border-color: var(--ts-red, #C8102E);
		color: var(--ts-red, #C8102E);
	}
	/* #01 gives up the wash the moment another row is focused. */
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:has(.tsp-sidebar__item:focus-within) .tsp-sidebar__item:first-child:not(:focus-within) {
		border-left-color: transparent;
		background: none;
	}
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:has(.tsp-sidebar__item:focus-within) .tsp-sidebar__item:first-child:not(:focus-within)::before {
		border-color: var(--tsp-brief-rank-border, #d7dbe2);
		color: var(--tsp-brief-rank-color, #6b7280);
	}
}

/* The pointer half, gated so a touch tablet never depends on hover to see a
   picture, and so a sticky touch-hover cannot strand the index. Declared after
   the base tier and carrying one more `:not()`, so on a fine-pointer device
   these win and the two conditions combine: #01 is active only while NEITHER
   the pointer nor the keyboard is engaged anywhere in the list. */
@media (min-width: 1024px) and (hover: hover) and (pointer: fine) {

	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:not(:has(.tsp-sidebar__item:hover)):not(:has(.tsp-sidebar__item:focus-within)) .tsp-sidebar__item:first-child,
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:hover {
		grid-template-columns: 26px 88px minmax(0, 1fr);
	}
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:not(:has(.tsp-sidebar__item:hover)):not(:has(.tsp-sidebar__item:focus-within)) .tsp-sidebar__item:first-child .tsp-sidebar__item-image,
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:hover .tsp-sidebar__item-image {
		display: block;
	}
	/* ...and when the pointer IS engaged elsewhere, #01 takes the compact shape
	   like any other inactive row. */
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:has(.tsp-sidebar__item:hover) .tsp-sidebar__item:first-child:not(:hover) {
		grid-template-columns: 26px minmax(0, 1fr);
		border-left-color: transparent;
		background: none;
	}
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:has(.tsp-sidebar__item:hover) .tsp-sidebar__item:first-child:not(:hover) .tsp-sidebar__item-image {
		display: none;
	}
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:has(.tsp-sidebar__item:hover) .tsp-sidebar__item:first-child:not(:hover)::before {
		border-color: var(--tsp-brief-rank-border, #d7dbe2);
		color: var(--tsp-brief-rank-color, #6b7280);
	}
}

/* v1.10.496 — the last 9px of reserved space.

   1.10.495 dropped the thumbnail and the headline moved 88px left, but the
   computed template still read `26px 0px 422px`: the body is explicitly placed
   in `grid-column: 3` (see the v1.10.273 tier), so a two-track template just
   left an empty third track and grid still paid the 9px `gap` on either side
   of it. The row was 9px short of a true text index.

   Re-placing the body in column 2 when the row is compact is how the file's
   own image-less tier already solves this, so this follows it rather than
   inventing a second mechanism. */
@media (min-width: 1024px) {
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-body { grid-column: 2; }

	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:not(:has(.tsp-sidebar__item:focus-within)) .tsp-sidebar__item:first-child .tsp-sidebar__item-body,
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:focus-within .tsp-sidebar__item-body {
		grid-column: 3;
	}
}
@media (min-width: 1024px) and (hover: hover) and (pointer: fine) {
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:not(:has(.tsp-sidebar__item:hover)):not(:has(.tsp-sidebar__item:focus-within)) .tsp-sidebar__item:first-child .tsp-sidebar__item-body,
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:hover .tsp-sidebar__item-body {
		grid-column: 3;
	}
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:has(.tsp-sidebar__item:hover) .tsp-sidebar__item:first-child:not(:hover) .tsp-sidebar__item-body {
		grid-column: 2;
	}
}

/* v1.10.497 — THE ROW TRACK MUST BE FIXED, not `minmax(row, auto)`.

   Releasing the thumbnail column made this urgent. A compact row is 96px wider,
   so a headline that needed two lines while the row was active can fall to one
   line once it is inactive -- measured on staging, row 4 went 82px -> 76px and
   the component went 519 -> 514 purely because the active row moved. That is
   the layout shift the interaction is required never to produce, arriving
   through the text rather than through the picture.

   An `auto` track lets content decide the height, and the content's width now
   depends on the active state. The two facts cannot both stand. 84px holds the
   measured two-line body (68px) plus its 14px of padding with 2px to spare, so
   every row is the same height whether its headline runs to one line or two,
   and five rows are 420px in every one of the five active states. */
@media (min-width: 1024px) {
	.tsp-sidebar-wrap--briefing .tsp-sidebar { --tsp-brief-row: 84px; }
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list {
		grid-template-rows: repeat(var(--tsp-nav-rows, 5), var(--tsp-brief-row, 84px));
	}
}

/* v1.10.502 — an active story with no photograph must not open a column for it.

   Found on the Telugu edition, where story #01 has no featured image at all:
   `hasImgEl` reads 01111. #01 is the DEFAULT active row, so the active shape
   was giving it `26px 88px minmax(0,1fr)` and placing its body in column 3 --
   an 88px track with nothing in it, which is precisely the reserved empty
   gutter this design removed everywhere else. English never showed it because
   all five of its stories carry a thumbnail.

   The condition is the element, not the state: a row that has no image takes
   the compact shape whatever its active state. These mirror each active
   selector with `:not(:has(...))`, so they carry one more compound and are
   declared later -- they win without needing `!important`. The wash, the rail
   and the ranking numeral still move to the row, because it is still the
   active story; only the column it cannot fill goes away. */
@media (min-width: 1024px) {
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:not(:has(.tsp-sidebar__item:focus-within)) .tsp-sidebar__item:first-child:not(:has(.tsp-sidebar__item-image)),
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:focus-within:not(:has(.tsp-sidebar__item-image)) {
		grid-template-columns: 26px minmax(0, 1fr);
	}
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:not(:has(.tsp-sidebar__item:focus-within)) .tsp-sidebar__item:first-child:not(:has(.tsp-sidebar__item-image)) .tsp-sidebar__item-body,
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:focus-within:not(:has(.tsp-sidebar__item-image)) .tsp-sidebar__item-body {
		grid-column: 2;
	}
}
@media (min-width: 1024px) and (hover: hover) and (pointer: fine) {
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:not(:has(.tsp-sidebar__item:hover)):not(:has(.tsp-sidebar__item:focus-within)) .tsp-sidebar__item:first-child:not(:has(.tsp-sidebar__item-image)),
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:hover:not(:has(.tsp-sidebar__item-image)) {
		grid-template-columns: 26px minmax(0, 1fr);
	}
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__list:not(:has(.tsp-sidebar__item:hover)):not(:has(.tsp-sidebar__item:focus-within)) .tsp-sidebar__item:first-child:not(:has(.tsp-sidebar__item-image)) .tsp-sidebar__item-body,
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item:hover:not(:has(.tsp-sidebar__item-image)) .tsp-sidebar__item-body {
		grid-column: 2;
	}
}

/* ==========================================================================
   v1.10.507 — THE BRIEFING FINISHES AFTER STORY 5, AND THE TIMESTAMP MOVES
   UNDER THE HEADLINE.

   TWO CHANGES, ONE ROOT CAUSE BETWEEN THEM.

   1. The dead space. v1.10.482 gave the wrap `height:100%` so the Briefing
      panel would end level with the Hero, and its own comment accepted that
      "the spare height lands harmlessly beneath the last row". That was true
      while the Hero was a photograph plus a text panel that grew to meet it.
      It stopped being true at v1.10.490, when the Hero became a card that
      declares its own ratio: the Briefing is now stretched to a height it has
      no content for, and the slack shows as 77px of empty panel under Story 5
      (measured at 1920 — wrap 584, five 84px rows ending at 420).

      So the stretch is released rather than counter-balanced. No filler, no
      min-height, no matching the Hero: the component is as tall as five rows
      and a header, and stops.

   2. The hierarchy. With the panel no longer padded out, the row can spend a
      line on something useful. `CATEGORY / headline / timestamp` reads as a
      ranked index entry; the timestamp under the headline is the line a reader
      checks after deciding they care, which is where it belongs.

      Still CSS-only, still grid areas over the SAME three children, so the
      renderer, the DOM order and the accessibility tree are untouched — and
      the timestamp is still the real `human_time_diff` value the section
      already rendered. Nothing here invents or reformats a date.

   DESKTOP ONLY. Every rule is inside `min-width: 1024px`, so the approved
   phone composition keeps One Meta Line, its 104px rows and its five
   thumbnails exactly as they are.
   ========================================================================== */

@media (min-width: 1024px) {

	/* 1 — the component finishes naturally. */
	.tsp-sidebar-wrap--briefing,
	.tsp-sidebar-wrap--briefing .tsp-sidebar {
		height: auto;
	}

	/* 2 — kicker, headline, then the time. One column, three rows.
	   The row track stays FIXED (see v1.10.497): hovering changes the text
	   column's width, which can change the headline's line count, and an `auto`
	   track would let that resize the component mid-interaction. 100px is the
	   measured content — 17 kicker + 42 two-line headline + 16 time + 10 of
	   row-gap + 14 padding = 99, with a pixel to spare. */
	.tsp-sidebar-wrap--briefing .tsp-sidebar { --tsp-brief-row: 100px; }

	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-body {
		grid-template-columns: minmax(0, 1fr);
		grid-template-areas:
			"kicker"
			"title"
			"when";
		align-items: start;
		align-content: center;
		column-gap: 0;
		row-gap: 5px;
	}
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-body time {
		grid-area: when;
		justify-self: start;
	}
}

/* v1.10.508 — the fixed row track was never actually fixed.

   v1.10.497 declared `repeat(5, var(--tsp-brief-row))` on
   `.tsp-sidebar__section--scope-briefing .tsp-sidebar__list` — (0,2,0) — against
   the tier at the top of this file which declares
   `repeat(5, minmax(var(--tsp-brief-row), auto))` on
   `.tsp-sidebar-wrap--briefing .tsp-sidebar--single.tsp-nav-enabled
   .tsp-sidebar__list` — (0,4,0). The shorter selector lost, and this file's own
   comment beside that rule predicts precisely this: "a shorter selector here
   would simply lose and the fix would look applied while changing nothing."

   It looked correct for eleven versions because every row's content fitted
   under the 84px floor, so `minmax(84, auto)` and `repeat(5, 84px)` render
   identically. Adding the timestamp line pushed the content past the floor and
   the `auto` half took over: measured 102.984 / 102.984 / 102.984 / 100 / 100 —
   rows sized by their headline's line count.

   THAT IS THE LAYOUT-SHIFT BUG, LIVE. The active row's text column is 96px
   narrower than a compact one, so moving the active state can change a
   headline's line count, and an `auto` track turns that into a height change
   for the whole component mid-hover.

   Matching the (0,4,0) selector is the fix. 104px is the measured worst case:
   88px of body at the two-line clamp plus 14px of padding, with headroom. */
@media (min-width: 1024px) {
	.tsp-sidebar-wrap--briefing .tsp-sidebar { --tsp-brief-row: 104px; }
	.tsp-sidebar-wrap--briefing .tsp-sidebar--single.tsp-nav-enabled .tsp-sidebar__list {
		grid-template-rows: repeat(var(--tsp-nav-rows, 5), var(--tsp-brief-row, 104px));
	}
}

/* v1.10.509 — the kicker is a chip, not a bar. Again.

   v1.10.507 moved the row body from `"kicker when" / "title title"` to a
   single `minmax(0,1fr)` column. In the two-column form the kicker sat in an
   `auto` track and hugged its text; in a 1fr track a grid item's default
   `justify-self: stretch` fills the whole column, so every category rendered
   as a full-width red bar across the row.

   The same mistake in its flex form was fixed at v1.10.483 with
   `align-self: flex-start`. Recording it here because the cause is one level
   up from the property: a chip must always opt out of the stretch its
   container hands it, whichever layout system that container happens to use. */
@media (min-width: 1024px) {
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-category {
		justify-self: start;
	}
}

/* ==========================================================================
   v1.10.518 — ONE BOTTOM BASELINE, PAID FOR OUT OF BRIEFING DENSITY.

   Owner review of v1.10.507: moving the timestamp under the headline added a
   line to all five rows and the Briefing overtook the Hero. The Hero's
   architecture, crop and height are approved and are not to be touched, so the
   correction is entirely inside the Briefing.

   TWO CHANGES.

   1. THE META GOES BACK ON ONE LINE. `CATEGORY  ◷ date` above the headline,
      for active and inactive rows alike. This is the v1.10.486 treatment,
      restored: a category and a date are both short, both metadata, and cost a
      full line of every row when stacked.

   2. THE PANEL TAKES THE ROW HEIGHT AGAIN, and the rows divide it.

      v1.10.482 did this and v1.10.507 removed it, correctly at the time: the
      panel was being stretched to a height it had no content for and the slack
      showed as dead space under Story 5. Restoring it is only safe because of
      what changed in between — the rows now DIVIDE the available height
      (`1fr`) instead of sitting at a fixed 104px inside it. There is no slack
      left to strand, because the content grows to meet the panel.

      AND THIS TIME IT CANNOT LOOP. The warning at v1.10.482 — rows grow,
      content grows, panel grows, rows grow again, settling at 888px — needed
      the panel's height to be content-derived. It is not: the panel takes the
      Gutenberg row's height, the row's height is the Hero's, and the Hero's is
      its own column width over its own ratio. Nothing in that chain reads the
      Briefing. The input is independent, so the division is stable.

      `minmax(min-content, 1fr)` rather than plain `1fr` is the guard: when the
      Hero is short enough that five rows cannot fit, a row stops at its
      content rather than spilling into the next one's kicker — the v1.10.424
      collision. In that case the Briefing ends slightly below the Hero, which
      is the honest failure and is reported rather than hidden.

   ZERO LAYOUT SHIFT ON HOVER IS NOW STRUCTURAL. The outer height is the Hero's
   height. Moving the active row changes which row carries a thumbnail and how
   wide the text column is; it cannot change a height that is set by a sibling.

   DESKTOP ONLY. Everything is inside `min-width: 1024px`, so the approved
   phone composition — five thumbnails, circular ranks, 104px rows, three-line
   clamp — is untouched.
   ========================================================================== */

@media (min-width: 1024px) {

	/* --- the panel fills the row, and the list fills the panel ----------- */
	.tsp-sidebar-wrap--briefing,
	.tsp-sidebar-wrap--briefing .tsp-sidebar {
		height: 100%;
	}
	.tsp-sidebar-wrap--briefing .tsp-sidebar__list {
		flex: 1 1 auto;
		min-height: 0;
	}

	/* The (0,4,0) selector, deliberately: the tier at the top of this file
	   declares `grid-template-rows` at that weight and a shorter selector here
	   would lose silently — see v1.10.508, which cost eleven versions. */
	.tsp-sidebar-wrap--briefing .tsp-sidebar--single.tsp-nav-enabled .tsp-sidebar__list {
		grid-template-rows: repeat(var(--tsp-nav-rows, 5), minmax(min-content, 1fr));
	}

	/* --- the meta returns to one line ------------------------------------ */
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-body {
		grid-template-columns: auto minmax(0, 1fr);
		grid-template-areas:
			"kicker when"
			"title  title";
		align-items: center;
		align-content: center;
		column-gap: 10px;
		row-gap: 4px;
	}
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-category {
		grid-area: kicker;
		justify-self: start;
		margin: 0;
	}
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-body time {
		grid-area: when;
		justify-self: start;
		margin: 0;
	}
	.tsp-sidebar__section--scope-briefing .tsp-story-title {
		grid-area: title;
		margin: 0;
	}

	/* Padding first, type never: the row gives up its slack before its
	   readability. 6px is the smallest that still reads as a row rather than a
	   table line. */
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item {
		padding-block: 6px;
	}
}

/* v1.10.519 — the growth chain, which v1.10.518 opened at one end only.

   v1.10.518 gave the panel the row's height and told the LIST to fill it, and
   the bottoms duly aligned at 1536 and 1920 — but only because the panel was
   stretched. Measured at 1920: wrap 286-870, list 373-766. The list never grew;
   104px of the panel was empty below Story 5, which is the exact defect
   v1.10.507 was written to remove, hidden behind a correct-looking outer
   height.

   The chain from the panel to the list is
     .tsp-sidebar (flex column, 584)
       .tsp-nav-viewport      flex: 0 0 auto, display: block   <- stops here
         .tsp-sidebar__section                display: block   <- and here
           .tsp-sidebar__list  flex: 1 1 auto (inert: parent is not flex)

   Two links were closed. The viewport was pinned at `flex: 0 0 auto` by
   v1.10.482 as part of the anti-feedback-loop guard, and the section is a plain
   block, so `flex` on the list had nothing to act on. Both are opened here and
   both are given `min-height: 0`, without which a flex item refuses to shrink
   below its content and the grid cannot distribute.

   THE LOOP STILL CANNOT HAPPEN, for the reason set out at v1.10.518: `1fr`
   distributes SPARE height and does not raise `min-content`, so the Briefing's
   natural height is unchanged by this. The row height stays
   max(Hero, Briefing-natural) and the Hero half of that is computed from its
   own width and its own ratio. */
@media (min-width: 1024px) {
	.tsp-sidebar-wrap--briefing .tsp-nav-viewport {
		flex: 1 1 auto;
		min-height: 0;
		display: flex;
		flex-direction: column;
	}
	.tsp-sidebar-wrap--briefing .tsp-sidebar__section--scope-briefing {
		flex: 1 1 auto;
		min-height: 0;
		display: flex;
		flex-direction: column;
	}
	.tsp-sidebar-wrap--briefing .tsp-sidebar__section--scope-briefing .tsp-sidebar__list {
		flex: 1 1 auto;
		min-height: 0;
	}
}

/* v1.10.520 — the last link: the list takes the section's height directly.

   v1.10.519 opened the viewport and the section (both now 474 at 1920), and the
   rows still measured 79 with 104px dead below Story 5. The section stayed
   `display: block` — something outranks the `display: flex` written for it — so
   `flex: 1 1 auto` on the list had nothing to act on for the second time.

   Rather than hunt the rule that wins, the list takes the height directly. The
   section's height is flex-derived and therefore definite, so a percentage on a
   block child resolves against it — which is exactly the condition that was
   missing on the review poster at v1.10.516, where the parent used `min-height`
   and the percentage collapsed to `auto`. Here the parent has a real used
   height, so this is the case where `height: 100%` is the right tool.

   Verified by injection on staging before shipping: list 393 -> 474, rows
   79 -> 95, dead space 104 -> 23. */
@media (min-width: 1024px) {
	.tsp-sidebar-wrap--briefing .tsp-sidebar__section--scope-briefing .tsp-sidebar__list {
		height: 100%;
	}
}

/* v1.10.521 — the last of the row's slack, spent where it actually helps.

   After v1.10.520 the bottoms align exactly at 1536 and 1920, where the Hero is
   tall enough for the rows to divide its height. Between 1024 and 1440 the Hero
   is SHORTER than the Briefing's minimum content height, so the rows sit at
   `min-content` and the Briefing overhangs by 37-112px.

   Trimming the row's padding lowers that floor. It costs nothing at the wide
   widths — there the rows are space-bound at `1fr` and padding does not decide
   their height — so this is a change that only applies itself where there is a
   problem to solve.

   Padding and gap only. The type is untouched, per the brief: a row gives up
   its air before its readability. */
@media (min-width: 1024px) {
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item {
		padding-block: 4px;
	}
	.tsp-sidebar__section--scope-briefing .tsp-sidebar__item-body {
		row-gap: 3px;
	}
}

/* ===========================================================================
   v1.10.538 — Telugu News strip: one baseline for the row (design Concept A)

   The row currently has two card designs in it. Measured on English staging at
   1440: an imaged card puts its headline at y236 at 15px; an image-less card
   puts its headline at y173 at 19px, inside a bordered panel. Nine cards say
   one thing and three say another, 63px apart, and the eye reads the odd ones
   as images that failed rather than as stories without one.

   v1.10.442 reached for Concept B - drop the band, enlarge the headline, and
   let the panel declare itself a text card. That is a real design and it is
   defensible; it just loses the row's baseline, which is the thing this strip
   most needs, because the mix is not stable. Five of these twelve stories carry
   `featured_media: 0` at source and which five changes with the feed.

   So: every card reserves the same band. An image-less card fills it with the
   edition's own word rather than a headline, and the headline then starts where
   every other headline starts, at the size every other headline uses.

   The v1.10.442 note that no placeholder graphic should be invented still
   holds and is not broken here. A word set in the page's own type is not a
   photograph and cannot be mistaken for one - which is exactly why it can sit
   in the band without pretending to be missing content.

   The feed is the reason the band carries the edition word and not the story's
   category: `Cross_Site_Feed` returns title, url, image and date only, so a
   category word would have to be fetched per item from the remote REST API.
   The edition word needs no data and is true of every card in the strip.
   =========================================================================== */

/* The panel goes. Its padding, border and centring existed to make a card with
   no band look intentional; with a band there is nothing to compensate for. */
.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item--noimg {
	justify-content: flex-start;
	padding: 0;
	border: 0;
	background: none;
}

/* Overrides the v1.10.471 rule at its own specificity - that one restored the
   panel's top edge, and there is no panel now. */
.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item + .tsp-sidebar__item--noimg {
	border-top: 0;
}

/* The band. Same box as `.tsp-sidebar__item-image` above: same ratio, radius,
   margin and `flex: none`, so the two card types cannot drift apart. */
.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item--noimg::before {
	/* v1.10.545: the word arrives from PHP, which knows which edition the feed
	   comes from. Empty default: Most Viewed and Trending share this layout and
	   must not claim a language. */
	content: var(--tsp-band-word, "");
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	aspect-ratio: 16 / 10;
	margin: 0 0 10px;
	flex: none;
	border-radius: 6px;
	background: var(--tsp-band-bg, #F1EEE8);
	color: var(--tsp-band-ink, rgba(22, 24, 31, 0.20));
	font-size: 34px;
	line-height: 1;
	font-weight: 700;
	letter-spacing: 0.01em;
	user-select: none;
}

/* The headline returns to the row's size. The +4 and +9 steps below existed to
   fill a panel that no longer exists; leaving them would re-break the baseline
   this rule set is here to create. */
.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item--noimg .tsp-story-title {
	font-size: var(--tsp-sidebar-title, 15px);
	line-height: 1.45;
}

/* One card fills the rail on a phone, so the band is far wider there and the
   word has to grow with it or it reads as a stray glyph in a large empty box.
   `@container`, matching the rule this replaces. */
@container (max-width: 520px) {
	.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item--noimg .tsp-story-title {
		font-size: var(--tsp-sidebar-title, 15px);
	}
	.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item--noimg::before {
		font-size: 54px;
	}
}

/* v1.10.539 — the band needs an edge to read as an object.

   With the baseline fixed, the one thing still separating the two card types on
   screen is definition: a photograph has a hard boundary, a pale tint on white
   does not, so at a glance the bands read as soft holes in the row rather than
   as panels someone placed there. The hairline is the whole fix - it gives the
   band the same definite edge the image has, using the rule colour the rest of
   the page already uses for exactly this job.

   The word comes up from 0.20 to 0.26 at the same time. It stays a watermark;
   it just stops looking like a printing fault. */
.tsp-sidebar__section--compact-telugu-strip .tsp-sidebar__item--noimg::before {
	border: 1px solid var(--tsp-hairline, #E8E5DE);
	color: var(--tsp-band-ink, rgba(22, 24, 31, 0.26));
}


/* ==========================================================================
   v1.10.624 — a Briefing row cannot balloon when the panel is under-filled.

   FOUND BY LOOKING, on the Telugu homepage at 1.10.623. The Briefing said
   "1 story you need to know" and drew that one story as a 442px block of tint
   with its content floating in the middle — roughly 300px of stretched
   highlight above the fold.

   CAUSE. The row track is
   `repeat(var(--tsp-nav-rows,5), minmax(min-content, 1fr))`, and `--tsp-nav-rows`
   is the ITEM COUNT, not the page size. That `1fr` exists to COMPRESS five rows
   into a panel whose height is matched to the Hero — measured at 1.10.623, five
   rows resolve to 88.32px each inside 441.6px. With one row the same `1fr`
   expands it to the whole 441.6px.

   So the panel is only ever verified full. The Scope Briefing was frozen at
   1.10.517 on "five uniform rows"; a one-story Briefing is a content state that
   freeze never covered, and it is reachable on any edition with a small
   inventory or a quiet day — the duplicate registry excludes whatever the Hero
   already showed, so the Telugu edition hits it routinely.

   WHY A max-height AND NOT `align-items: start`. Tried first, and measured on the
   English homepage, which has five: alignment changed the rows from a uniform
   88px to 74/74/62/74/73. That is the frozen composition — five uniform rows with
   even hairlines — broken. A cap is inert instead: the track is 88px there, well
   under the cap, so nothing changes. It binds ONLY where a track is over-tall,
   which is precisely the under-filled case.

   Measured after: English five rows 88/88/88/88/88, unchanged. Telugu one row
   442 -> 130, pinned to the top of its track.

   1.25x of the approved row leaves a two-line Telugu headline room to breathe —
   Telugu wraps longer than English at the same measure — while keeping the row
   recognisably a row.

   NOT ADDRESSED HERE, deliberately: the panel itself still stands as tall as the
   Hero beside it, so an under-filled Briefing leaves white space below the last
   story. That is the approved panel/Hero height relationship and changing it is a
   composition decision for the owner, not a defect fix.
   ========================================================================== */
.tsp-sidebar__section--scope-briefing .tsp-sidebar__item {
	max-height: calc(var(--tsp-brief-row, 104px) * 1.25);
}

/* ==========================================================================
   v1.10.640 — THE BRIEFING IS AS TALL AS THE STORIES IT HAS.

   The owner's decision of 31 August 2026, superseding the "composition
   decision for the owner" note left above at v1.10.624: an under-filled
   Briefing must adapt, at 1, 2, 3, 4 or 5 stories, on every tier.

   TWO MECHANISMS SIZED THIS PANEL, and only one of them had ever been looked
   at. Both are gated here.

   1. `min-height: var(--tsp-unit-min-h, 440px)` sat unconditional on
      `.tsp-sidebar-wrap--briefing .tsp-sidebar`. It exists so the panel meets
      the Hero's bottom edge — which is a SIDE-BY-SIDE relationship. Below
      1024px the two stack and there is no edge to meet, but the floor still
      bound: measured on English staging with two stories, a 441px bordered
      card around 208px of list. 130px of empty card at 390 and 320, and 290px
      at 768, inside a visible 1px border, which reads as a component that
      failed to load rather than as breathing room.

   2. `height: 100%` (v1.10.518) makes the wrap fill the flex-stretched
      `.wp-block-column`, so the panel takes the Hero's height directly.
      Neutralising the floor alone left this in place and changed nothing at
      1600 — the reason the first pass at this fix measured as a no-op.

   THE GATE IS THE THIRD ROW, and it is measured, not guessed. With the panel
   held at the Hero's height on English staging at 1600:

     | stories | rows            | worst gap | tail |
     |---------|-----------------|-----------|------|
     | 5       | 80/80/80/80/80  | 1px       | 23px |
     | 4       | 100 x4          | 1px       | 24px |
     | 3       | 130 x3          | 4px       | 27px |
     | 2       | 130/130         | 71px      | 94px |
     | 1       | 130             | -         | 295px|

   Three rows still divide the Hero's height into something that reads as a
   ranked index. Two do not, and the slack stops landing at the foot and starts
   landing BETWEEN the rows, which breaks the even hairlines the freeze is
   about. So three or more keeps the frozen relationship; fewer releases it and
   the panel is exactly its content.

   WHAT IS DELIBERATELY UNCHANGED. The five-story panel is byte-for-byte what
   it was at every width — 512/80px rows at 1600, 635/104px rows at 390 — so
   the Telugu edition and the 1.10.517 freeze are untouched. The row cap from
   v1.10.624 stays: it is what keeps three rows at 130 rather than 170.

   No `!important`: `:has()` carries its argument's specificity, so these
   outrank the rules they gate on specificity and on source order.
   ========================================================================== */

@media (min-width: 1024px) {

	/* Three rows or more: the panel meets the Hero, exactly as before. */
	.tsp-sidebar-wrap--briefing:has(.tsp-sidebar__list > .tsp-sidebar__item:nth-child(3)) .tsp-sidebar {
		min-height: var(--tsp-unit-min-h, 440px);
	}

	/* Fewer: release BOTH the floor and the stretch. The column keeps the row's
	   height and the spare sits outside the panel, where it reads as layout
	   whitespace instead of a hole in a bordered card. */
	.tsp-sidebar-wrap--briefing:not(:has(.tsp-sidebar__list > .tsp-sidebar__item:nth-child(3))),
	.tsp-sidebar-wrap--briefing:not(:has(.tsp-sidebar__list > .tsp-sidebar__item:nth-child(3))) .tsp-sidebar {
		height: auto;
	}
}

/* ==========================================================================
   v1.10.666 — PORTRAIT TILES: show the whole picture instead of a face band.

   v1.10.663 anchored the generated crops to the top of the frame, which fixes
   an ordinary photograph. It cannot fix a strongly portrait one, because there
   the problem is not WHERE the crop sits but HOW MUCH it must throw away. Into
   this ~1.85:1 tile a 0.717 source keeps 40% of its height, and the subject's
   crown is already ~2% from the top — so even a perfect top crop is a face
   band with nothing left above it to include.

   Those are shown whole. `Portrait_Tile` decides which, from the ORIGINAL
   attachment's stored dimensions, and the renderer swaps in an uncropped
   derivative and adds `--portrait`.

   THE BOX DOES NOT MOVE. Only `object-fit` and the backdrop change, so the
   96x52 tile, the five frozen 104px rows and the column tracks are all exactly
   as they were.

   Placed LAST on purpose. These selectors are (0,2,0) and (0,2,1), which tie
   the `--scope-briefing` rules above rather than beating them, so source order
   is what decides it — move this block up and the treatment silently stops
   applying. Scoped to `.tsp-sidebar__section` rather than the briefing so every
   small card family gets the same answer.
   ========================================================================== */

.tsp-sidebar__section .tsp-sidebar__item-image--portrait {
	position: relative;
	/* The house charcoal, and the only thing showing if the backdrop fails. */
	background: var(--ts-ink, #16181F);
}

/* A blurred, darkened copy of the SAME derivative the <img> is already
   showing, so it costs no second download — the browser serves it from cache.
   `scale` hides the transparent bleed a blur leaves at the edges. If
   `--tsp-tile-bg` is unset the background-image is simply invalid and the
   charcoal above stands alone, which is a correct result rather than a broken
   one. */
.tsp-sidebar__section .tsp-sidebar__item-image--portrait::before {
	content: "";
	position: absolute;
	inset: 0;
	background-image: var(--tsp-tile-bg);
	background-size: cover;
	background-position: center 30%;
	filter: blur(10px) brightness(.42) saturate(.85);
	transform: scale(1.25);
	z-index: 0;
}

/* `contain`, so the photograph is never cropped and never distorted, sitting
   sharp above the blur. The face must not inherit the backdrop's blur, which is
   why this is a separate element and not a filter on the container. */
.tsp-sidebar__section .tsp-sidebar__item-image--portrait img {
	position: relative;
	z-index: 1;
	width: 100%;
	height: 100%;
	object-fit: contain;
	object-position: center center;
}

/* The hover zoom is a crop effect: on a contained portrait it would push the
   picture past its own edges, which is the thing this block exists to stop. */
.tsp-sidebar__section .tsp-sidebar__item:hover .tsp-sidebar__item-image--portrait img {
	transform: none;
}
