/* Aperture article template.

   Scoped entirely under .tsp-art-wrap so nothing here can leak into Blocksy's
   header, footer or any other template. Tokens are declared on the wrapper
   rather than :root for the same reason.

   Responsive note: this template owns the full page width rather than sitting
   inside a block, so it uses MEDIA queries. The plugin's container-query rule
   applies to width-responsive BLOCKS inside a container-type wrapper, which is
   not what this is. */

.tsp-art-wrap{
	--tsp-red:#C8102E;
	--tsp-dark-red:#9C0F27;
	--tsp-ink:#16181F;
	--tsp-muted:#676E7B;
	--tsp-hairline:#E8E5DE;
	--tsp-gold:#B8892F;
	--tsp-wash:#F6F4EF;
	--tsp-paper:#fff;
	/* The article shell tops out BELOW the global shell on purpose. A reading page
	   does not benefit from 1760px: prose is capped at 800, so every pixel past
	   ~1500 became empty column beside the text rather than useful composition.
	   Different content types want different widths -- grids and the homepage keep
	   the full tier, the article does not. */
	--tsp-wrap:min(var(--tsp-shell,1200px),1500px);
	background:var(--tsp-paper);
	color:var(--tsp-ink);
	font-family:var(--tsp-font-body);
}
.tsp-art__inner{max-width:var(--tsp-wrap);margin:0 auto;padding:0 24px}
.tsp-art a{color:inherit;text-decoration:none}

/* ---------------------------------------------------------------- head */
/* v1.10.307 — one line, and the current-page crumb yields.
   The trail printed the whole 60-character headline as its last crumb, so the
   breadcrumb was longer than most standfirsts and competed with the headline
   directly beneath it. The title is KEPT — a breadcrumb's job is to say where
   you are, and deleting it to match a mockup would remove that and whatever
   schema reads it — but it is truncated so the ancestors stay legible and the
   trail can never take a second line. */
.tsp-art__crumb{display:flex;align-items:center;flex-wrap:nowrap;
	font-family:var(--tsp-font-ui);font-size:12.5px;color:var(--tsp-muted);padding:22px 0 6px}
/* v1.10.450 — 24px of touchable height, WCAG 2.5.8.
 *
 * Measured at 390 on a live article: "Home" 35x20 and "Breaking News" 89x20.
 * The floor is 24. These are NOT covered by the "inline text link" exception —
 * that exception is for a link sitting in a sentence, and a breadcrumb is a
 * navigation control that happens to be made of words.
 *
 * `inline-flex` + `min-height` rather than padding, exactly as the ticker links
 * were fixed: padding would push the row taller and move the headline beneath
 * it, whereas the row is already 20px inside a taller line box, so the target
 * grows into space that is there and nothing shifts. Type size is untouched. */
.tsp-art__crumb a{white-space:nowrap;flex:0 0 auto;display:inline-flex;align-items:center;min-height:24px}
.tsp-art__crumb a:hover{color:var(--tsp-red)}
.tsp-art__crumb .sep{margin:0 8px;color:#c4c8cf;flex:0 0 auto}
.tsp-art__crumb [aria-current="page"]{
	min-width:0;
	overflow:hidden;
	text-overflow:ellipsis;
	white-space:nowrap;
	/* Was #9aa0ab -- 2.63:1 on white, well under AA for 12.5px text. It is the
	   only crumb that is not a link, so it now shares the muted token and takes
	   its distinction from being unclickable rather than from being faint. */
	color:var(--tsp-muted,#676E7B);
}
.tsp-art__head{padding-top:6px}
/* v1.10.307 — two chips rather than one red string, per article_page2.png.
   The primary term is a filled red field; the secondary is a quiet neutral
   outline, so the section reads first and the sub-desk supports it instead of
   competing at the same weight. */
.tsp-art__kicker{display:flex;flex-wrap:wrap;align-items:center;gap:8px;
	font-family:var(--tsp-font-ui);font-weight:800;font-size:10.5px;
	letter-spacing:.12em;text-transform:uppercase}

.tsp-art__kicker-chip{display:inline-block;padding:5px 10px;border-radius:4px;
	border:1px solid var(--tsp-hairline,#E8E5DE);background:#fff;
	color:#5A616E;text-decoration:none;transition:border-color .15s,color .15s}

.tsp-art__kicker-chip.is-primary{background:var(--tsp-red);border-color:var(--tsp-red);color:#fff}

.tsp-art__kicker-chip:not(.is-primary):hover,
.tsp-art__kicker-chip:not(.is-primary):focus-visible{border-color:var(--tsp-red);color:var(--tsp-red)}
.tsp-art__kicker-chip.is-primary:hover,
.tsp-art__kicker-chip.is-primary:focus-visible{background:var(--tsp-dark-red,#9C0F27);border-color:var(--tsp-dark-red,#9C0F27)}
/* v1.10.385 — 1060, and not a pixel more.
   The headline is display type, so it does not owe anything to the 720px prose
   measure; at 960 it was taking three lines where two would do. Tested against
   three real headlines at 960 / 1060 / 1150 / 1250, at 1366, 1600 and 1920:
   64- and 66-character headlines are two lines at EVERY width, and the
   82-character one drops from three lines to two at 1060 and then never
   improves again. So 1060 captures the entire measured benefit and 1150+ buys
   nothing but a longer line to scan.
   It is also safe at the narrowest desktop: the header band is 1152 at 1366 and
   sits ABOVE the two-column split, so there is no sidebar to collide with. */
.tsp-art__title{font-family:var(--tsp-font-display);font-weight:800;line-height:1.1;letter-spacing:-.01em;margin:14px 0 0;max-width:1060px;color:var(--tsp-ink)}
.tsp-art__standfirst{font-family:var(--tsp-font-display);font-weight:600;font-style:italic;font-size:clamp(18px,2vw,22px);line-height:1.45;color:#48505c;margin:18px 0 0;max-width:820px}

.tsp-art__byline{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin:24px 0 0;padding:18px 0;border-top:1px solid var(--tsp-hairline);border-bottom:1px solid var(--tsp-hairline)}
.tsp-art__avatar{flex:none;width:42px;height:42px;border-radius:50%;overflow:hidden;background:linear-gradient(135deg,#d9dde3,#eef0f3);display:block}
.tsp-art__avatar img{width:100%;height:100%;object-fit:cover;display:block;border-radius:50%}
.tsp-art__bywho{font-family:var(--tsp-font-ui);font-size:13.5px;line-height:1.4}
.tsp-art__bywho b{font-weight:600}
.tsp-art__bymeta{color:var(--tsp-muted);font-size:12.5px}

.tsp-art__share{margin-left:auto;display:flex;gap:10px;align-items:center}
.tsp-art__share-lbl{font-family:var(--tsp-font-ui);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--tsp-muted);margin-right:2px}
.tsp-art__share-btn{width:38px;height:38px;border-radius:50%;border:1px solid var(--tsp-hairline);display:flex;align-items:center;justify-content:center;color:var(--tsp-ink);background:none;padding:0;cursor:pointer;transition:.15s}
.tsp-art__share-btn:hover,.tsp-art__share-btn:focus-visible{background:var(--tsp-ink);color:#fff;border-color:var(--tsp-ink)}
.tsp-art__share-btn svg{width:16px;height:16px;fill:currentColor}
.tsp-art__share-copy.is-copied{background:var(--tsp-gold);border-color:var(--tsp-gold);color:#fff}
/* v1.10.713: the phone share-sheet button stays out until article.js shows it (display:flex above would beat [hidden]). */
.tsp-art__share-native[hidden]{display:none}
/* v1.10.714: the note after the Facebook button copies the post text. */
.tsp-art__toast{position:fixed;left:50%;bottom:calc(84px + env(safe-area-inset-bottom,0px));transform:translate(-50%,12px);max-width:min(92vw,440px);background:#14161c;color:#fff;font-family:var(--tsp-font-ui);font-size:14px;line-height:1.4;padding:12px 16px;border-radius:10px;box-shadow:0 10px 30px rgba(0,0,0,.25);opacity:0;transition:opacity .2s,transform .2s;z-index:9999;text-align:center}
.tsp-art__toast.is-on{opacity:1;transform:translate(-50%,0)}

.tsp-art__lead{margin:26px 0 28px}
/* v1.10.662 — the lead shows the WHOLE photograph, not a 16/9 slice of it.
 *
 * It was `aspect-ratio:16/9;object-fit:cover`, which is a crop and not a fit:
 * the box was forced to 16/9 and the picture centred inside it, so any original
 * taller than 16/9 — 3/2, 4/3, square, portrait — lost equal bands off the TOP
 * and the BOTTOM. In a news photograph the subject's head sits in the upper
 * third, so the top band took the head. Reported by the owner on
 * `/rajnath-singh-sri-lanka-visit-2/`, where the minister was beheaded by the
 * crop; the file itself was never wrong.
 *
 * It also meant the reader saw a DIFFERENT picture from the one the Picture
 * Desk approved, and from the one Rank Math hands to Open Graph, Twitter and
 * Article schema — those take the file, which was never cropped. The card and
 * the article disagreed about what the photograph was.
 *
 * `width:auto;max-width:100%` is the same pattern `.tsp-art__body img` already
 * uses. Every real lead is wider than the measure, so max-width binds and the
 * image still spans the column edge to edge — the 390px fallback QA reading
 * (16 -> 374 against a 16 -> 374 body) is unchanged. `max-height` catches the
 * one case this opens up, a portrait or square original that would otherwise
 * run past a screen height; it shrinks the picture, it does not cut it.
 *
 * CLS is still covered. get_the_post_thumbnail() emits width and height and
 * the browser derives the intrinsic ratio from them — that is what reserved the
 * space before aspect-ratio was ever written here. Image_Alt::thumb_attrs()
 * only adds `alt`; it strips nothing.
 */
.tsp-art__lead img{width:auto;max-width:100%;height:auto;max-height:80vh;display:block;margin-inline:auto;border-radius:8px}
/* v1.10.708 — landscape leads fill the column outright instead of relying on
 * the intrinsic width (iPhone Safari rendered a 1600x900 lead at ~114px wide).
 * object-fit keeps the ratio if max-height ever binds on a short landscape
 * screen. Portrait leads keep the rule above. */
.tsp-art__lead--wide img{width:100%;object-fit:contain}
.tsp-art__lead figcaption{font-family:var(--tsp-font-ui);font-size:12px;color:var(--tsp-muted);margin-top:8px}

/* ---------------------------------------------------------------- body */
.tsp-art__layout{display:grid;grid-template-columns:minmax(0,1fr) var(--tsp-rail,320px);gap:56px;padding:28px 0 0;align-items:start}

/* v1.10.308 — the left column now holds Key Points, the hero AND the prose, so
   the rail can begin beside the upper article. The column is the composition
   width; the PROSE keeps its own measure inside it — 720 when this was written,
   800 since v1.10.401, but always its own. Widening body text to the column was
   explicitly not the point of this correction and still is not. */
.tsp-art__main{min-width:0}
.tsp-art__body{max-width:none;min-width:0}

/* Key Points and the hero fill the column rather than the old full-bleed width.
   The 960px cap set when this sat outside the grid would now exceed the column
   and force an overflow. */
/* Key Points is TEXT, so it takes a measure rather than the whole column. At the
   1200 shell the column is 776 and this cap never applies, so the laptop layout
   is untouched; at the 1760 shell the column is ~1276 and the bullets would
   otherwise run to that full width. */
.tsp-art__main .tsp-art__keypts{max-width:min(100%,960px);margin-top:0}
.tsp-art__main .tsp-art__lead{margin-top:22px}
.tsp-art__body p{font-size:19px;line-height:1.78;margin:0 0 24px;color:#22262e}
/* Drop cap on the opening paragraph only. :not() keeps it off a paragraph that
   merely follows the verified box or an image. */
.tsp-art__body>p:first-of-type::first-letter{font-family:var(--tsp-font-display);font-weight:800;font-size:64px;line-height:.8;float:left;margin:6px 12px 0 0;color:var(--tsp-red)}
.tsp-art__body h2{font-family:var(--tsp-font-display);font-weight:700;font-size:26px;margin:34px 0 16px;line-height:1.2;color:var(--tsp-ink)}
.tsp-art__body h3{font-family:var(--tsp-font-display);font-weight:700;font-size:21px;margin:28px 0 12px;line-height:1.25}
.tsp-art__body blockquote{border-left:4px solid var(--tsp-red);margin:30px 0;padding:6px 0 6px 24px;font-family:var(--tsp-font-display);font-style:italic;font-size:24px;line-height:1.4;color:var(--tsp-ink)}
.tsp-art__body blockquote p{font-size:inherit;line-height:inherit;margin:0}
.tsp-art__body img{max-width:100%;height:auto;border-radius:8px}
.tsp-art__body figcaption{font-family:var(--tsp-font-ui);font-size:12px;color:var(--tsp-muted);margin-top:8px}
.tsp-art__body a{color:var(--tsp-red);text-decoration:underline;text-underline-offset:2px}
.tsp-art__body ul,.tsp-art__body ol{margin:0 0 24px;padding-left:24px;font-size:19px;line-height:1.78}
.tsp-art__body li{margin-bottom:8px}

/* v1.10.26: symmetric margin now that the note sits BETWEEN paragraphs rather
   than above the article, matching the prototype's `margin:28px 0`. */
.tsp-art__verified{background:var(--tsp-wash);border:1px solid var(--tsp-hairline);border-left:4px solid var(--tsp-gold);border-radius:8px;padding:18px 20px;margin:28px 0;display:flex;gap:14px;align-items:flex-start}
.tsp-art__verified-badge{color:var(--tsp-gold);font-size:22px;line-height:1}
.tsp-art__verified-t{font-family:var(--tsp-font-ui)}
.tsp-art__verified-t b{display:block;font-size:14px;font-weight:700;color:var(--tsp-ink);margin-bottom:3px}
.tsp-art__verified-t span{font-size:13px;color:var(--tsp-muted);line-height:1.5}

.tsp-art__tags{display:flex;flex-wrap:wrap;gap:10px;margin:34px 0 0;padding-top:24px;border-top:1px solid var(--tsp-hairline)}
/* v1.10.694: the lead picture's credit or disclosure, one small line at the article's end — the review page's .tsp-rv__credits.
   v1.10.695: a div, because inside .tsp-art__body every paragraph rule (19px serif, justified) outranked it as a p. */
.tsp-art__body .tsp-art__picture-note{font-family:var(--tsp-font-ui);font-size:11.5px;line-height:1.5;color:var(--tsp-muted);margin:24px 0 0;text-align:left}
.tsp-art__tag{font-family:var(--tsp-font-ui);font-size:12.5px;color:var(--tsp-ink);background:var(--tsp-wash);border:1px solid var(--tsp-hairline);padding:7px 14px;border-radius:40px}
.tsp-art__tag:hover{border-color:var(--tsp-red);color:var(--tsp-red)}

.tsp-art__authorbox{display:flex;gap:16px;align-items:flex-start;margin:28px 0 0;padding:22px;background:var(--tsp-wash);border-radius:10px}
.tsp-art__authorbox-av{width:56px;height:56px;border-radius:50%;overflow:hidden;flex:none;background:linear-gradient(135deg,#d9dde3,#eef0f3)}
.tsp-art__authorbox-av img{width:100%;height:100%;object-fit:cover;display:block;border-radius:50%}
.tsp-art__authorbox-t b{font-family:var(--tsp-font-ui);font-size:15px}
.tsp-art__authorbox-t p{font-family:var(--tsp-font-ui);font-size:13px;color:var(--tsp-muted);margin-top:5px;line-height:1.55}

/* ------------------------------------------------------------- sidebar */
.tsp-art__rail{position:sticky;top:20px;display:flex;flex-direction:column;gap:28px;min-width:0}
/* v1.10.422: display serif — "MOST VIEWED IN ANDHRA PRADESH" heads a group of
   stories. Family only; the eyebrow scale, uppercase and red rule are kept. */
.tsp-rail__h{font-family:var(--tsp-font-display);font-weight:700;font-size:13px;letter-spacing:.08em;text-transform:uppercase;color:var(--tsp-ink);padding-bottom:12px;border-bottom:2px solid var(--tsp-red);margin:0 0 4px}
.tsp-rail__item{display:flex;gap:12px;padding:14px 0;border-bottom:1px solid var(--tsp-hairline);align-items:flex-start}
/* 34px, not 30: two digits of the 26px display face need ~32px, so "01"
   was breaking between the 0 and the 1 and every rank rendered as a stacked
   pair. nowrap is the guard; the width stops it overlapping the headline. */
.tsp-rail__n{font-family:var(--tsp-font-display);font-weight:800;font-size:26px;color:var(--tsp-gold);line-height:1;flex:none;width:34px;white-space:nowrap}
.tsp-rail__h3{font-family:var(--tsp-font-display);font-weight:700;font-size:15.5px;line-height:1.3}
.tsp-rail__item:hover .tsp-rail__h3,.tsp-rail__item:hover .tsp-rail__te{color:var(--tsp-red)}
.tsp-rail--ad{display:flex;flex-direction:column;align-items:center;gap:6px}
.tsp-rail__adlabel{font-family:var(--tsp-font-ui);letter-spacing:.15em;text-transform:uppercase;font-size:10px;color:var(--tsp-muted)}
.tsp-rail--telugu .tsp-rail__item{align-items:center;padding:12px 0}
.tsp-rail__thumb{width:64px;height:46px;border-radius:6px;overflow:hidden;flex:none;background:linear-gradient(135deg,#e7d7dc,#dfe4ea)}
.tsp-rail__thumb img{width:100%;height:100%;object-fit:cover;display:block}
.tsp-rail__te{font-weight:600;font-size:15px;line-height:1.35}

.tsp-rail--news{background:var(--tsp-ink);border-radius:10px;padding:22px;color:#fff}
.tsp-rail--news h2{font-family:var(--tsp-font-display);font-weight:700;font-size:19px;margin:0 0 6px;color:#fff;border:0;padding:0;letter-spacing:normal;text-transform:none}
.tsp-rail--news p{font-family:var(--tsp-font-ui);font-size:12.5px;color:#aeb4be;margin:0 0 14px}
.tsp-rail--news input{width:100%;border:none;border-radius:8px;padding:11px 13px;font-family:var(--tsp-font-ui);font-size:13px;margin-bottom:9px}
.tsp-rail--news button{width:100%;background:var(--tsp-red);color:#fff;border:none;border-radius:8px;padding:11px;font-family:var(--tsp-font-ui);font-weight:600;font-size:13px;cursor:pointer}

/* ------------------------------------------------------------- related */
/* v1.10.376: the tail separator moves to the one remaining section. `.tsp-art__related`
   is kept in the selector so any cached markup mid-deploy still gets the rule. */
.tsp-art__more,
.tsp-art__related{border-top:1px solid var(--tsp-hairline);margin-top:56px;padding-top:32px}
.tsp-art__related-h{font-family:var(--tsp-font-display);font-weight:800;font-size:28px;margin:0 0 22px}
.tsp-art__rgrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:26px}
.tsp-art__rcard{display:block;min-width:0}
.tsp-art__rmedia{display:block;width:100%;aspect-ratio:16/10;border-radius:8px;overflow:hidden;margin-bottom:12px;background:linear-gradient(135deg,#e7d7dc,#dfe4ea)}
.tsp-art__rmedia img{width:100%;height:100%;object-fit:cover;display:block}
.tsp-art__rimg--empty{display:block;width:100%;height:100%}
.tsp-art__rk{font-family:var(--tsp-font-ui);font-weight:700;font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--tsp-red);display:block}
.tsp-art__rt{font-family:var(--tsp-font-display);font-weight:700;font-size:18px;line-height:1.3;margin-top:6px;display:block}
.tsp-art__rcard:hover .tsp-art__rt{color:var(--tsp-red)}

/* -------------------------------------------------------------- band */
/* v1.10.421 — a shorter interruption.
 *
 * The band sits in the middle of a reading flow, and at 312px tall it asked for
 * more of the page than an interruption should. Padding 52>42, the pitch's
 * margins 10/20>8/16 and the headline 30>28 take roughly a fifth off the height
 * without touching the composition, which was already right. 28px also brings
 * it within one step of the homepage placement's 24px, so the two read as one
 * type system. The approach margin comes down with it. */
.tsp-art__band{background:var(--tsp-red);color:#fff;text-align:center;padding:42px 24px;margin-top:48px}
.tsp-art__band h2{font-family:var(--tsp-font-display);font-weight:800;font-size:28px;margin:0;color:#fff}
.tsp-art__band p{font-family:var(--tsp-font-ui);font-size:14px;opacity:.92;margin:8px 0 16px}
/* The tail sign-up form.
 *
 * `flex-wrap` and a full-width consent line are load bearing — the consent line
 * gets `flex: 1 0 100%` from the shared component sheet, and without it the
 * notice becomes a THIRD flex child on the control row and takes its share of
 * the width: measured at 1366 and 1920 the email field collapsed to 32px while
 * the button stretched to 74px tall against a 40px input.
 *
 * v1.10.421: the field's and button's APPEARANCE now comes from the shared
 * Scope Briefing sheet, so what is left here is composition only — a centred,
 * compact row. The gap is the component's `--tsp-sb-gap`, tighter than the
 * surrounding rhythm so the field and its button read as one form rather than
 * two adjacent controls, and the row is capped at 520px so it stays a compact
 * editorial CTA rather than a wide desktop bar. */
.tsp-art__band form{display:flex;flex-wrap:wrap;align-items:center;gap:var(--tsp-sb-gap,8px);justify-content:center;max-width:520px;margin:0 auto}
/* `width: auto` is not cosmetic. Blocksy gives inputs `width: 100%`, and with
   `flex-basis: auto` that 100% BECOMES the basis — so the field claimed the
   whole 520px row on its own and pushed the button onto a second line at every
   desktop width. Measured at 1920: input 520x48 with the button below it, on a
   composition that is supposed to be a single centred row. Resetting the width
   lets the basis fall back to content size, which is what `flex-grow` is then
   free to expand. Scoped at (0,2,2) so it clears the theme's own rule. */
.tsp-art__band form input[type="email"]{flex:1 1 auto;width:auto;min-width:0}
.tsp-art__band form button{flex:0 0 auto}
.tsp-art__band__consent{text-align:center}

/* ------------------------------------------------------------- mobile */
@media (max-width:900px){
	.tsp-art__layout{grid-template-columns:1fr;gap:36px}
	.tsp-art__rail{position:static}
	.tsp-art__rgrid{grid-template-columns:1fr}
	.tsp-art__share{margin-left:0;width:100%;flex-wrap:wrap}
	.tsp-art__body p,.tsp-art__body ul,.tsp-art__body ol{font-size:18px;line-height:1.7}
}
@media (max-width:600px){
	.tsp-art__inner{padding:0 16px}
	.tsp-art__lead{margin-bottom:22px}
	.tsp-art__body>p:first-of-type::first-letter{font-size:52px}
	.tsp-art__band{padding:34px 16px}
	.tsp-art__band form{flex-direction:column}
}
@media (prefers-reduced-motion:reduce){
	.tsp-art__share-btn{transition:none}
}

/* ==========================================================================
   v1.10.77 — §24/§25 long-form reading.

   The article page is where typography does the most work, so these are the
   changes most likely to be felt. Sizes and leading only; no layout change.
   ========================================================================== */

/* H1 — fluid 31px→44px so it lands mid-30s on a phone and mid-40s on desktop
   without a one-off breakpoint (§28 prefers clamp over extra breakpoints).
   Weight drops 800→700: at 44px Georgia's 800 is heavier than the "editorial
   authority" this is aiming at, and 700 holds the page better. */
.tsp-art__title{font-size:clamp(31px,1.6rem + 2.2vw,44px);font-weight:700;line-height:1.12}

/* Standfirst — the reading serif, not the display serif. It is the first thing
   actually READ rather than scanned, so it belongs to the body voice; keeping it
   Georgia italic made it a second headline. */
.tsp-art__standfirst{font-family:var(--ts-font-body);font-size:clamp(17px,1rem + .5vw,20px);font-weight:400;font-style:normal;line-height:1.55}

/* Body — 19px at 1.7. §25: not pure black. #202124 keeps well above WCAG AA on
   white while taking the glare off a long column. */
.tsp-art__body p,.tsp-art__body ul,.tsp-art__body ol{font-size:19px;line-height:1.7;color:#202124}

/* Measure — the column, not a fixed number.

   OWNER DECISION, v1.10.615: the prose must line up with the picture above it.

   Every earlier revision of this rule set an absolute cap — 720, then 800 —
   and the cap is what produced the defect. The lead image fills the main
   column, the prose did not, so under the picture the text stopped short and
   left a band of white down the right. Measured on staging before this change:

     1920   image 1036, prose 800   ->  236px short
     1680   image  876, prose 800   ->   76px short
      900   image  852, prose 720   ->  132px short
     1440   image  776, prose 776   ->  aligned (column below the cap)

   1440 is why this survived earlier QA: there the column is narrower than the
   cap, so the cap never binds and the page looks correct. The fault only
   appears once the column outgrows the number, which is why a fixed number was
   the wrong instrument for it.

   So the body now takes the column's width at every breakpoint, and the ≤900
   override that set 720 is gone with it — that breakpoint had the same fault,
   not a different one.

   THE TRADE, stated plainly: at 1920 the measure goes from 800px (~83
   characters at 19px) to 1036px (~108). That is longer than the textbook
   comfortable maximum. It is bought back in part by the 1.7 leading and the
   automatic hyphenation this column already runs, and the alignment with the
   image was judged the more visible problem. If the long line proves worse in
   reading than the dead strip was in looking, the fix is to cap the COLUMN —
   `.tsp-art__main` — so the image narrows with the prose and the two stay
   aligned, rather than to reintroduce a cap here on the prose alone. */
.tsp-art__body{max-width:none}

/* Headings — Georgia throughout, sized down the scale rather than each picked
   independently. */
.tsp-art__body h2{font-family:var(--ts-font-display);font-size:28px;font-weight:700;line-height:1.25}
.tsp-art__body h3{font-family:var(--ts-font-display);font-size:22px;font-weight:700;line-height:1.3}
.tsp-art__body h4{font-family:var(--ts-font-display);font-size:18px;font-weight:700;line-height:1.35}

/* Blockquote stays in the reading voice — a quote is read, not scanned. */
.tsp-art__body blockquote{font-family:var(--ts-font-body);font-size:20px;line-height:1.6}

/* Captions and meta are furniture, so they take the UI voice. */
.tsp-art__body figcaption,.tsp-art__lead figcaption{font-family:var(--ts-font-ui);font-size:12px;font-weight:400;line-height:1.5}
.tsp-art__bywho,.tsp-art__bymeta{font-family:var(--ts-font-ui);font-size:12px;font-weight:500}

@media (max-width:600px){
	/* §27: mobile body is 18px/1.7 — reduced deliberately, not scaled down with
	   everything else. */
	.tsp-art__body p,.tsp-art__body ul,.tsp-art__body ol{font-size:18px;line-height:1.7}
}

/* ---- v2.2 tail sections: Previous/Next, More from, Recommended ---- */
.tsp-art__pn{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin:26px 0 0}
.tsp-art__pn-item{display:block;border:1px solid var(--tsp-art-line,#e8e5de);border-radius:10px;
	padding:13px 16px;text-decoration:none;color:inherit;transition:border-color .18s}
.tsp-art__pn-item:hover,.tsp-art__pn-item--prev:focus-visible,.tsp-art__pn-item--next:focus-visible{border-color:#C8102E}
.tsp-art__pn-item--next{text-align:right}
.tsp-art__pn-lbl{display:block;font-size:9.5px;font-weight:800;letter-spacing:.12em;
	text-transform:uppercase;color:#676E7B}
.tsp-art__pn-t{display:block;font-family:var(--ts-display);font-size:15px;font-weight:700;
	line-height:1.3;margin-top:5px;overflow-wrap:break-word}
/* A single neighbour must not stretch across both columns. */
.tsp-art__pn-item--next:only-child{grid-column:2}

.tsp-art__morefrom,.tsp-art__recommended{margin-top:30px}

@media (max-width:640px){
	.tsp-art__pn{grid-template-columns:minmax(0,1fr)}
	.tsp-art__pn-item--next{text-align:left}
	.tsp-art__pn-item--next:only-child{grid-column:auto}
}

/* ---- Key points / Correction (v2.2) ----
   Values from the prototype: the key-points box carries the red left rule, the
   correction sits on the wash tint. Both are rendered only when their field has
   content, so neither can appear empty. */
/* v1.10.305 — Key Points as a recognisable Telugu Scope component.
   Warm wash rather than white, so it reads as an editorial field set into the
   article rather than a generic bordered callout; the red keeps its left accent
   and its eyebrow, and the type comes up to reading scale — at 13px these were
   smaller than the body they summarise, which inverted the hierarchy. */
/* 960 to match the headline. The head already steps its measures down —
   title 960, standfirst 820 — and at the full 1152 this panel was WIDER than the
   headline above it, so four short points left a large empty right side and the
   ladder read backwards. */
.tsp-art__keypts{border:1px solid var(--tsp-art-line,#e8e5de);border-left:4px solid #C8102E;
	background:var(--tsp-wash,#F6F4EF);border-radius:8px;padding:20px 24px 18px;margin-top:20px;
	max-width:960px}

.tsp-art__keypts-eyebrow{display:flex;align-items:center;gap:8px;margin:0 0 10px;
	font-family:var(--ts-ui);font-size:10.5px;font-weight:800;letter-spacing:.13em;
	text-transform:uppercase;color:var(--tsp-muted,#676E7B)}
.tsp-art__keypts-brand{color:#C8102E}
.tsp-art__keypts-sep{color:#C9C4B8}

.tsp-art-wrap .tsp-art__keypts h2{font-family:var(--tsp-font-display);font-size:19px;
	font-weight:700;line-height:1.25;margin:0 0 12px;color:#16181F}

.tsp-art__keypts ul{list-style:none;margin:0;padding:0}
.tsp-art__keypts li{list-style:none;position:relative;padding:7px 0 7px 24px;
	font-size:15px;line-height:1.55;color:#2C3038}
.tsp-art__keypts li+li{border-top:1px solid rgba(0,0,0,.055)}
/* A small square mark, not a dot: it echoes the red field of the eyebrow and
   reads as a deliberate editorial device at this size. */
.tsp-art__keypts li::before{content:"";position:absolute;left:2px;top:15px;
	width:7px;height:7px;border-radius:2px;background:#C8102E}

.tsp-art__corr{display:block;background:#faf8f2;border:1px solid var(--tsp-art-line,#e8e5de);
	border-radius:8px;padding:12px 18px;font-size:12.5px;line-height:1.6;
	color:#3A3D46;margin-top:26px}
.tsp-art__corr b{color:#16181F}

/* ==========================================================================
   v1.10.114 — mobile article, section 15 of the mobile build.

   Measured at 390px against the prototype's `.art` block:
     headline   34.18px  ->  prototype 27px   (191px of a 844px screen)
     standfirst 17.95px  ->  prototype 16px
     share      38x38    ->  under the 44px touch floor
     tags       36px tall->  under the 44px touch floor

   The headline is the one that matters: `clamp(31px,1.6rem + 2.2vw,44px)`
   resolves to 34.18px at 390px, so a four-line headline eats nearly a quarter
   of the first screen before the standfirst starts.

   NOT changed: body paragraphs stay 18px/1.7. The prototype draws 16.5px and
   the work order says "~16px", but article.css records that size as a
   deliberate decision (§27, "reduced deliberately, not scaled down with
   everything else") and 18px is the easier read on a phone. Flagged rather
   than silently reversed.
   ========================================================================== */

/* Phone typography. 600px rather than 782px on purpose: at 768px the column is
   wide enough to carry the larger display size, and shrinking a tablet
   headline to a phone size would look undersized for its measure. */
@media (max-width:600px){
	.tsp-art__title{font-size:27px;line-height:1.18}
	.tsp-art__standfirst{font-size:16px;line-height:1.5}
}

/* Touch targets across the whole phone/tablet range — both controls are under
   the floor at 768px too, and the floor is a property of the input, not of the
   column width. min-height on the tag keeps the label centred rather than
   padding the row taller than the chip. */
@media (max-width:782px){
	.tsp-art__share-btn{width:44px;height:44px}
	.tsp-art__share-btn svg{width:18px;height:18px}
	.tsp-art__tag{min-height:44px;display:inline-flex;align-items:center}
}
/* v1.10.713 — six buttons on a phone (Threads and the share sheet added): the
   "Share" word goes where they would no longer fit on one row at 360px. The
   buttons keep their 44px tap size. */
@media (max-width:420px){
	.tsp-art__share{gap:8px}
	.tsp-art__share-lbl{display:none}
}

/* ==========================================================================
   v1.10.385 — LATEST STORIES: THE ROW IT WAS ALWAYS LAID OUT FOR
   ========================================================================== */

/* `.tsp-rail__item` has been `display:flex; gap:12px` since the rail was built,
   and `.tsp-rail__thumb` already carried its own fallback gradient — the module
   simply never emitted a picture, so five headlines stacked as text and it
   measured 485px at 1366. Everything here is the existing component finally
   being used, plus the two spans a row needs to hold a kicker and a time.

   88x62 measured against the real rail rather than assumed: the column is 320px
   at 1366, so 88 + 12 gap leaves 220px of headline — about 26 characters a line
   at 15.5px, which carries a normal headline in two or three lines. */
.tsp-rail--latest .tsp-rail__thumb { width: 88px; height: 62px; }

.tsp-rail__body { min-width: 0; display: block; }

.tsp-rail__kicker {
	display: block;
	font-family: var(--tsp-font-ui);
	font-weight: 700;
	font-size: 10px;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: var(--tsp-red);
	margin: 0 0 3px;
}

/* TWO lines, not three. Measured: the text column is 220px beside an 88px
   thumbnail, which is about 26 characters a line, so every one of the five live
   headlines clamps at three lines AND at two — the column is the constraint,
   not the clamp, and a third line buys an ellipsis 20px lower rather than a
   finished sentence. Two keeps the module at 591px against 692px for three,
   which is the difference between a rail and a second article.

   A rail headline is a pointer, not the story: the reader is choosing what to
   open next, and the section, the picture and the first half of the headline
   are what they choose on. */
.tsp-rail--latest .tsp-rail__h3 {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.tsp-rail__time {
	display: block;
	margin-top: 4px;
	font-family: var(--tsp-font-ui);
	font-size: 11.5px;
	color: var(--ts-muted, #676E7B);
}

/* ==========================================================================
   v1.10.387 — MORE STORIES BECOMES A LIST ON PHONES
   ========================================================================== */

/* The grid drops to one column below the desktop breakpoint, which turned six
   recommendations into six full-width cards with 16:10 pictures: measured 2,181px
   at 390 and 3,427px at 768 — a second article's worth of scrolling after the
   article. That is not a reason to publish fewer stories, so all six stay and
   the ROW gets smaller instead.

   Same shape the desks and the rail already use on a phone: picture left,
   kicker and headline right. The three spans the card already emits are placed
   with grid areas rather than re-marked-up, so the desktop three-column grid,
   the selection logic and the de-duplication are all untouched.

   96px keeps the picture identifiable at 16:10 (60px tall) and leaves ~242px of
   headline at 390 — about three lines, which is what the desks carry.

   THE BREAKPOINT IS 900, NOT THE USUAL 781.98. This has to match the grid's own
   switch rather than the phone boundary: `.tsp-art__rgrid` goes single-column at
   `max-width:900px`, so keying this to 781.98 left 782–900 as one column of
   full-width cards — measured 3,427px at 782, the worst figure on the page and
   worse than the phone it was meant to fix. The two rules describe the same
   layout state, so they take the same width. */
@media (max-width: 900px) {

	.tsp-art__rgrid {
		gap: 0;
	}

	.tsp-art__rcard {
		display: grid;
		grid-template-columns: 96px minmax(0, 1fr);
		column-gap: 12px;
		align-items: start;
		padding: 12px 0;
		border-bottom: 1px solid var(--tsp-hairline);
	}

	.tsp-art__rcard:last-child { border-bottom: 0; }

	.tsp-art__rmedia {
		grid-column: 1;
		grid-row: 1 / span 2;
		aspect-ratio: 16 / 10;
		margin-bottom: 0;
	}

	.tsp-art__rk { grid-column: 2; grid-row: 1; }

	.tsp-art__rt {
		grid-column: 2;
		grid-row: 2;
		font-size: 16px;
		margin-top: 3px;
		display: -webkit-box;
		-webkit-line-clamp: 3;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}
}

/* Justified prose needs hyphenation, or it needs to stop being justified.
 *
 * The browser default is `hyphens: manual`, so a 720px measure was setting lines
 * like "The government has established a clear schedule to expedite revenue
 * record" by stretching the word spaces instead of breaking a word. The result
 * is the rivers of white visible running down the column at 1600. `hyphens:
 * auto` is the correction; it needs a `lang` to pick a dictionary, and the
 * document declares en-US.
 *
 * CORRECTION, v1.10.605. This note used to say the body "inherits `text-align:
 * justify` from the theme — nothing in this stylesheet asks for it". That was
 * wrong, and it mattered: it recorded the desktop's justification as somebody
 * else's property, which is why nothing here ever claimed it and why articles
 * written by hand went unjustified for so long without the cause being obvious.
 * Measured on staging, no theme rule and no Blocksy setting justifies this text
 * — the rivers described above were in generated articles, which arrived
 * pre-justified by their own inline rule. The justification is now this
 * stylesheet's, declared at the end of this file, so the sentence is true today
 * in a way it was not when written.
 *
 * `li` is included here but is never justified by us, so its hyphenation is
 * ragged-right hyphenation — defensible, but not something this rule set out to
 * do. Left as-is rather than changed in passing; it predates this patch.
 */
.tsp-art__body p,
.tsp-art__body li {
	hyphens: auto;
	-webkit-hyphens: auto;
}

/* The 800px measure is a DESKTOP composition fix, so it stops at the desktop.
 *
 * It exists to close the dead strip between the prose and the rail. Below 901px
 * the rail drops underneath and there is no strip to close, while the main
 * column becomes full width — so the cap would land there as a plain widening
 * of the measure on a tablet, which is not what it is for. Measured at 900:
 * prose went 720 to 800 when the cap first shipped.
 *
 * This lives at the END of the sheet on purpose. The unconditional
 * `.tsp-art__body` cap further up has the same specificity, so an override
 * placed beside the other 900px rules lost to it on source order — which is
 * exactly what happened on the first attempt.
 */
@media (max-width: 900px) {
	.tsp-art__body { max-width: none; }
}

/* The 16px rule the rail needs so iOS does not zoom the page on focus. The tail
 * band used to be listed here too; it takes the same rule from the shared Scope
 * Briefing sheet now, along with the rest of its field treatment. */
@media (max-width: 900px) {
	.tsp-rail input[type="email"] {
		font-size: 16px;
	}
}

/* Consent notice on the sidebar rail.
 *
 * The rail carries `background: var(--tsp-ink)`, and the first version of this
 * rule gave it `--tsp-muted` (#676E7B) on that #16181F panel — about 2.5:1,
 * well under AA, on the one sentence that tells a reader what happens to their
 * address. It takes the same #aeb4be the rail uses for its own supporting copy,
 * which is ~8.9:1.
 *
 * v1.10.421: the tail band's copy of this moved to the shared Scope Briefing
 * sheet, where it is stated once for both red placements. */
.tsp-rail__consent {
	margin: 8px 0 0;
	font-family: var(--tsp-font-ui);
	font-size: 12px;
	line-height: 1.5;
	color: #aeb4be;
}
.tsp-rail__consent a { color: #fff; text-decoration: underline; }

/* The RAIL's email field stays white in every state, for the same reason the
 * two red placements' do: Blocksy's `input:is([type=email],…):focus` computes
 * to (0,2,1) and out-specifies a two-class selector, so focusing the field
 * dropped its background to transparent and repainted the text in the theme's
 * slate blue — here, on a near-black panel. These selectors are (0,2,2).
 * -webkit-text-fill-color is set because it overrides `color` on Blink, and
 * autofill is covered with an inset shadow because Chrome paints its own
 * background outside the cascade.
 *
 * v1.10.421: the tail band's identical copy of all of this is gone — it reads
 * the shared Scope Briefing sheet now. The rail keeps its own because it also
 * renders on category archives, which style it as a different panel entirely. */
.tsp-rail--news form input[type="email"],
.tsp-rail--news form input[type="email"]:hover,
.tsp-rail--news form input[type="email"]:focus,
.tsp-rail--news form input[type="email"]:focus-visible,
.tsp-rail--news form input[type="email"]:active {
	background-color: #fff;
	color: var(--tsp-ink, #16181F);
	-webkit-text-fill-color: var(--tsp-ink, #16181F);
	caret-color: var(--tsp-ink, #16181F);
	border-color: transparent;
}

.tsp-rail--news form input[type="email"]::placeholder {
	color: var(--tsp-muted, #676E7B);
	-webkit-text-fill-color: var(--tsp-muted, #676E7B);
	opacity: 1;
}

.tsp-rail--news form input[type="email"]:-webkit-autofill,
.tsp-rail--news form input[type="email"]:-webkit-autofill:hover,
.tsp-rail--news form input[type="email"]:-webkit-autofill:focus {
	-webkit-box-shadow: inset 0 0 0 100px #fff;
	box-shadow: inset 0 0 0 100px #fff;
	-webkit-text-fill-color: var(--tsp-ink, #16181F);
	caret-color: var(--tsp-ink, #16181F);
	transition: background-color 100000s ease-in-out 0s;
}

/* A focus ring visible on the near-black rail, without relying on the theme's
 * outline colour, which is tuned for white pages. The band's ring — and the
 * homepage band's, which used to be declared in this file and therefore never
 * reached the homepage at all — now come from the shared component. */
.tsp-rail--news form input[type="email"]:focus-visible {
	outline: 3px solid #fff;
	outline-offset: 2px;
}

/* v1.10.421 — the rail's Subscribe button, at a specificity that reaches it.
 *
 * Found while checking that the band work had not regressed the sidebar. It
 * had not; these were already broken, and all three are the same failure — the
 * rail states what it wants at (0,1,1) and Blocksy answers later at the same
 * weight or higher:
 *
 *   hover  the button turned rgb(21,89,237) — the theme's link blue — on a
 *          near-black panel, because the rail declares a red background and no
 *          hover, so the theme's own :hover was the only rule in play;
 *   focus  the ring computed rgb(200,16,46) at 2px: brand red drawn around a
 *          brand-red button, which is not an indicator;
 *   radius the input asks for 8px and rendered 3px, so the field and the
 *          button under it disagreed about their own corners.
 *
 * Scoped through `.tsp-art__rail` on purpose. The same markup renders on
 * category archives, where category.css draws a deliberately different panel
 * at (0,2,x); scoping to the article's own wrapper keeps this off it.
 */
.tsp-art__rail .tsp-rail--news form input[type="email"] {
	border-radius: 8px;
	min-height: 44px;
}

.tsp-art__rail .tsp-rail--news form button {
	min-height: 44px;
	border-radius: 8px;
	background: var(--tsp-red);
	transition: background-color .16s ease;
}

.tsp-art__rail .tsp-rail--news form button:hover,
.tsp-art__rail .tsp-rail--news form button:focus-visible {
	background: #a50d26;
}

.tsp-art__rail .tsp-rail--news form button:focus-visible {
	outline: 3px solid #fff;
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	.tsp-art__rail .tsp-rail--news form button {
		transition: none;
	}
}

/* Stacked, a flex-basis is a HEIGHT.
 *
 * `flex-basis` sizes along the main axis, and the main axis becomes vertical
 * the moment the form turns into a column — measured at 320-430 the email field
 * once rendered 280px TALL. Below the breakpoint the controls simply go full
 * width and keep the component's own height.
 *
 * v1.10.421: 900 > 600, matching the form's own `flex-direction: column` rule
 * and the homepage placement. At 900 these rules sent the button onto a second
 * line while the centred 520px row still had 250px of clear space either side
 * of it — the composition stacked long before it was crowded. */
@media (max-width: 600px) {
	.tsp-art__band form input[type="email"] {
		flex: 0 0 auto;
		width: 100%;
	}
	.tsp-art__band form button {
		flex: 0 0 auto;
		width: 100%;
	}
}

/* v1.10.430 — justification stops where the measure can no longer carry it.
 *
 * The rule above chose `hyphens: auto` over ragged-right and said so plainly:
 * switching the template was "a design decision this fix has no mandate to
 * make". The UX audit is that mandate, and the measurements say the compromise
 * only works on wide measures:
 *
 *     320px   measure 288px  ~29 chars/line   15 of 57 lines end in a hyphen
 *     390px   measure 358px  ~38 chars/line   14 of 46
 *     768px   measure 720px  ~76 chars/line    8 of 25
 *    1440px   measure 776px  ~76 chars/line    5 of 23
 *
 * A quarter to a third of every line on a phone ending in a broken word is not
 * a rivers problem traded for a smaller one — it is the dominant texture of the
 * paragraph. Justification needs roughly sixty characters to distribute word
 * space without either rivers or constant hyphenation, and a phone column has
 * half that.
 *
 * So: ragged right below 600px, where the measure cannot support justifying,
 * and `hyphens: manual` with it so words are not broken when there is no
 * justification to serve. Above 600px nothing changes — the desktop keeps the
 * justified setting the design intended and the hyphenation that makes it work.
 */
@media (max-width: 600px) {
	.tsp-art__body p,
	.tsp-art__body li {
		text-align: left;
		hyphens: manual;
		-webkit-hyphens: manual;
	}
}

/* ===========================================================================
   v1.10.540 — justified article prose on the phone.
   v1.10.605 — and at every width, because the desktop never owned it.

   THE PLATFORM OWNS ARTICLE BODY TYPOGRAPHY. This rule is the whole contract:
   ordinary prose in a published article is justified because it is ordinary
   prose in a published article, not because of who or what typed it.

   What it replaced: desktop justification was never in this stylesheet, and the
   note further up claiming the body "inherits `text-align: justify` from the
   theme" was wrong — measured on staging, no theme rule and no Blocksy setting
   justifies this text. The desktop was justified by a single inline
   `<style>` rule shipped with generated content, matching a class stamped onto
   each paragraph as it was written. Articles typed by hand in WordPress carry no
   such class, so they computed `text-align: start` at 1440, 1024 and 768 while
   an otherwise identical article beside them computed `justify` — same
   template, same 800px measure, same `hyphens: auto`. A reader could tell how a
   story had been produced by looking at its right-hand edge.

   Presentation cannot depend on markup a generator inserted. The one narrow
   band where this template already looked right in both cases was 340–600px,
   because THIS rule was the thing applying it there and it never asked about a
   class. Extending its upper bound is therefore the entire fix: no new
   selector, no specificity contest, no rewriting of a single stored post.

   The generated class is left alone. It resolves to the same declaration, so it
   is now redundant rather than wrong, and it lives in another plugin's output —
   removing it would mean editing historical post content to change formatting,
   which this must not do.

   This deliberately reverses the rule directly above, which set the phone
   ragged-right. That rule was not arbitrary and its evidence still stands:

       320px   measure 288px  ~29 chars/line   15 of 57 lines ended hyphenated
       390px   measure 358px  ~38 chars/line   14 of 46

   The owner's instruction is that long-form mobile should carry the justified
   newspaper setting the desktop already has, with the explicit provision that a
   breakpoint which produces visibly unacceptable spacing takes the safest
   fallback instead. So this justifies, and the QA below decides how far down.

   Scope is `> p` on purpose. Only a direct child of the prose container is
   article body text; a blockquote's paragraph, a figure's caption and the Key
   Points aside are all nested a level deeper, so none of them is touched, and
   `li` is left out of the selector entirely. Headline, deck, kicker, byline and
   the meta line live outside `.tsp-art__body` altogether.

   Paragraphs the editor has explicitly aligned keep that alignment - an author
   who centred a line meant it.
   =========================================================================== */
/* The lower bound is 340, decided by QA rather than by taste. Measured on real
   articles at 1.10.540, word-space width in px (a normal space is ~4-5px here)
   and the share of lines the browser had to break mid-word:

     English   320: med 8.0  p95 19.8  MAX 59.3   29% of lines hyphenated
               360: med 8.5  p95 19.0  max 44.7   22%
               390: med 7.3  p95 17.8  max 32.8   24%
               414: med 6.9  p95 14.8  max 24.3   24%
               430: med 7.6  p95 17.7  max 22.0   20%

     Telugu    320: med 16.1 p95 30.8  MAX 73.4   0 mid-word breaks
               360: med 12.6 p95 20.9  max 21.9   0
               390: med 10.2 p95 25.9  max 50.4   0
               414: med 10.0 p95 17.8  max 40.8   0
               430: med 6.9  p95 15.7  max 15.7   0

   320 is the outlier in both languages and it is visible on screen, not just in
   the table: rivers run down the column, and in English nearly a third of the
   lines end in a broken word. Telugu is looser than English throughout, which
   is expected - it has no hyphenation dictionary to fall back on, so word space
   is the only thing that can absorb a long word - but at 340 and above it
   settles into the texture Telugu newspapers actually set.

   So justification runs 340-600 and a 320 phone keeps the ragged right the rule
   above gives it. That is the fallback the work order asks for at a breakpoint
   where spacing would otherwise damage readability.

   The zero mid-word break count for Telugu at every width is the important
   number: it is the evidence that no conjunct or vowel sign is being split.

   v1.10.605 removed the `max-width: 600px` half of this query. The lower bound
   is doing real work and stays — 320 is where the measure stops supporting
   justification and a phone there keeps the ragged right the rule above gives
   it. The upper bound was never protecting anything: above 600px the measure
   only gets wider, which is the comfortable direction for justified text, and
   at 768/1024/1440 it is 800px and ~76 characters — the width the p95 word-space
   figures above improve monotonically towards. It was an upper bound only
   because the patch that introduced it was scoped to the phone. */
@media (min-width: 340px) {
	.tsp-art__body > p:not([class*="has-text-align"]) {
		text-align: justify;
		/* Never `distribute` or `inter-character`: those add space BETWEEN
		   letters, which on Telugu means prising apart the glyph clusters that
		   make up a syllable. Word spacing is the only safe lever here. */
		text-justify: inter-word;
		/* Improves the last line, which is the one justification cannot help. */
		text-wrap: pretty;
	}

	/* English gets hyphenation, because at ~30-38 characters a line justified
	   text without it is all rivers. The document declares en-US, which is what
	   gives the browser a dictionary to work from. */
	:lang(en) .tsp-art__body > p:not([class*="has-text-align"]) {
		hyphens: auto;
		-webkit-hyphens: auto;
	}

	/* Telugu gets none of it. There is no Telugu hyphenation dictionary to ask
	   for, and every automatic breaking property that could fire instead -
	   `word-break: break-all`, `overflow-wrap: break-word/anywhere` - breaks on
	   grapheme boundaries the shaper does not agree with, which is how a
	   conjunct or a vowel sign ends up orphaned on the next line. Telugu words
	   are separated by spaces, so word spacing alone has something to work
	   with; these are stated rather than left to inherit so that nothing
	   upstream can quietly turn character breaking on for this text. */
	:lang(te) .tsp-art__body > p:not([class*="has-text-align"]) {
		hyphens: manual;
		-webkit-hyphens: manual;
		word-break: normal;
		overflow-wrap: normal;
		line-break: auto;
	}
}

/* ===========================================================================
   v1.10.606 — Telugu was being cut mid-word to make a straight edge.

   The rule directly above is the right rule and was in the wrong place: it sat
   inside the phone-only query, so it protected 340–600px and NOTHING ELSE. Every
   Telugu article on a desktop was unprotected, and two separate mechanisms were
   damaging the text there.

   MEASURED on a live Telugu article at 1536px, before this patch:

     text-align      justify        (from the generated paragraph class)
     overflow-wrap   break-word     (INHERITED FROM `body` — the theme sets it)
     hyphens         auto           (from this stylesheet, unconditional)

   12 mid-word breaks in one article. They were not near-misses:

     ఢిల్లీల|ోని       vowel sign ో orphaned onto the next line
     సాధ|్యమవుతుంది    split inside the conjunct ధ్య
     అడవుల|్లో         split inside the conjunct ల్లో
     ఉన్నత|ాధికారి     vowel sign ా orphaned

   And on screen it was worse than the count: `hyphens: auto` was printing
   LITERAL HYPHENS into Telugu — "అత్యా-", "ఢిల్లీ-", "ఉన్న-". Telugu does not
   hyphenate. Chrome will happily apply a generic dictionary if asked, and this
   stylesheet was asking, at every width above 600.

   ---------------------------------------------------------------------------
   1. Safe wrapping is UNCONDITIONAL, not a phone treatment.

   No media query and no `:not([class*="has-text-align"])`. Breaking a Telugu
   word is wrong at 320 and wrong at 1920, and it is just as wrong in a
   paragraph the author centred. `p` rather than `> p` so a blockquote's
   paragraph and a caption are covered too — nothing about a conjunct changes
   because the text moved one level down the tree.

   v1.10.643 ADDS `li`. The rule shipped covering `p` only, while the
   unconditional `hyphens: auto` twelve hundred lines above names BOTH
   `.tsp-art__body p` and `.tsp-art__body li`. So a Telugu list item asked
   Chrome for automatic hyphenation from 601px up -- measured, not inferred:
   `<p>` manual at every width, `<li>` auto at 601, 768 and 1440, protected
   below 600 only because the phone rule happens to name `li` too.

   Inert today: Chromium ships no Telugu hyphenation dictionary, so `auto`
   resolves to nothing. It is fixed because the asymmetry is the defect --
   the same script, the same container, two different answers -- and because
   "inert" depends on a browser's dictionary list, which is not this
   stylesheet's to promise.

   This also closes the gap below 340px, which the rule above never reached. It
   is a quiet gap rather than a loud one — ragged text only forces a break when a
   single word cannot fit the column, so it fires rarely and looks like a typo
   when it does.
   =========================================================================== */
:lang(te) .tsp-art__body p,
:lang(te) .tsp-art__body li {
	hyphens: manual;
	-webkit-hyphens: manual;
	word-break: normal;
	overflow-wrap: normal;
	line-break: auto;
}

/* ---------------------------------------------------------------------------
   2. The overflow guard, kept separate from prose.

   Turning `overflow-wrap` off would otherwise let one unbroken token — a bare
   URL, a path, a long identifier — push the column sideways and break the page.
   That risk is real but it does not live in ordinary prose, so it is not
   answered there: it is answered on the elements that actually carry such
   tokens, in BOTH editions.

   `break-word`, deliberately, not `anywhere`: `break-word` breaks a token only
   when it cannot fit a line by itself, so a linked Telugu phrase wraps normally
   at its spaces and only a genuinely unbreakable string is cut. `anywhere`
   would also shrink min-content and start breaking ordinary linked words.

   Accepted edge case, stated rather than hidden: a single Telugu word longer
   than the column INSIDE a link can still be broken. Preventing page overflow
   wins there, and it is the narrow case the work order asks to handle
   separately.
   --------------------------------------------------------------------------- */
.tsp-art__body a,
.tsp-art__body code,
.tsp-art__body pre,
.tsp-art__body kbd,
.tsp-art__body samp {
	overflow-wrap: break-word;
}

/* ---------------------------------------------------------------------------
   3. Telugu justifies at every width English does — owner decision, 29 Aug 2026.

   HISTORY, kept because the measurements are real and someone will want them.
   An earlier revision stopped Telugu justifying below 600px. Telugu has no
   hyphenation dictionary, so word space is the only slack justification can use,
   and the column pays for a straight edge in gaps. Measured on a real article
   with safe wrapping on, word-space width in px (a normal space is 4.2px), all
   with ZERO mid-word breaks:

     320   ragged already          4.2 / 4.2 / 4.2
     390   med 11.8  p95 20.8  MAX 46.9      <- 11x a normal space
     430   med 11.1  p95 21.9  max 28.8
     520   med  7.9  p95 16.4  max 16.7
     600   med  6.9  p95 13.2  max 14.7
     768   med  7.0  p95 11.8  max 11.8
     1440  med  7.2  p95 12.3  max 12.4

   Re-measured at 1.10.624 before this change, same article at 390: ragged gives
   a uniform 4.2px; justified gives med 8.6, p95 26.8, max 37.6.

   WHY IT CHANGED ANYWAY. That rule was this stylesheet applying the v1.10.540
   provision that "a breakpoint which produces visibly unacceptable spacing takes
   the safest fallback instead". The owner is the judge of visibly unacceptable,
   reviewed the result on a real phone, and ruled the other way: the ragged
   mobile column read worse to them than the wider gaps do, and the two editions
   disagreeing at the same width read as a fault rather than as care.

   So the Telugu override is gone and both editions now take the shared
   `min-width: 340px` rule above. Below 340 both stay ragged — that floor is
   unchanged and is where the numbers are not close for either language.

   NOTHING ELSE MOVED. The Telugu safety properties immediately below —
   `hyphens: manual`, `word-break: normal`, `overflow-wrap: normal`,
   `line-break: auto` — are what keep a conjunct or a vowel sign from being
   orphaned across a line, and they are untouched. Justification stretches word
   spaces only; it never introduces a break.

   TO REVERT, restore:
       @media (max-width: 600px) {
           :lang(te) .tsp-art__body > p:not([class*="has-text-align"]) {
               text-align: start;
           }
       }
   --------------------------------------------------------------------------- */

/* ===========================================================================
   v1.10.631 — THE MOBILE ARTICLE READING CONTRACT.

   Owner brief, 30 August 2026: the article body on a phone "feels too dense and
   too desktop-derived". Diagnosed rather than tuned, and the brief is right
   about the cause — the phone was using the DESKTOP's vertical rhythm at a much
   narrower measure. Measured on a real Telugu article:

                       390 (phone)      1024 (desktop)
     characters/line        40                68
     body / line-height   18 / 30.6        19 / 32.3
     paragraph gap          24                24     <- identical
     space above h2         34                34     <- identical
     space below h2         16                16     <- identical

   Three numbers that should differ with the measure did not differ at all.

   1. PARAGRAPH GAP 24 -> 30. At 24px against a 30.6px line-height, the space
      BETWEEN paragraphs was smaller than the space between two lines inside
      one. Paragraphs stopped reading as paragraphs. 30 is one line, which is
      the least that separates them; it costs ~6px per paragraph in scroll and
      buys the rhythm the brief is asking for.

   2. SPACE ABOVE A HEADING 34 -> 44. With the paragraph gap at 30, a 34px gap
      above an h2 is four pixels more than an ordinary paragraph break — the
      heading stopped being a section boundary. 44 is a clear break at a glance.

   3. SPACE BELOW A HEADING 16 -> 12. A heading belongs to what follows it, and
      the above:below ratio does the work: 44 above against 12 below binds the
      heading to its own section instead of floating between two.

   DESKTOP IS UNTOUCHED. Every rule here is inside max-width:600px, and the
   desktop measure at 68 characters is comfortable as it stands.
   =========================================================================== */
@media (max-width: 600px) {

	.tsp-art__body > p {
		/* One line-height, so a paragraph break is never tighter than a line. */
		margin-bottom: 30px;
	}

	.tsp-art__body h2 {
		margin-top: 44px;
		margin-bottom: 12px;
	}
}

/* ===========================================================================
   v1.10.631 — Telugu goes back to ragged right below 600px.

   THIS REVERSES THE CENTRAL CHANGE OF v1.10.630, on the owner's explicit
   instruction in the same brief: "If justified Telugu creates obvious rivers or
   large gaps between words, prefer start alignment on mobile. Readability is
   more important than forcing a straight right edge."

   It does. Measured on the live Telugu article, every word gap on the first
   four paragraphs wrapped and measured individually — 126 gaps, normal space
   4.2px, zero mid-word breaks in every case:

       width   median gap        p95      worst        lines
        320    4.2  (1.0x)       4.2      4.2  (1.0x)    39   <- already ragged
        360   12.9  (3.1x)      28.4     37.4  (8.9x)     35
        390   16.1  (3.8x)      32.3     39.0  (9.3x)     33
        414   10.1  (2.4x)      29.1     40.6  (9.7x)     30
        600    8.0  (1.9x)      14.2     14.2  (3.4x)     19
        768    7.9  (1.8x)      17.3     17.3  (3.9x)     16
       1024    8.6  (2.0x)      15.1     15.1  (3.4x)     19

   The inflection at 600 is not marginal. Below it the median gap is two to four
   times a normal space and the worst lines reach nine; at and above it the
   median settles near 1.9x and the worst never passes 3.9x.

   THE DECIDING NUMBER IS THE LINE COUNT. The same article, same width, ragged
   instead of justified, produces THE SAME 33 LINES at 390 — with every gap a
   uniform 4.2px. Justification is not buying a shorter column or a denser one.
   It redistributes the identical text into visibly uneven gaps and returns
   nothing for them.

   v1.10.630 removed this override after the owner judged the ragged column
   worse on a phone. That judgement was made against the previous typography;
   this brief re-opened it explicitly, with instructions to measure and to
   prefer readability. The measurements above are what the earlier decision did
   not have.

   ENGLISH IS UNTOUCHED and stays justified from 340 up: it has a hyphenation
   dictionary, which is the slack Telugu does not have.

   The Telugu safety properties are untouched — `hyphens: manual`,
   `word-break: normal`, `overflow-wrap: normal`, `line-break: auto`. Ragged
   alignment cannot introduce a break; it only stops stretching the spaces.
   =========================================================================== */
/* ---------------------------------------------------------------------------
   v1.10.646 — REVERSED ON OWNER INSTRUCTION. Telugu is justified on the phone.

   The owner sent a side-by-side: our Telugu article on a phone against the same
   view of sakshi.com, and asked for the Sakshi treatment — a straight right
   edge. That is the third time this alignment has been looked at on a real
   device and the second time the owner has said the ragged rag is not what they
   want, so the earlier reading of "there is nothing wrong with the Telugu rag"
   is retired rather than re-argued.

   WHAT THIS COSTS, measured rather than asserted — see the v1.10.642 note above
   for the method. Telugu has no hyphenation dictionary, so justification has
   only word spacing to work with and every shortfall lands in the gaps between
   words. Ragged Telugu measured a flat 4.0px word space at every phone width;
   justified it necessarily varies. The measured figures are recorded in
   CHANGELOG 1.10.646.

   WHAT IS DELIBERATELY NOT CHANGED:

   - The Telugu SAFETY properties. `hyphens: manual`, `word-break: normal`,
     `overflow-wrap: normal`, `line-break: auto` all still apply from the
     min-width:340px block. Justification stretches spaces BETWEEN words; it
     cannot introduce a break inside one, so no conjunct is at risk. That is
     also why `text-justify: inter-word` is set there and `distribute` is
     banned — the latter would prise apart the glyph clusters inside a syllable.
   - Below 340px. The justify rule this now defers to starts at 340px, so a
     320px phone keeps its ragged right. At that measure Telugu justification
     has too little to distribute and the gaps become the texture of the
     paragraph. Raising that floor is a separate decision.
   - English, which has been justified on the phone since v1.10.540 and keeps
     its `hyphenate-limit-chars` tuning from v1.10.642.

   Stated explicitly rather than deleted: with the override gone Telugu would
   inherit justification silently, and the next person to read this file should
   see that the phone alignment is intended, not accidental.
   --------------------------------------------------------------------------- */
@media (min-width: 340px) and (max-width: 600px) {
	:lang(te) .tsp-art__body > p:not([class*="has-text-align"]) {
		text-align: justify;
		text-justify: inter-word;
	}
}

/* ===========================================================================
   v1.10.634 — the Telugu mobile column reads as a column, not as fragments.

   THE OWNER'S OBSERVATION, on a real iPhone 13 Pro Max: desktop and tablet look
   good, the mobile article body does not look professionally typeset, and the
   problem is much more obvious WHILE SCROLLING THROUGH LONG PARAGRAPHS than in
   a screenshot of the top of the page.

   WHAT THE MEASUREMENTS SAID, AND WHY THEY WERE NOT THE ANSWER. Every container
   — h1, lead image, figure, body, first paragraph, h2 — has identical left and
   right coordinates at 320, 360, 390, 428 and 768. Δ0 everywhere. The brief
   warned that this would be true and that it would not be the point, and it was
   right: the fault is optical, not arithmetic.

   WHAT IS ACTUALLY WRONG, measured at 428x926 on a real article:

     body size / line-height   18px / 30.6px
     measure                   396px
     words per line            5.5          <- the number that causes everything
     paragraph gap             30px         <- one full line-height
     paragraphs                37 across 117 lines = 3.2 lines each
     rag: worst line ending    122px short of the measure, on a 396px column

   At five and a half words to the line, a single long Telugu word that will not
   fit leaves a third of the column empty. Paragraphs run to one, two or three
   lines. Between every one of them sits a gap exactly as tall as a line. The
   result is not a column of prose; it is a stack of small blocks separated by
   white channels, and that is what reads as unprofessional however well the
   containers line up.

   THE 30px GAP IS MINE, FROM v1.10.631, AND THE REASONING WAS IMPORTED FROM THE
   WRONG SETTING. I raised it from 24 on the rule that a paragraph break should
   never be tighter than the space between two lines. That rule is true of
   JUSTIFIED text, where every line reaches the measure and the gap is the only
   signal a paragraph ended. In a RAGGED setting the short last line is already
   the signal — so the gap does not have to exceed a line-height, and when it
   does, it opens a channel instead of marking a break.

   JUSTIFICATION WAS RE-TESTED RATHER THAN ASSUMED, at four sizes, because the
   brief asked for that and because v1.10.631's decision deserved re-checking
   rather than citing. Word gaps against a 3.7-4.2px normal space:

     18.0px justified   median 8.3   p95 20.2   max 45.0
     16.5px justified   median 6.9   p95 20.5   max 33.1
     15.5px justified   median 8.0   p95 20.8   max 26.4
     14.5px justified   median 6.3   p95 16.4   max 27.8

   Shrinking the type does reduce the worst gap, and never far enough: a 95th
   percentile of four to five times a normal space is a river on every screen.
   Telugu has no hyphenation dictionary, so word space is the only slack, and at
   ~6 words per line there are too few gaps to divide the shortfall between.
   The v1.10.631 decision stands, now on evidence rather than on memory.

   WHAT CHANGED, AND WHY EACH NUMBER.

   1. BODY 18px -> 17px, line-height 1.7 -> 1.75. Not to make the text smaller
      for its own sake — to buy back column. The worst line ending improves from
      122px short to 108px, lines run visibly fuller, and the extra leading keeps
      Telugu's stacked vowel signs clear at the smaller size. 17px is a floor,
      not a target: below it the matras start to crowd, which is why 15.5 and
      14.5 were measured and rejected for reading rather than for rag.

   2. PARAGRAPH GAP 30px -> 20px, TELUGU ONLY. Enough to mark a break, not
      enough to open a channel. The last line of a ragged paragraph does most of
      the work already.

   3. HEADING SPACE 44/12 -> 36/10, to keep the same proportion against the
      tighter rhythm. A heading that was a clear boundary at a 30px gap would
      shout at a 20px one.

   ENGLISH IS UNTOUCHED, and this is why the rules are :lang(te). English on a
   phone is justified from 340px up, because it HAS a hyphenation dictionary —
   so every line reaches the measure, and it genuinely does need a gap of at
   least a line-height to show a paragraph ended. The two editions need
   different numbers for the same reason they need different alignment.

   DESKTOP AND TABLET ARE UNTOUCHED: everything here is inside max-width:600px,
   and at 768 and above the measure is wide enough that none of this applies.
   =========================================================================== */
@media (max-width: 600px) {

	:lang(te) .tsp-art__body > p,
	:lang(te) .tsp-art__body > ul,
	:lang(te) .tsp-art__body > ol {
		font-size: 17px;
		line-height: 1.75;
	}

	:lang(te) .tsp-art__body > p {
		margin-bottom: 20px;
	}

	:lang(te) .tsp-art__body h2 {
		margin-top: 36px;
		margin-bottom: 10px;
	}
}

/* ===========================================================================
   v1.10.642 — English keeps its straight edge and stops paying for it one
   broken word in four.

   THE OWNER IS LOOKING AT A TELUGU ARTICLE AND SAYING MOBILE STILL LOOKS
   WRONG. Measured on staging at 1.10.641, both editions, seven phone widths:

     Telugu   ragged right, 0 broken words at every width, every word space
              exactly 4.0px. There is nothing wrong with the Telugu rag.

     English  justified, and 21-24% of lines end in a word the browser broke:
              360: 12 of 51   375: 10 of 48   390: 11 of 46   430: 10 of 41

   So the typographic defect is on the OTHER edition from the one that prompted
   the report. A quarter of lines ending mid-word is what v1.10.430 described as
   "the dominant texture of the paragraph", and it is still there — v1.10.540
   reversed that patch on an owner instruction to carry the justified newspaper
   setting onto the phone, and recorded the 24% as the price.

   THIS PAYS LESS OF THAT PRICE WITHOUT GIVING UP THE SETTING THE OWNER ASKED
   FOR. `hyphenate-limit-chars: 9 4 4` refuses to break a word shorter than nine
   characters, and leaves at least four on each side of any break it does make.
   That is the conventional typographic minimum rather than a number tuned to
   this page. Measured with it applied, same articles and widths:

                       broken lines        word space med / p95 / max
     before   360         12  (24%)              8.0 / 19.8 / 31.0
     after    360          4   (8%)              7.9 / 24.5 / 31.6
     before   390         11  (24%)              7.9 / 15.2 / 20.3
     after    390          5  (11%)              8.5 / 16.7 / 22.6
     before   430         10  (24%)              6.7 / 15.5 / 23.3
     after    430          4  (10%)              7.2 / 17.1 / 23.3

   THE TRADE IS DELIBERATE AND IT IS NOT FREE. Fewer hyphens means word space
   absorbs more of the shortfall, so the 95th percentile gap rises by two to
   five pixels. A gap a reader's eye slides over is a smaller cost than a word
   cut in half every fourth line, which the eye cannot slide over at all —
   that is the whole judgement here, and it is a judgement rather than a
   measurement.

   `10 5 4` was measured too and reached 6-9% for the same gaps. It is not used:
   nine characters is the value a typographer would recognise, and the extra two
   points are not worth a number nobody else would understand.

   TELUGU IS DELIBERATELY NOT TOUCHED. It has no hyphenation dictionary to
   limit, it already breaks no words, and its phone treatment was tuned on
   evidence at v1.10.631 — 17px, 1.75, 20px paragraph gap, with 15.5px and
   14.5px measured and rejected for reading. Nothing above 600px is touched
   either: the desktop measure is ~76 characters, where justified text with
   hyphenation is comfortable and this limit would only make it stiffer.
   =========================================================================== */
@media (max-width: 600px) {
	:lang(en) .tsp-art__body > p:not([class*="has-text-align"]) {
		hyphenate-limit-chars: 9 4 4;
		-webkit-hyphenate-limit-chars: 9 4 4;
	}
}
