.tsp-news-ticker,.tsp-social-icons{container-type:inline-size}/* MANDATORY wrapper standard: container-type lives HERE, never on the section (see DEVELOPERS.md) */.tsp-eb-wrap{container-type:inline-size;width:100%}.tsp-eb{box-sizing:border-box;background:var(--tsp-section-bg,transparent);color:var(--tsp-text-color,inherit);margin-top:var(--tsp-mt,0);margin-bottom:var(--tsp-mb,32px);padding:var(--tsp-pt,0) var(--tsp-pr,0) var(--tsp-pb,0) var(--tsp-pl,0)}
.tsp-eb *{box-sizing:border-box}.tsp-eb a{text-decoration:none;color:inherit}.tsp-eb-heading{margin:0 0 16px}.tsp-eb-heading h2,.tsp-eb-heading h3,.tsp-eb-heading h4,.tsp-eb-heading div{margin:0;color:var(--tsp-title-color,inherit);font-weight:800}.tsp-eb-heading--accent-line{border-left:5px solid var(--tsp-accent,#ed1c24);padding-left:10px}.tsp-eb-heading--border{border-bottom:2px solid var(--tsp-accent,#ed1c24);padding-bottom:8px}.tsp-eb-heading--filled>*{display:inline-block;background:var(--tsp-accent,#ed1c24);color:#fff;padding:6px 12px}.tsp-eb-category{display:inline-block;background:var(--tsp-accent,#ed1c24);color:#fff;font-weight:700;padding:3px 7px;text-transform:uppercase}.tsp-eb time{font-size:12px;opacity:.8}.tsp-eb-placeholder{display:block;width:100%;height:100%}.tsp-eb-empty{padding:20px;border:1px dashed #bbb;background:#fafafa}
.tsp-feature-grid__items{display:grid;grid-template-columns:2fr 1fr 1fr;grid-template-rows:repeat(2,minmax(var(--tsp-row-h,180px),1fr));gap:var(--tsp-gap,4px)}.tsp-feature-card{position:relative;min-height:var(--tsp-card-min,220px);overflow:hidden;border-radius:var(--tsp-radius,0);background:#222}.tsp-feature-card.is-lead{grid-row:1/3}.tsp-feature-card__link,.tsp-feature-card__media,.tsp-feature-card__media img{display:block;width:100%;height:100%}.tsp-feature-card__media img{object-fit:cover}.tsp-feature-card__overlay{position:absolute;inset:0;background:linear-gradient(transparent 25%,rgba(0,0,0,var(--tsp-overlay,.55)))}.tsp-feature-card__content{position:absolute;left:0;right:0;bottom:0;padding:16px;color:var(--tsp-title-color,#fff)}.tsp-feature-card h3{font-size:var(--tsp-card-title,20px);line-height:1.15;margin:7px 0;color:inherit}.tsp-feature-card.is-lead h3{font-size:var(--tsp-lead-title,30px)}.tsp-feature-card p{margin:7px 0 0}.tsp-feature-grid--lead-list .tsp-feature-grid__items{grid-template-columns:2fr 1fr;grid-template-rows:auto;align-items:start;display:grid}.tsp-feature-grid--lead-list .tsp-feature-card.is-lead{min-height:var(--tsp-lead-min,420px);grid-row:auto}.tsp-feature-grid--lead-list .tsp-feature-card:not(.is-lead){min-height:0;background:transparent;border-radius:0;margin-bottom:14px}.tsp-feature-grid--lead-list .tsp-feature-card:not(.is-lead) .tsp-feature-card__link{display:flex;gap:10px;align-items:flex-start;height:auto}.tsp-feature-grid--lead-list .tsp-feature-card:not(.is-lead) .tsp-feature-card__media{position:relative;flex:0 0 80px;width:80px;height:80px;border-radius:6px;overflow:hidden}.tsp-feature-grid--lead-list .tsp-feature-card:not(.is-lead) .tsp-feature-card__overlay{display:none}.tsp-feature-grid--lead-list .tsp-feature-card:not(.is-lead) .tsp-feature-card__content{position:static;padding:0;color:var(--tsp-text-color,#222)}.tsp-feature-grid--lead-list .tsp-feature-card:not(.is-lead) h3{font-size:15px;margin:0;line-height:1.35}.tsp-feature-grid--lead-list .tsp-feature-card:not(.is-lead) time{font-size:12px;opacity:.7;display:block;margin-top:4px}.tsp-feature-grid--split-columns .tsp-feature-grid__items{display:grid;grid-template-columns:1fr 1fr;gap:32px;grid-auto-flow:row}.tsp-feature-grid--split-columns .tsp-feature-card.is-lead{grid-column:span 1;min-height:280px}.tsp-feature-grid--split-columns .tsp-feature-card:not(.is-lead){min-height:0;background:transparent;border-radius:0;margin-top:10px}.tsp-feature-grid--split-columns .tsp-feature-card:not(.is-lead) .tsp-feature-card__link{display:flex;gap:10px;align-items:flex-start;height:auto}.tsp-feature-grid--split-columns .tsp-feature-card:not(.is-lead) .tsp-feature-card__media{position:relative;flex:0 0 72px;width:72px;height:72px;border-radius:6px;overflow:hidden}.tsp-feature-grid--split-columns .tsp-feature-card:not(.is-lead) .tsp-feature-card__overlay{display:none}.tsp-feature-grid--split-columns .tsp-feature-card:not(.is-lead) .tsp-feature-card__content{position:static;padding:0;color:var(--tsp-text-color,#222)}.tsp-feature-grid--split-columns .tsp-feature-card:not(.is-lead) h3{font-size:14px;margin:0;line-height:1.3}
.tsp-feature-grid--balanced .tsp-feature-grid__items{grid-template-columns:repeat(5,1fr);grid-template-rows:1fr}.tsp-feature-grid--balanced .is-lead{grid-row:auto}.tsp-feature-grid--feature-list .tsp-feature-grid__items{grid-template-columns:2fr 1fr;grid-template-rows:repeat(4,var(--tsp-row-h,110px))}.tsp-feature-grid--feature-list .is-lead{grid-row:1/5}.tsp-feature-grid--three-column .tsp-feature-grid__items{grid-template-columns:repeat(3,1fr);grid-template-rows:auto}.tsp-feature-grid--three-column .is-lead,.tsp-feature-grid--four-column .is-lead{grid-row:auto}.tsp-feature-grid--four-column .tsp-feature-grid__items{grid-template-columns:repeat(4,1fr);grid-template-rows:auto}.tsp-feature-grid--single .tsp-feature-grid__items{grid-template-columns:1fr;grid-template-rows:minmax(380px,60vh)}.tsp-feature-grid--single .tsp-feature-card:not(:first-child){display:none}.tsp-feature-grid--single .is-lead{grid-row:auto}
.tsp-news-grid__items{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--tsp-gap,20px)}.tsp-news-card{overflow:hidden;border-radius:var(--tsp-radius,6px);background:var(--tsp-section-bg,#fff)}.tsp-news-card__media{aspect-ratio:16/9;overflow:hidden}.tsp-news-card__media img{width:100%;height:100%;object-fit:cover}.tsp-news-card__content{padding:12px}.tsp-news-card h3{color:var(--tsp-title-color,inherit);line-height:1.25;margin:8px 0}.tsp-news-card p{margin:8px 0 0}.tsp-news-grid--four-column .tsp-news-grid__items{grid-template-columns:repeat(4,minmax(0,1fr))}.tsp-news-grid--two-column .tsp-news-grid__items{grid-template-columns:repeat(2,minmax(0,1fr))}.tsp-news-grid--list .tsp-news-grid__items,.tsp-news-grid--compact .tsp-news-grid__items{grid-template-columns:1fr}.tsp-news-grid--list .tsp-news-card a{display:grid;grid-template-columns:220px minmax(0,1fr)}.tsp-news-card.is-lead h3{line-height:1.2}.tsp-news-grid--lead-left .tsp-news-grid__items{display:grid;grid-template-columns:2fr 1fr;align-items:start}.tsp-news-grid--lead-left .tsp-news-card.is-lead{grid-row:1/5}.tsp-news-grid--lead-left .tsp-news-card:not(.is-lead) a{display:grid;grid-template-columns:110px minmax(0,1fr);gap:10px;align-items:start}.tsp-news-grid--lead-left .tsp-news-card:not(.is-lead) h3{font-size:15px;margin:0}.tsp-news-grid--lead-right .tsp-news-grid__items{display:grid;grid-template-columns:1fr 2fr;align-items:start}.tsp-news-grid--lead-right .tsp-news-card.is-lead{grid-column:2;grid-row:1/5}.tsp-news-grid--lead-right .tsp-news-card:not(.is-lead){grid-column:1}.tsp-news-grid--lead-right .tsp-news-card:not(.is-lead) a{display:grid;grid-template-columns:110px minmax(0,1fr);gap:10px;align-items:start}.tsp-news-grid--lead-right .tsp-news-card:not(.is-lead) h3{font-size:15px;margin:0}.tsp-news-grid--two-leads-four .tsp-news-grid__items{display:grid;grid-template-columns:1fr 1fr}.tsp-news-grid--two-leads-four .tsp-news-card:not(.is-lead) a{display:grid;grid-template-columns:96px minmax(0,1fr);gap:10px;align-items:start}.tsp-news-grid--two-leads-four .tsp-news-card:not(.is-lead) h3{font-size:15px;margin:0}.tsp-news-grid--media-list .tsp-news-grid__items{display:grid;grid-template-columns:1fr}.tsp-news-grid--media-list .tsp-news-card a{display:grid;grid-template-columns:220px minmax(0,1fr);gap:16px;align-items:start}.tsp-news-grid--media-list .tsp-news-card h3{margin:0 0 6px}.tsp-news-grid--media-list .tsp-news-card p{margin:6px 0 0}.tsp-news-grid--sidebar-lead-compact .tsp-news-grid__items{display:grid;grid-template-columns:1fr}.tsp-news-grid--sidebar-lead-compact .tsp-news-card:not(.is-lead) a{display:grid;grid-template-columns:84px minmax(0,1fr);gap:10px;align-items:start}.tsp-news-grid--sidebar-lead-compact .tsp-news-card:not(.is-lead) h3{font-size:14px;margin:0}.tsp-news-grid--two-leads .tsp-news-grid__items{display:grid;grid-template-columns:1fr 1fr}.tsp-news-grid--compact .tsp-news-card__media{display:none}.tsp-news-grid--compact .tsp-news-card{border-bottom:1px solid #ddd;border-radius:0}
.tsp-news-ticker{display:flex;align-items:stretch;overflow:hidden;background:var(--tsp-section-bg,#111);color:var(--tsp-text-color,#fff);border-radius:var(--tsp-radius,0)}.tsp-news-ticker__label{background:var(--tsp-accent,#ed1c24);color:#fff;font-weight:800;padding:11px 16px;white-space:nowrap;flex:0 0 19%;display:flex;align-items:center;justify-content:center;text-align:center}.tsp-news-ticker__viewport{overflow:hidden;flex:1}.tsp-news-ticker__track{display:flex;align-items:center;gap:var(--tsp-gap,24px);height:100%;padding:0 20px;white-space:nowrap}.tsp-news-ticker--scroll .tsp-news-ticker__track{width:max-content;animation:tspTicker var(--tsp-speed,35s) linear infinite}.tsp-news-ticker__track a:after{content:'•';margin-left:var(--tsp-gap,24px);opacity:.5}.tsp-news-ticker--stacked{display:block}.tsp-news-ticker--stacked .tsp-news-ticker__track{display:grid;white-space:normal;padding:14px}.tsp-news-ticker--static .tsp-news-ticker__track{overflow:auto}@keyframes tspTicker{from{transform:translateX(5%)}to{transform:translateX(-100%)}}
.tsp-social-icons{display:flex;flex-wrap:wrap;gap:var(--tsp-gap,10px);align-items:center}.tsp-social-icons a{display:inline-flex;align-items:center;justify-content:center;gap:8px;color:var(--tsp-text-color,#111)}.tsp-social-icons svg{width:var(--tsp-icon-size,36px);height:var(--tsp-icon-size,36px);padding:8px;fill:currentColor;border-radius:var(--tsp-radius,50%);background:var(--tsp-section-bg,#f2f2f2)}.tsp-social-icons--pills a{padding:7px 12px;border:1px solid currentColor;border-radius:999px}.tsp-social-icons--pills svg{background:transparent;padding:3px}.tsp-social-icons--vertical{display:grid}.tsp-social-icons--vertical a{justify-content:flex-start}.tsp-social-icons--share-bar{gap:4px}.tsp-social-icons--share-bar svg{border-radius:3px}.tsp-social-icons--counter a{display:flex;flex-direction:column;align-items:center;gap:2px;padding:12px 16px;background:var(--tsp-section-bg,#f6f7f7);border-radius:var(--tsp-radius,8px);text-decoration:none}.tsp-social-icons--counter svg{width:22px;height:22px}.tsp-social-icons__count{font-size:16px;font-weight:800;color:var(--tsp-title-color,inherit)}.tsp-social-icons__count-label{font-size:11px;color:var(--tsp-text-color,#646970);text-transform:uppercase}.tsp-eb-editor-preview{border:1px solid #dcdcde;padding:12px}.tsp-eb-editor-preview__label{font-size:11px;font-weight:700;text-transform:uppercase;color:#646970;margin-bottom:8px}
.tsp-photo-gallery__items{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--tsp-gap,12px)}.tsp-photo-card{display:block}.tsp-photo-card__media{position:relative;aspect-ratio:3/4;border-radius:var(--tsp-radius,12px);overflow:hidden;background:linear-gradient(135deg,#e9e6dd,#d8d4c8);margin-bottom:8px}.tsp-photo-card__media img,.tsp-photo-card__media .tsp-eb-placeholder{width:100%;height:100%;object-fit:cover;display:block}.tsp-photo-card__category{margin-bottom:6px;text-transform:none;background:var(--tsp-accent,#ed1c24)}.tsp-photo-card__title{margin:0;line-height:1.35;color:var(--tsp-title-color,inherit)}.tsp-photo-gallery--masonry .tsp-photo-gallery__items{align-items:start}.tsp-photo-gallery--masonry .tsp-photo-card:nth-child(4n+2){margin-top:28px}.tsp-photo-gallery--masonry .tsp-photo-card:nth-child(4n+4){margin-top:18px}.tsp-photo-gallery--masonry .tsp-photo-card:nth-child(4n+1) .tsp-photo-card__media{aspect-ratio:3/4}.tsp-photo-gallery--masonry .tsp-photo-card:nth-child(4n+2) .tsp-photo-card__media{aspect-ratio:1/1}.tsp-photo-gallery--masonry .tsp-photo-card:nth-child(4n+3) .tsp-photo-card__media{aspect-ratio:4/5}.tsp-photo-gallery--story-strip .tsp-photo-gallery__items{grid-template-columns:none;grid-auto-flow:column;grid-auto-columns:88px;overflow-x:auto;padding-bottom:4px}.tsp-photo-gallery--story-strip .tsp-photo-card__media{aspect-ratio:1/1;border-radius:50%;border:2px solid var(--tsp-accent,#ed1c24)}.tsp-photo-gallery--story-strip .tsp-photo-card__category{display:none}.tsp-photo-gallery--story-strip .tsp-photo-card__title{text-align:center}.tsp-video-grid__items{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--tsp-gap,12px)}.tsp-video-card__link{display:block}.tsp-video-card__media{position:relative;aspect-ratio:16/9;border-radius:var(--tsp-radius,12px);overflow:hidden;background:#222;margin-bottom:8px}.tsp-video-card__media img,.tsp-video-card__media .tsp-eb-placeholder{width:100%;height:100%;object-fit:cover;display:block}.tsp-video-card__play{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:48px;height:48px;border-radius:50%;background:rgba(255,255,255,.88)}.tsp-video-card__play::after{content:'';position:absolute;top:50%;left:56%;transform:translate(-50%,-50%);border-style:solid;border-width:8px 0 8px 13px;border-color:transparent transparent transparent #111}.tsp-video-card__duration{position:absolute;bottom:8px;right:8px;background:rgba(0,0,0,.65);color:#fff;font-size:11px;padding:2px 6px;border-radius:4px}.tsp-video-card h3{margin:6px 0 0;line-height:1.3;color:var(--tsp-title-color,inherit)}.tsp-video-grid--featured-row .tsp-video-grid__items{grid-template-columns:repeat(3,minmax(0,1fr))}.tsp-video-grid--featured-row .tsp-video-card.is-featured{grid-column:1/-1}.tsp-video-grid--featured-row .tsp-video-card.is-featured .tsp-video-card__media{aspect-ratio:21/9}.tsp-video-grid--featured-row .tsp-video-card.is-featured .tsp-video-card__play{width:64px;height:64px}.tsp-video-grid--featured-row .tsp-video-card.is-featured h3{font-size:20px}.tsp-video-grid--compact-list .tsp-video-grid__items{display:flex;flex-direction:column;gap:0}.tsp-video-grid--compact-list .tsp-video-card{border-bottom:1px solid #e5e7eb;padding:10px 0}.tsp-video-grid--compact-list .tsp-video-card__link{display:flex;gap:12px;align-items:center}.tsp-video-grid--compact-list .tsp-video-card__media{flex:0 0 120px;aspect-ratio:16/9;margin-bottom:0}.tsp-video-grid--compact-list .tsp-video-card__play{width:32px;height:32px}.tsp-video-grid--compact-list .tsp-video-card__play::after{border-width:6px 0 6px 9px;left:57%}.tsp-video-grid--compact-list .tsp-video-card h3{margin:0;}.tsp-video-embed{position:relative;margin:0 0 20px}.tsp-video-embed--oembed iframe{width:100%;aspect-ratio:16/9;border-radius:8px}.tsp-video-embed--file video{width:100%;border-radius:8px}
@container (max-width:760px){.tsp-feature-grid__items{grid-template-columns:1fr 1fr;grid-template-rows:auto}.tsp-feature-card.is-lead{grid-column:1/3;grid-row:auto;min-height:360px}.tsp-news-grid__items,.tsp-news-grid--four-column .tsp-news-grid__items{grid-template-columns:repeat(2,1fr)}}
@container (max-width:520px){.tsp-feature-grid__items,.tsp-feature-grid--balanced .tsp-feature-grid__items,.tsp-feature-grid--feature-list .tsp-feature-grid__items,.tsp-feature-grid--three-column .tsp-feature-grid__items,.tsp-feature-grid--four-column .tsp-feature-grid__items,.tsp-feature-grid--lead-list .tsp-feature-grid__items,.tsp-feature-grid--split-columns .tsp-feature-grid__items{display:block}.tsp-feature-card{min-height:var(--tsp-card-min,220px);margin-bottom:4px}.tsp-feature-card.is-lead{min-height:300px}.tsp-feature-card.is-lead h3{font-size:24px}.tsp-news-grid__items,.tsp-news-grid--four-column .tsp-news-grid__items,.tsp-news-grid--two-column .tsp-news-grid__items{grid-template-columns:1fr}.tsp-news-grid--list .tsp-news-card a{grid-template-columns:120px minmax(0,1fr)}.tsp-news-ticker__label{padding:8px 6px;font-size:12px;white-space:normal;line-height:1.2}.tsp-social-icons--icons-labels span{display:none}}
@media(prefers-reduced-motion:reduce){.tsp-news-ticker--scroll .tsp-news-ticker__track{animation:none;overflow:auto}}
@container (max-width:760px){.tsp-photo-gallery__items{grid-template-columns:repeat(2,1fr)}.tsp-video-grid__items{grid-template-columns:repeat(2,1fr)}}
@container (max-width:520px){.tsp-photo-gallery__items{grid-template-columns:repeat(2,1fr)}.tsp-photo-gallery--story-strip .tsp-photo-gallery__items{grid-auto-columns:76px}.tsp-video-grid__items{grid-template-columns:1fr}.tsp-video-grid--compact-list .tsp-video-card__media{flex:0 0 96px}}

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

.tsp-anim{opacity:0}.tsp-anim.is-inview{opacity:1;transition:opacity .5s ease,transform .5s ease}.tsp-anim--slide{transform:translateY(24px)}.tsp-anim--slide.is-inview{transform:none}.tsp-anim--zoom{transform:scale(.96)}.tsp-anim--zoom.is-inview{transform:none}@media(prefers-reduced-motion:reduce){.tsp-anim{opacity:1;transform:none}}.editor-styles-wrapper .tsp-anim{opacity:1;transform:none}

@container (max-width:520px){.tsp-feature-grid .tsp-feature-card:not(:first-child){min-height:0;background:transparent;border-radius:0;margin-bottom:12px;padding-bottom:12px;border-bottom:1px solid #eceff3}.tsp-feature-grid .tsp-feature-card:not(:first-child) .tsp-feature-card__link{display:flex;gap:10px;align-items:flex-start;height:auto}.tsp-feature-grid .tsp-feature-card:not(:first-child) .tsp-feature-card__media{position:relative;flex:0 0 104px;width:104px;height:74px;border-radius:6px;overflow:hidden}.tsp-feature-grid .tsp-feature-card:not(:first-child) .tsp-feature-card__overlay{display:none}.tsp-feature-grid .tsp-feature-card:not(:first-child) .tsp-feature-card__content{position:static;padding:0;color:var(--tsp-text-color,#172033)}.tsp-feature-grid .tsp-feature-card:not(:first-child) h3{font-size:15px;line-height:1.3;margin:0}.tsp-feature-grid .tsp-feature-card:not(:first-child) p,.tsp-feature-grid .tsp-feature-card:not(:first-child) .tsp-eb-category{display:none}.tsp-feature-grid .tsp-feature-card:first-child{min-height:230px}}

@container (min-width:521px){/* v1.6.0 §5: uniform supporting-story geometry — the 'shifted image' fix.
   Root cause: supports inherited the card's 12px content padding (media flush, text inset)
   plus unclamped headlines producing unequal rows. Decision per review: cover + explicit
   centre crop + fixed 3:2 thumb geometry + 2-line clamp = identical rows, aligned media. */
.tsp-news-grid--lead-left .tsp-news-card:not(.is-lead) .tsp-news-card__content,.tsp-news-grid--lead-right .tsp-news-card:not(.is-lead) .tsp-news-card__content,.tsp-news-grid--two-leads-four .tsp-news-card:not(.is-lead) .tsp-news-card__content,.tsp-news-grid--sidebar-lead-compact .tsp-news-card:not(.is-lead) .tsp-news-card__content{padding:0}.tsp-news-grid--lead-left .tsp-news-card:not(.is-lead) .tsp-news-card__media,.tsp-news-grid--lead-right .tsp-news-card:not(.is-lead) .tsp-news-card__media,.tsp-news-grid--two-leads-four .tsp-news-card:not(.is-lead) .tsp-news-card__media,.tsp-news-grid--sidebar-lead-compact .tsp-news-card:not(.is-lead) .tsp-news-card__media{aspect-ratio:3/2}.tsp-news-grid--lead-left .tsp-news-card:not(.is-lead) .tsp-news-card__media img,.tsp-news-grid--lead-right .tsp-news-card:not(.is-lead) .tsp-news-card__media img,.tsp-news-grid--two-leads-four .tsp-news-card:not(.is-lead) .tsp-news-card__media img,.tsp-news-grid--sidebar-lead-compact .tsp-news-card:not(.is-lead) .tsp-news-card__media img{object-fit:cover;object-position:center center}.tsp-news-grid--lead-left .tsp-news-card:not(.is-lead) h3,.tsp-news-grid--lead-right .tsp-news-card:not(.is-lead) h3,.tsp-news-grid--two-leads-four .tsp-news-card:not(.is-lead) h3,.tsp-news-grid--sidebar-lead-compact .tsp-news-card:not(.is-lead) h3{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.tsp-news-grid--lead-left .tsp-news-card:not(.is-lead) time,.tsp-news-grid--lead-right .tsp-news-card:not(.is-lead) time,.tsp-news-grid--two-leads-four .tsp-news-card:not(.is-lead) time,.tsp-news-grid--sidebar-lead-compact .tsp-news-card:not(.is-lead) time{margin-top:4px;display:block}.tsp-news-grid--media-list .tsp-news-card__content{padding:0}.tsp-news-grid--media-list .tsp-news-card__media img{object-fit:cover;object-position:center center}.tsp-news-card.is-lead .tsp-news-card__media img{object-position:center center}}
/* v1.6.0 §6: responsive content-heading hierarchy (sidebar scale untouched) */.tsp-eb-heading h2{line-height:1.2}.tsp-eb-heading h3{line-height:1.2}@container (max-width:760px){.tsp-eb-heading h2{}.tsp-eb-heading h3{}}@container (max-width:520px){.tsp-eb-heading{margin:0 0 12px}.tsp-eb-heading h2{}.tsp-eb-heading h3{}.tsp-eb-heading--accent-line{border-left-width:4px;padding-left:8px}}@container (max-width:520px){.tsp-news-card__content{padding:10px}.tsp-news-card h3{}.tsp-eb{margin-bottom:8px}}



/* v1.8.0 MOBILE DESIGN SYSTEM — single source of truth.
   Ownership (v1.10.11): Section Navigation positions its own track and page
   boxes and nothing else; the layout owns the items grid and the mobile layout
   class styles the card interior. The former :not(.tsp-nav-enabled) gate was
   removed because navigation no longer competes for the items container, so the
   mobile presentation must stay active when navigation is enabled. */
@container (max-width:520px){.tsp-news-grid[class*='tsp-news-grid--m-'] .tsp-news-grid__items{display:grid;grid-template-columns:1fr;grid-template-rows:none;gap:22px}.tsp-news-grid[class*='tsp-news-grid--m-'] .tsp-news-card{grid-column:auto;grid-row:auto}.tsp-news-grid--m-large-card .tsp-news-card a,.tsp-news-grid--m-feature-card .tsp-news-card a,.tsp-news-grid--m-minimal-list .tsp-news-card a{display:block}.tsp-news-grid--m-large-card .tsp-news-card__media,.tsp-news-grid--m-feature-card .tsp-news-card__media{width:100%;aspect-ratio:16/9;margin:0}.tsp-news-grid--m-large-card .tsp-news-card__media img,.tsp-news-grid--m-feature-card .tsp-news-card__media img,.tsp-news-grid--m-compact-row .tsp-news-card__media img{object-fit:cover;object-position:center center}.tsp-news-grid--m-large-card .tsp-news-card__content,.tsp-news-grid--m-feature-card .tsp-news-card__content{padding:12px 2px 0}.tsp-news-grid--m-large-card .tsp-news-card h3{display:block;-webkit-line-clamp:unset;line-height:1.3;margin:6px 0}.tsp-news-grid--m-feature-card .tsp-news-card h3{display:block;-webkit-line-clamp:unset;line-height:1.25;margin:6px 0}.tsp-news-grid--m-feature-card .tsp-news-card__content{padding:14px 2px 0}.tsp-news-grid--m-large-card .tsp-news-card p,.tsp-news-grid--m-feature-card .tsp-news-card p{display:block;margin:8px 0 0;font-size:14px;line-height:1.5}.tsp-news-grid--m-large-card .tsp-news-card time,.tsp-news-grid--m-feature-card .tsp-news-card time{display:block;margin-top:2px}.tsp-news-grid--m-compact-row .tsp-news-card a{display:grid;grid-template-columns:96px minmax(0,1fr);gap:10px;align-items:start}.tsp-news-grid--m-compact-row .tsp-news-card__media{aspect-ratio:3/2;margin:0}.tsp-news-grid--m-compact-row .tsp-news-card__content{padding:0;min-width:0}.tsp-news-grid--m-compact-row .tsp-news-card h3{line-height:1.3;margin:2px 0 0;overflow-wrap:break-word}.tsp-news-grid--m-compact-row .tsp-news-card p{display:none}.tsp-news-grid--m-compact-row .tsp-news-card time{display:block;margin-top:3px}.tsp-news-grid--m-compact-row .tsp-news-card:not(:last-child){padding-bottom:12px;border-bottom:1px solid #eceff3}.tsp-news-grid--m-minimal-list .tsp-news-card__media{display:none}.tsp-news-grid--m-minimal-list .tsp-news-card__content{padding:10px 0}.tsp-news-grid--m-minimal-list .tsp-news-card h3{line-height:1.35;margin:2px 0}.tsp-news-grid--m-minimal-list .tsp-news-card p{display:none}.tsp-news-grid--m-minimal-list .tsp-news-card:not(:last-child){border-bottom:1px solid #eceff3}@container (max-width:360px){.tsp-news-grid--m-feature-card .tsp-news-card h3{}}}

/* v1.9.0 shared text protection */.tsp-eb-category{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;display:inline-block;vertical-align:bottom}.tsp-news-card time{white-space:nowrap}

/* ==========================================================================
   v1.10.9 — News Grid responsive + editor/frontend parity.
   Container tiers only (.tsp-eb-wrap carries container-type:inline-size);
   no viewport media queries are added. Every rule below is appended, so it
   wins on source order at equal specificity - no !important is used.
   ========================================================================== */

/* 1. THEME SAFETY (Blocksy). The editor iframe and the frontend load the SAME
   stylesheet and the SAME render_callback markup, so the only frontend-only
   variable is the theme. .tsp-news-card is an <article> and the media child is
   a bare <img>; themes routinely give both a margin, which shows up on the
   frontend and never in the editor - the reported "editor correct, frontend
   spacing wrong" symptom on four-column. Neutralised at the same specificity
   as the base rules rather than with !important. */
.tsp-news-grid .tsp-news-card{margin:0}
.tsp-news-card__media img{display:block;margin:0}

/* 2. LONG-HEADLINE PROTECTION. Every inner card grid used a bare `1fr` track.
   `1fr` is `minmax(auto,1fr)`, and the auto minimum is the item's min-content
   width, so an unbreakable Telugu or English headline pushed the track wider
   than the card and .tsp-news-card{overflow:hidden} silently CLIPPED it. The
   fixed+`1fr` pairs were corrected IN PLACE above (the project's own
   --m-compact-row tier already used minmax(0,1fr)); these two declarations are
   the remaining pieces of that pattern. */
.tsp-news-card__content{min-width:0}
.tsp-news-card h3{overflow-wrap:break-word}

/* 3. v1.10.10: the v1.10.9 `@container (max-width:1024px)` three-column step for
   four-column was REMOVED. The Gutenberg canvas is narrower than Blocksy's
   frontend content area, so a tier in that band rendered 3 columns in the
   editor and 4 on the site for the same saved attributes - the exact
   editor/frontend mismatch this module must avoid. Column counts now change
   only at 760px and 520px, which sit below both contexts' widths, so the
   editor and the frontend agree. */

/* 4. TABLET BAND 521-760px. The existing 760px tier targets
   `.tsp-news-grid__items` (specificity 0,1,0), which LOSES to
   `.tsp-news-grid--lead-left .tsp-news-grid__items` (0,2,0) - so the lead
   layouts never reduced. At a 600px container lead-left's secondary column was
   (600-20)/3 = ~193px, leaving ~73px of text after the 110px thumbnail. These
   rules match that specificity and collapse the lead layouts to a single
   column of full-width compact rows in reading order. */
@container (max-width:760px){
.tsp-news-grid__items,.tsp-news-grid--four-column .tsp-news-grid__items{grid-template-columns:repeat(2,minmax(0,1fr))}
.tsp-news-grid--lead-left .tsp-news-grid__items,.tsp-news-grid--lead-right .tsp-news-grid__items{grid-template-columns:minmax(0,1fr)}
.tsp-news-grid--lead-left .tsp-news-card.is-lead,.tsp-news-grid--lead-right .tsp-news-card.is-lead{grid-column:auto;grid-row:auto}
.tsp-news-grid--lead-right .tsp-news-card:not(.is-lead){grid-column:auto}
.tsp-news-grid--two-leads-four .tsp-news-grid__items,.tsp-news-grid--two-leads .tsp-news-grid__items{grid-template-columns:repeat(2,minmax(0,1fr))}
.tsp-news-grid--list .tsp-news-card a,.tsp-news-grid--media-list .tsp-news-card a{grid-template-columns:160px minmax(0,1fr)}
}

/* 5. The 520px tier's bare `1fr` tracks get the same overflow protection. The
   --m- selector is repeated at its own specificity because the v1.9.0 mobile
   block would otherwise win with a bare 1fr; both carry the same weight, so
   source order decides. v1.10.11 dropped the `:not(.tsp-nav-enabled)` gate from
   every --m- rule: navigation no longer touches the items container, so the
   mobile layout must stay active when navigation is enabled. */
@container (max-width:520px){
.tsp-news-grid__items,.tsp-news-grid--four-column .tsp-news-grid__items,.tsp-news-grid--two-column .tsp-news-grid__items{grid-template-columns:minmax(0,1fr)}
.tsp-news-grid[class*='tsp-news-grid--m-'] .tsp-news-grid__items{grid-template-columns:minmax(0,1fr)}
.tsp-news-grid--list .tsp-news-card a,.tsp-news-grid--media-list .tsp-news-card a{grid-template-columns:120px minmax(0,1fr)}
}

/* 6. v1.10.10 MOBILE CARD PRESENTATION. Mobile is a stacked list: a larger
   picture, padding on all four sides of the text, and a divider between posts.
   The image goes 16/9 -> 4/3 (taller at the same full-bleed width, so it reads
   as BIGGER) while the text gains real side padding - previously the content
   padding was `12px 2px 0`, which left the headline almost touching the card
   edge and no space beneath it at all. Applies to the two card-style mobile
   modes (large-card is the auto mapping for three/four/two-column, list,
   media-list and two-leads-four; feature-card for lead-left/lead-right/
   two-leads), so every layout that falls back to a mobile card gets the same
   treatment. compact-row and minimal-list already have their own dividers and
   are deliberately left alone. Same specificity as the v1.9.0 rules and later
   in the file, so no !important is needed. */
@container (max-width:520px){
.tsp-news-grid--m-large-card .tsp-news-card__media,.tsp-news-grid--m-feature-card .tsp-news-card__media{aspect-ratio:4/3}
.tsp-news-grid--m-large-card .tsp-news-card__content,.tsp-news-grid--m-feature-card .tsp-news-card__content{padding:14px}
.tsp-news-grid--m-large-card .tsp-news-card:not(:last-child),.tsp-news-grid--m-feature-card .tsp-news-card:not(:last-child){border-bottom:1px solid #e5e7eb}
}

/* ==========================================================================
   v1.10.14 — two additive News Grid presets. Nothing above is modified.

   `editorial-mosaic` (Editorial Mosaic 1+4): a full-width lead banner, two
   medium cards side by side, then compact image-left rows. Chosen over a
   lead-beside-supports mosaic precisely because visual order stays identical
   to DOM order 1,2,3,4,5 - no grid-area reordering, so keyboard and screen
   reader order are the content order - AND the 1 + 2 + n shape has no empty
   cell at any story count: three stories render lead + two medium, six render
   one more compact row. Roles come from the is-lead/is-medium/is-compact
   classes emitted by render_news_grid(), not from :nth-child(), so navigation
   paging (which restarts the hierarchy per page) stays correct.

   `editorial-strip` (Four-card Editorial Strip): four equal cards on one row,
   2x2 on tablet, one column on phones. Cards are top-aligned so a long Telugu
   headline grows its own card instead of stretching all four.
   ========================================================================== */
.tsp-news-grid--editorial-mosaic .tsp-news-grid__items{grid-template-columns:repeat(2,minmax(0,1fr));align-items:start}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-lead{grid-column:1/-1}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-lead .tsp-news-card__media{aspect-ratio:21/9}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-lead h3{line-height:1.2}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-medium .tsp-news-card__media{aspect-ratio:16/9}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-medium h3{font-size:17px;line-height:1.3}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-compact{grid-column:1/-1}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-compact a{display:grid;grid-template-columns:180px minmax(0,1fr);gap:14px;align-items:start}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-compact .tsp-news-card__media{aspect-ratio:3/2}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-compact .tsp-news-card__content{padding:0}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-compact h3{font-size:16px;line-height:1.35;margin:0}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-compact time{display:block;margin-top:4px}
.tsp-news-grid--editorial-strip .tsp-news-grid__items{grid-template-columns:repeat(4,minmax(0,1fr));align-items:start}
.tsp-news-grid--editorial-strip .tsp-news-card__media{aspect-ratio:16/9}
.tsp-news-grid--editorial-strip .tsp-news-card h3{line-height:1.3}

@container (max-width:760px){
.tsp-news-grid--editorial-mosaic .tsp-news-grid__items{grid-template-columns:repeat(2,minmax(0,1fr))}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-lead .tsp-news-card__media{aspect-ratio:16/9}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-compact a{grid-template-columns:140px minmax(0,1fr)}
.tsp-news-grid--editorial-strip .tsp-news-grid__items{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* Phones: one column, and the desktop compact-row rules above (0,3,x) must be
   handed back to the shared mobile design system (0,2,x), which would
   otherwise lose the cascade and leave a 180px thumbnail on a 320px screen. */
@container (max-width:520px){
.tsp-news-grid--editorial-mosaic .tsp-news-grid__items,.tsp-news-grid--editorial-strip .tsp-news-grid__items{grid-template-columns:minmax(0,1fr)}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-lead,.tsp-news-grid--editorial-mosaic .tsp-news-card.is-compact{grid-column:auto}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-compact a{display:block}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-lead .tsp-news-card__media,.tsp-news-grid--editorial-mosaic .tsp-news-card.is-medium .tsp-news-card__media,.tsp-news-grid--editorial-mosaic .tsp-news-card.is-compact .tsp-news-card__media{aspect-ratio:4/3}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-compact .tsp-news-card__content{padding:14px}
.tsp-news-grid--editorial-mosaic .tsp-news-card.is-lead h3,.tsp-news-grid--editorial-mosaic .tsp-news-card.is-medium h3,.tsp-news-grid--editorial-mosaic .tsp-news-card.is-compact h3{font-size:21px;line-height:1.25;margin:6px 0}
.tsp-news-grid--editorial-strip .tsp-news-card__media{aspect-ratio:4/3}
.tsp-news-grid--editorial-strip .tsp-news-card h3{line-height:1.3;margin:6px 0}
}

/* ==========================================================================
   v1.10.14 — Photo preset "Gallery Mosaic" (`gallery-mosaic`).

   Reuses the existing Photo query and renderer unchanged: a photo story is
   still just a post with a featured image, so nothing here assumes attachments
   or gallery metadata. There is deliberately NO photo-count badge - the data
   model holds no count, and inventing one would be fabricated content.

   Four columns with a 2x2 dominant tile means five stories fill the grid
   exactly. Titles move onto the tile over a controlled scrim, which is why
   .tsp-photo-card becomes the positioning context here (it is an <a>, so no
   nested link is created and the accessible name is unchanged).
   ========================================================================== */
/* v1.10.612 — `minmax(0, …)` on the columns, matching the .has-2/.has-3/.has-4
   variants of this same component twelve lines below.

   A bare `1fr` is `minmax(auto, 1fr)`: the track can never go below its
   content's min-content width, so one unbreakable token — a long URL in a
   caption, a wide image with no max-width — pushes the track out and the grid
   overflows its container. The three smaller variants were written safely; the
   default 5-up mosaic was the only one left on bare fr units, which is why the
   layout-preset suite has been flagging it. Rows are left alone: vertical
   overflow grows the block instead of breaking the page. */
.tsp-photo-gallery--gallery-mosaic .tsp-photo-gallery__items{grid-template-columns:minmax(0,2fr) minmax(0,1fr) minmax(0,1fr);grid-template-rows:1fr 1fr}
.tsp-photo-gallery--gallery-mosaic .tsp-photo-card{position:relative;height:100%;overflow:hidden;border-radius:var(--tsp-radius,12px);background:#222}
.tsp-photo-gallery--gallery-mosaic .tsp-photo-card.is-lead{grid-row:span 2}
/* v1.10.52: the prototype sizes rows with `1fr 1fr` and lets the tile's own
   min-height establish the track rather than pinning a row height, so the
   mosaic stays proportional to whatever column it is dropped into — in the
   prototype that is a ~695px column, on our pages it can be far wider. */
.tsp-photo-gallery--gallery-mosaic .tsp-photo-card__media{min-height:120px}

/* Graceful degrade (v1.10.45). Five tiles fill the 4-column grid exactly; four
   or fewer used to leave holes. Each count below picks a shape that fills with
   no gaps, so a thin section looks deliberate instead of broken. The section is
   never padded to reach a count — these are the stories that actually exist.

   Scoped to min-width:761px on purpose. These selectors carry three classes and
   would otherwise out-specify the two-class rules in the narrow @container
   blocks below regardless of source order — has-3 would hold three columns down
   to a 320px phone. Below 761px the existing responsive shape already fills
   correctly, so the degrade only has to run at the wide size. */
/* v1.10.52: reworked from the old 4-column/2x2-lead shape to the prototype's
   3-column `2fr 1fr 1fr` x 2, per the owner's design decision.

   Five tiles fill that shape exactly: the lead takes the 2fr column across both
   rows, and four small tiles fill the 1fr columns. Every count below picks a
   shape that tiles with no holes, and each one that is not five must ALSO undo
   the lead's `grid-row:span 2` — otherwise the lead keeps reserving a second
   row that nothing fills, which is the hole in a different place.

   Still scoped to min-width:761px: these carry three classes and would
   otherwise out-specify the two-class narrow rules below regardless of source
   order. Below 761px the existing responsive shape already fills correctly. */
@container (min-width:761px){
.tsp-photo-gallery--gallery-mosaic.has-4 .tsp-photo-gallery__items{grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:1fr 1fr}
.tsp-photo-gallery--gallery-mosaic.has-4 .tsp-photo-card.is-lead{grid-row:span 1}
.tsp-photo-gallery--gallery-mosaic.has-3 .tsp-photo-gallery__items{grid-template-columns:repeat(3,minmax(0,1fr));grid-template-rows:1fr}
.tsp-photo-gallery--gallery-mosaic.has-3 .tsp-photo-card.is-lead{grid-row:span 1}
.tsp-photo-gallery--gallery-mosaic.has-2 .tsp-photo-gallery__items{grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:1fr}
.tsp-photo-gallery--gallery-mosaic.has-2 .tsp-photo-card.is-lead{grid-row:span 1}
.tsp-photo-gallery--gallery-mosaic.has-1 .tsp-photo-gallery__items{grid-template-columns:minmax(0,1fr);grid-template-rows:1fr}
.tsp-photo-gallery--gallery-mosaic.has-1 .tsp-photo-card.is-lead{grid-row:span 1}
/* One and two tiles get a taller track — at full width a single 120px-min row
   reads as a letterbox strip rather than a photo. */
.tsp-photo-gallery--gallery-mosaic.has-2 .tsp-photo-card__media{min-height:220px}
.tsp-photo-gallery--gallery-mosaic.has-1 .tsp-photo-card__media{min-height:340px}
}

.tsp-photo-gallery--gallery-mosaic .tsp-photo-card__media{aspect-ratio:auto;height:100%;margin:0;border-radius:0}
.tsp-photo-gallery--gallery-mosaic .tsp-photo-card__category{position:absolute;top:10px;left:10px;z-index:2;margin:0}
.tsp-photo-gallery--gallery-mosaic .tsp-photo-card__title{position:absolute;left:0;right:0;bottom:0;z-index:2;margin:0;padding:26px 12px 12px;line-height:1.3;color:#fff;background:linear-gradient(to top,rgba(0,0,0,.78) 0%,rgba(0,0,0,.45) 55%,rgba(0,0,0,0) 100%);overflow-wrap:break-word}
.tsp-photo-gallery--gallery-mosaic .tsp-photo-card.is-lead .tsp-photo-card__title{padding:40px 18px 18px;line-height:1.25}

/* Tablet and phones: the dominant tile stays first and full width, supporting
   tiles keep two columns because a square thumbnail stays legible there. */
@container (max-width:760px){
.tsp-photo-gallery--gallery-mosaic .tsp-photo-gallery__items{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:minmax(0,150px)}
.tsp-photo-gallery--gallery-mosaic .tsp-photo-card.is-lead{grid-column:span 2;grid-row:span 2}
}
@container (max-width:520px){
.tsp-photo-gallery--gallery-mosaic .tsp-photo-gallery__items{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:minmax(0,124px)}
.tsp-photo-gallery--gallery-mosaic .tsp-photo-card.is-lead{grid-column:span 2;grid-row:span 2}
.tsp-photo-gallery--gallery-mosaic .tsp-photo-card__title{padding:22px 10px 10px}
.tsp-photo-gallery--gallery-mosaic .tsp-photo-card.is-lead .tsp-photo-card__title{padding:32px 14px 14px}
}

/* ==========================================================================
   v1.10.14 — Video preset "Video Lead + 4" (`lead-four`).
   One dominant video plus a 2x2 supporting block, using the same four-column
   frame as Gallery Mosaic so five videos fill it exactly. Play badge, duration
   and links are the existing ones - no new video metadata is introduced.
   ========================================================================== */
.tsp-video-grid--lead-four .tsp-video-grid__items{grid-template-columns:repeat(4,minmax(0,1fr))}
.tsp-video-grid--lead-four .tsp-video-card.is-featured{grid-column:span 2;grid-row:span 2;height:100%}
/* The lead spans two auto rows, so its media absorbs whatever height the 2x2
   stack ends up with instead of leaving dead space under a fixed 16/9 box. */
.tsp-video-grid--lead-four .tsp-video-card.is-featured .tsp-video-card__link{display:flex;flex-direction:column;height:100%}
.tsp-video-grid--lead-four .tsp-video-card.is-featured .tsp-video-card__media{flex:1 1 auto;aspect-ratio:auto;min-height:260px}
.tsp-video-grid--lead-four .tsp-video-card.is-featured .tsp-video-card__play{width:64px;height:64px}
.tsp-video-grid--lead-four .tsp-video-card.is-featured h3{font-size:20px;line-height:1.25}

/* Tablet keeps a two-column supporting block; phones collapse to one column,
   because a 16/9 card in two columns is a ~140px tap target at 320px. */
@container (max-width:760px){
.tsp-video-grid--lead-four .tsp-video-grid__items{grid-template-columns:repeat(2,minmax(0,1fr))}
.tsp-video-grid--lead-four .tsp-video-card.is-featured{grid-column:span 2;grid-row:auto}
}
@container (max-width:520px){
.tsp-video-grid--lead-four .tsp-video-grid__items{grid-template-columns:minmax(0,1fr)}
.tsp-video-grid--lead-four .tsp-video-card.is-featured{grid-column:auto;grid-row:auto;height:auto}
.tsp-video-grid--lead-four .tsp-video-card.is-featured .tsp-video-card__media{flex:0 0 auto;aspect-ratio:16/9;min-height:0}
}

/* ==========================================================================
   v1.10.15 — three additive News Grid presets reproducing the homepage
   reference composition. ADDITIVE ONLY: `editorial-mosaic`, `editorial-strip`,
   `three-column` and every other existing layout are untouched above, so saved
   blocks keep their exact appearance.

     lead-mosaic    Political News and Sports - one asymmetric three-column
                    mosaic that produces BOTH compositions from story count
                    alone (5 -> Political, 4 -> Sports). Nothing is
                    category-aware.
     compact-strip  Movie News - four equal bordered cards.
     editorial-row  Reviews - three equal bordered cards.

   Tokens are declared once on the three layout scopes rather than globally, so
   nothing outside these presets inherits them. The kicker and card colours
   prefer the block's existing --tsp-accent / --tsp-title-color controls and
   only fall back to the reference palette, so the colour pickers keep working.
   ========================================================================== */
.tsp-news-grid--lead-mosaic,
.tsp-news-grid--compact-strip,
.tsp-news-grid--editorial-row{--tsp-ink:#16181f;--tsp-muted:#676E7B;--tsp-hairline:#e8e5de}

/* Shared: the reference kicker is red TEXT, not the filled pill the other
   layouts use, and metadata is muted rather than the base 80% opacity. */
.tsp-news-grid--lead-mosaic .tsp-eb-category,
.tsp-news-grid--compact-strip .tsp-eb-category,
.tsp-news-grid--editorial-row .tsp-eb-category{background:transparent;color:var(--tsp-accent,#c8102e);padding:0;font-weight:700;letter-spacing:.03em}
.tsp-news-grid--lead-mosaic time,
.tsp-news-grid--compact-strip time,
.tsp-news-grid--editorial-row time{color:var(--tsp-muted,#676E7B);opacity:1}
.tsp-news-grid--lead-mosaic .tsp-news-card h3,
.tsp-news-grid--compact-strip .tsp-news-card h3,
.tsp-news-grid--editorial-row .tsp-news-card h3{color:var(--tsp-title-color,var(--tsp-ink,#16181f))}

/* Shared card chrome for the two card-row presets. */
.tsp-news-grid--compact-strip .tsp-news-card,
.tsp-news-grid--editorial-row .tsp-news-card{border:1px solid var(--tsp-hairline,#e8e5de);border-radius:9px;overflow:hidden}
.tsp-news-grid--compact-strip .tsp-news-card__media,
.tsp-news-grid--editorial-row .tsp-news-card__media{aspect-ratio:16/10}
.tsp-news-grid--compact-strip .tsp-news-card__media img,
.tsp-news-grid--editorial-row .tsp-news-card__media img{object-fit:cover;object-position:center}
.tsp-news-grid--compact-strip .tsp-news-card__content,
.tsp-news-grid--editorial-row .tsp-news-card__content{padding:11px 12px 12px}
.tsp-news-grid--compact-strip .tsp-eb-category,
.tsp-news-grid--editorial-row .tsp-eb-category{line-height:1.2}
.tsp-news-grid--compact-strip .tsp-news-card h3,
.tsp-news-grid--editorial-row .tsp-news-card h3{margin:5px 0 0;font-weight:700;line-height:1.28;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.tsp-news-grid--compact-strip .tsp-news-card time,
.tsp-news-grid--editorial-row .tsp-news-card time{display:block;margin-top:6px;font-size:10px;line-height:1.35}
.tsp-news-grid--compact-strip .tsp-news-card p,
.tsp-news-grid--editorial-row .tsp-news-card p{margin:6px 0 0;font-size:12px;line-height:1.45;color:var(--tsp-muted,#676E7B)}

/* Columns. */
.tsp-news-grid--compact-strip .tsp-news-grid__items{grid-template-columns:repeat(4,minmax(0,1fr));align-items:start}
.tsp-news-grid--editorial-row .tsp-news-grid__items{grid-template-columns:repeat(3,minmax(0,1fr));align-items:start}

/* lead-mosaic — the approved overlay mosaic. Story 1 spans both rows of
   column 1; the rest AUTO-FLOW into columns 2-3. Rows are 1fr with a 150px
   floor rather than a fixed 150px, so a long headline can grow the tile
   instead of being clipped by it. */
.tsp-news-grid--lead-mosaic .tsp-news-grid__items{grid-template-columns:minmax(0,1.55fr) minmax(0,1fr) minmax(0,1fr);grid-template-rows:repeat(2,minmax(150px,1fr));align-items:stretch;gap:var(--tsp-gap,14px)}
.tsp-news-grid--lead-mosaic .tsp-news-card.is-lead{grid-row:1/3;grid-column:1}

/* Fewer stories than the design assumes must not leave holes in the grid. */
/* 3 tiles: the two supports run full height beside the lead. */
.tsp-news-grid--lead-mosaic .tsp-news-grid__items:has(> .tsp-news-card:nth-child(3)):not(:has(> .tsp-news-card:nth-child(4))) .tsp-news-card:not(.is-lead){grid-row:1/3}
/* 2 tiles: the single support takes the whole right-hand side. */
.tsp-news-grid--lead-mosaic .tsp-news-grid__items:not(:has(> .tsp-news-card:nth-child(3))) .tsp-news-card:not(.is-lead){grid-row:1/3;grid-column:2/-1}
/* 4 tiles: the last support widens to close the bottom row. */
.tsp-news-grid--lead-mosaic .tsp-news-grid__items:has(> .tsp-news-card:nth-child(4)):not(:has(> .tsp-news-card:nth-child(5))) .tsp-news-card:last-child{grid-column:span 2}

/* Heading row with a View All link, used only when Section Navigation is off.
   section-nav.css is NOT enqueued in that case, so the link is styled here. */
.tsp-news-grid__header{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;margin-bottom:16px;padding-bottom:8px;border-bottom:1px solid var(--tsp-hairline,#e8e5de)}
.tsp-news-grid__header .tsp-eb-heading{margin:0;min-width:0}
.tsp-news-grid__header .tsp-nav-viewall{flex:0 0 auto;font-size:12px;font-weight:600;line-height:1.4;color:var(--tsp-accent,#c8102e);text-decoration:none;white-space:nowrap}
.tsp-news-grid__header .tsp-nav-viewall:hover,.tsp-news-grid__header .tsp-nav-viewall:focus-visible{text-decoration:underline}

/* Tablet: the mosaic pairs up with the lead across both columns, the strip
   halves, and the three-card row stacks (three bordered cards below 760px
   leave too little width for a 13px two-line title). */
@container (max-width:760px){
.tsp-news-grid--lead-mosaic .tsp-news-grid__items{grid-template-columns:repeat(2,minmax(0,1fr))}
.tsp-news-grid--lead-mosaic .tsp-news-card.is-lead{grid-column:1/-1}
.tsp-news-grid--compact-strip .tsp-news-grid__items{grid-template-columns:repeat(2,minmax(0,1fr))}
.tsp-news-grid--editorial-row .tsp-news-grid__items{grid-template-columns:minmax(0,1fr)}
}

/* Phones: one column in DOM order, and the reference type scale is handed back
   to the shared mobile design system. These selectors are more specific than
   the --m- tier, so without an explicit hand-back a 13px clamped title and a
   16/10 image would survive onto a 320px screen. */
@container (max-width:520px){
.tsp-news-grid--lead-mosaic .tsp-news-grid__items,
.tsp-news-grid--compact-strip .tsp-news-grid__items,
.tsp-news-grid--editorial-row .tsp-news-grid__items{grid-template-columns:minmax(0,1fr)}
.tsp-news-grid--lead-mosaic .tsp-news-card.is-lead{grid-column:auto}
.tsp-news-grid--lead-mosaic .tsp-news-card__media,
.tsp-news-grid--compact-strip .tsp-news-card__media,
.tsp-news-grid--editorial-row .tsp-news-card__media{aspect-ratio:4/3}
.tsp-news-grid--lead-mosaic .tsp-news-card__content{padding:12px 2px 0}
.tsp-news-grid--compact-strip .tsp-news-card__content,
.tsp-news-grid--editorial-row .tsp-news-card__content{padding:14px}
.tsp-news-grid--lead-mosaic .tsp-news-card h3,
.tsp-news-grid--lead-mosaic .tsp-news-card.is-lead h3{margin:6px 0;line-height:1.25}
.tsp-news-grid--compact-strip .tsp-news-card h3,
.tsp-news-grid--editorial-row .tsp-news-card h3{margin:6px 0;line-height:1.3;display:block;-webkit-line-clamp:unset;overflow:visible}
.tsp-news-grid--lead-mosaic .tsp-eb-category,
.tsp-news-grid--lead-mosaic .tsp-news-card.is-lead .tsp-eb-category,
.tsp-news-grid--compact-strip .tsp-eb-category,
.tsp-news-grid--editorial-row .tsp-eb-category{font-size:11px}
.tsp-news-grid--lead-mosaic .tsp-news-card time,
.tsp-news-grid--lead-mosaic .tsp-news-card.is-lead time,
.tsp-news-grid--compact-strip .tsp-news-card time,
.tsp-news-grid--editorial-row .tsp-news-card time{font-size:12px}
.tsp-news-grid__header{gap:10px}
}

/* v1.10.18 — section intro: breadcrumb, title with the brand accent bar,
   description and refinement filters. Filters are real links, so focus and
   hover states are the browser's own plus these. */
.tsp-section-intro{margin-top:var(--tsp-mt,0);margin-bottom:var(--tsp-mb,24px)}
.tsp-section-intro__crumb{font-size:12px;color:var(--tsp-text-color,var(--tsp-muted,#676E7B));margin-bottom:10px}
/* v1.10.610 — the 24px touch floor, which this crumb never got.
   Measured on /sections/ at 390: the "Home" link was 34x15. The article
   breadcrumb took this correction in v1.10.450 and the category and review
   crumbs in v1.10.452; this is the same control in a fourth template and was
   simply missed. Same fix, verbatim: `inline-flex` + `min-height` rather than
   padding, so the target grows into the line box that is already there and
   nothing below it moves. Type size is untouched. */
.tsp-section-intro__crumb a{color:inherit;text-decoration:none;display:inline-flex;align-items:center;min-height:24px}
.tsp-section-intro__crumb a:hover{color:var(--tsp-accent,#c8102e)}
.tsp-section-intro__crumb span{margin:0 6px}
.tsp-section-intro__crumb span[aria-current]{margin:0;color:var(--tsp-title-color,var(--tsp-ink,#16181f));font-weight:600}
/* Title and the optional "All sections" link share one row. baseline alignment
   keeps the link sitting on the title's baseline as the title scales. */
.tsp-section-intro__head{display:flex;align-items:baseline;justify-content:space-between;gap:16px;flex-wrap:wrap}
.tsp-section-intro__title{margin:0;padding-left:12px;border-left:5px solid var(--tsp-accent,#c8102e);line-height:1.15;font-weight:800;color:var(--tsp-title-color,var(--tsp-ink,#16181f))}
.tsp-section-intro__all{flex:0 0 auto;font-family:var(--ts-ui);font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;text-decoration:none;white-space:nowrap;color:var(--tsp-accent,#c8102e)}
.tsp-section-intro__all:hover{text-decoration:underline}
.tsp-section-intro__all:focus-visible{outline:2px solid var(--tsp-accent,#c8102e);outline-offset:3px}
.tsp-section-intro__desc{margin:12px 0 0;max-width:60ch;font-size:14px;line-height:1.6;color:var(--tsp-text-color,var(--tsp-muted,#676E7B))}
.tsp-section-intro__filters{display:flex;flex-wrap:wrap;gap:8px;list-style:none;margin:16px 0 0;padding:0}
.tsp-section-intro__filter{display:inline-flex;align-items:center;min-height:36px;padding:0 14px;border:1px solid var(--tsp-hairline,#e8e5de);border-radius:999px;font-size:13px;font-weight:600;line-height:1;text-decoration:none;color:var(--tsp-title-color,var(--tsp-ink,#16181f));background:#fff}
.tsp-section-intro__filter:hover{border-color:var(--tsp-accent,#c8102e);color:var(--tsp-accent,#c8102e)}
.tsp-section-intro__filter:focus-visible{outline:2px solid var(--tsp-accent,#c8102e);outline-offset:2px}
.tsp-section-intro__filter.is-active{background:var(--tsp-accent,#c8102e);border-color:var(--tsp-accent,#c8102e);color:#fff}
@container (max-width:520px){
/* Narrow: the link drops under the title rather than squeezing it. */
.tsp-section-intro__head{gap:8px}
.tsp-section-intro__all{margin-left:12px}
/* Scrolls rather than wrapping into a tall stack, with the row still reachable
   by keyboard because these are links in source order. */
.tsp-section-intro__filters{flex-wrap:nowrap;overflow-x:auto;padding-bottom:4px;scrollbar-width:thin}
.tsp-section-intro__filter{flex:0 0 auto;min-height:40px}
}

/* v1.10.18 — server-side numbered pagination. paginate_links() emits <a> for
   other pages and <span class="current"> for the active one, so the current
   page is styled without needing extra markup. */
.tsp-eb-pagination{margin-top:26px}
.tsp-eb-pagination ul{display:flex;flex-wrap:wrap;gap:8px;list-style:none;margin:0;padding:0;justify-content:center}
.tsp-eb-pagination a,.tsp-eb-pagination span{display:inline-flex;align-items:center;justify-content:center;min-width:40px;min-height:40px;padding:0 12px;border:1px solid var(--tsp-hairline,#e8e5de);border-radius:7px;font-size:14px;font-weight:600;line-height:1;text-decoration:none;color:var(--tsp-title-color,var(--tsp-ink,#16181f))}
.tsp-eb-pagination a:hover{border-color:var(--tsp-accent,#c8102e);color:var(--tsp-accent,#c8102e)}
.tsp-eb-pagination a:focus-visible{outline:2px solid var(--tsp-accent,#c8102e);outline-offset:2px}
.tsp-eb-pagination .current{background:var(--tsp-accent,#c8102e);border-color:var(--tsp-accent,#c8102e);color:#fff}
.tsp-eb-pagination .dots{border-color:transparent}
@container (max-width:520px){
.tsp-eb-pagination ul{gap:6px}
.tsp-eb-pagination a,.tsp-eb-pagination span{min-width:44px;min-height:44px;padding:0 10px;font-size:13px}
}

/* ==========================================================================
   v1.10.18 — `lead-two` (Political Lead + 2). Category-agnostic: the pattern
   supplies the Politics query, the preset only supplies the composition.

   One dominant overlay lead beside two stacked image-top cards. The lead is
   the only News Grid card that overlays its text, so the media is promoted to
   a fill layer and the scrim is a pseudo-element on the anchor - News Grid
   markup has no overlay div and this preset must not change shared markup.
   ========================================================================== */
.tsp-news-grid--lead-two .tsp-news-grid__items{grid-template-columns:minmax(0,1.75fr) minmax(0,1fr);grid-template-rows:repeat(2,minmax(0,1fr));align-items:stretch}
.tsp-news-grid--lead-two .tsp-news-card.is-lead{grid-column:1;grid-row:1/3;position:relative;overflow:hidden;border-radius:var(--tsp-radius,10px);min-height:340px}
.tsp-news-grid--lead-two .tsp-news-card.is-lead a{display:block;position:relative;height:100%}
.tsp-news-grid--lead-two .tsp-news-card.is-lead .tsp-news-card__media{position:absolute;inset:0;height:100%;aspect-ratio:auto;margin:0;border-radius:0}
.tsp-news-grid--lead-two .tsp-news-card.is-lead .tsp-news-card__media img{width:100%;height:100%;object-fit:cover;object-position:center}
.tsp-news-grid--lead-two .tsp-news-card.is-lead a::after{content:'';position:absolute;inset:0;z-index:1;background:linear-gradient(to top,rgba(0,0,0,.82) 0%,rgba(0,0,0,.35) 45%,rgba(0,0,0,0) 72%)}
.tsp-news-grid--lead-two .tsp-news-card.is-lead .tsp-news-card__content{position:absolute;left:0;right:0;bottom:0;z-index:2;padding:20px;min-width:0}
.tsp-news-grid--lead-two .tsp-news-card.is-lead .tsp-eb-category{background:var(--tsp-accent,#c8102e);color:#fff;padding:4px 9px;letter-spacing:.03em}
.tsp-news-grid--lead-two .tsp-news-card.is-lead h3{margin:10px 0 0;line-height:1.2;color:#fff;overflow-wrap:break-word}
.tsp-news-grid--lead-two .tsp-news-card.is-lead time{display:block;margin-top:9px;font-size:12px;color:rgba(255,255,255,.86)}
.tsp-news-grid--lead-two .tsp-news-card:not(.is-lead){border:1px solid var(--tsp-hairline,#e8e5de);border-radius:9px;overflow:hidden;background-color:var(--tsp-section-bg,#fff)}
.tsp-news-grid--lead-two .tsp-news-card:not(.is-lead) .tsp-news-card__media{aspect-ratio:16/10;margin:0}
.tsp-news-grid--lead-two .tsp-news-card:not(.is-lead) .tsp-news-card__media img{width:100%;height:100%;object-fit:cover;object-position:center}
.tsp-news-grid--lead-two .tsp-news-card:not(.is-lead) .tsp-news-card__content{padding:11px 12px 13px}
.tsp-news-grid--lead-two .tsp-news-card:not(.is-lead) .tsp-eb-category{background:transparent;color:var(--tsp-accent,#c8102e);padding:0;letter-spacing:.03em}
.tsp-news-grid--lead-two .tsp-news-card:not(.is-lead) h3{margin:5px 0 0;font-size:15px;line-height:1.3;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.tsp-news-grid--lead-two .tsp-news-card:not(.is-lead) time{display:block;margin-top:7px;font-size:11px;color:var(--tsp-muted,#676E7B)}

@container (max-width:760px){
.tsp-news-grid--lead-two .tsp-news-grid__items{grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:none}
.tsp-news-grid--lead-two .tsp-news-card.is-lead{grid-column:1/-1;grid-row:auto;min-height:300px}
}

/* ==========================================================================
   v1.10.17 — two additive mobile families for the shared mobile design system.
   The saved desktop `layout` attribute is never touched; AUTO_MOBILE_MAP only
   decides which .tsp-news-grid--m-* class rides alongside it, and the editor's
   "Mobile layout" control still overrides per block.

     --m-lead-stream   full-width lead card, then compact rows (any lead layout)
     --m-card-row      one horizontal card per row (any equal-card layout)

   These sit LAST in the file on purpose. The per-preset <=520px hand-back
   blocks written in v1.10.14/15 carry the same specificity (0,3,x), so source
   order is what lets a mobile family win over a desktop preset's own mobile
   rules. Nothing here uses !important and nothing reorders the DOM: both
   families keep media-then-content source order, so reading order, focus order
   and visual order stay identical.
   ========================================================================== */
@container (max-width:520px){

/* ---- shared: one column, no desktop placement survives ---- */
.tsp-news-grid--m-lead-stream .tsp-news-grid__items,
.tsp-news-grid--m-card-row .tsp-news-grid__items{display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:none;gap:12px}
.tsp-news-grid--m-lead-stream .tsp-news-card,
.tsp-news-grid--m-card-row .tsp-news-card{grid-column:auto;grid-row:auto;margin:0}
.tsp-news-grid--m-lead-stream .tsp-news-card__media img,
.tsp-news-grid--m-card-row .tsp-news-card__media img{width:100%;height:100%;object-fit:cover;object-position:center}
.tsp-news-grid--m-lead-stream .tsp-news-card__content,
.tsp-news-grid--m-card-row .tsp-news-card__content{min-width:0}
.tsp-news-grid--m-lead-stream .tsp-news-card h3,
.tsp-news-grid--m-card-row .tsp-news-card h3{overflow-wrap:break-word}

/* ---- lead-stream: the lead keeps a full-width card ---- */
.tsp-news-grid--m-lead-stream .tsp-news-card.is-lead a{display:block}
.tsp-news-grid--m-lead-stream .tsp-news-card.is-lead .tsp-news-card__media{aspect-ratio:16/10;margin:0;border-radius:var(--tsp-radius,8px);overflow:hidden}
.tsp-news-grid--m-lead-stream .tsp-news-card.is-lead .tsp-news-card__content{padding:12px 0 0}
.tsp-news-grid--m-lead-stream .tsp-news-card.is-lead h3{margin:7px 0 0;line-height:1.24;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.tsp-news-grid--m-lead-stream .tsp-news-card.is-lead p{margin:8px 0 0;font-size:14px;line-height:1.55}
.tsp-news-grid--m-lead-stream .tsp-news-card.is-lead time{display:block;margin-top:7px;font-size:12px}

/* ---- lead-stream: everything after it becomes a compact row ---- */
.tsp-news-grid--m-lead-stream .tsp-news-card:not(.is-lead){padding-bottom:12px;border-bottom:1px solid #eceff3;border-radius:0;background-color:transparent}
.tsp-news-grid--m-lead-stream .tsp-news-card:not(.is-lead):last-child{border-bottom:0;padding-bottom:0}
.tsp-news-grid--m-lead-stream .tsp-news-card:not(.is-lead) a{display:grid;grid-template-columns:104px minmax(0,1fr);gap:12px;align-items:start}
.tsp-news-grid--m-lead-stream .tsp-news-card:not(.is-lead) .tsp-news-card__media{aspect-ratio:4/3;margin:0;border-radius:6px;overflow:hidden}
.tsp-news-grid--m-lead-stream .tsp-news-card:not(.is-lead) .tsp-news-card__content{padding:0}
.tsp-news-grid--m-lead-stream .tsp-news-card:not(.is-lead) h3{margin:4px 0 0;font-size:16px;line-height:1.3;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.tsp-news-grid--m-lead-stream .tsp-news-card:not(.is-lead) p{display:none}
.tsp-news-grid--m-lead-stream .tsp-news-card:not(.is-lead) time{display:block;margin-top:5px;font-size:11px}

/* ---- card-row: every story is a bordered horizontal card ---- */
.tsp-news-grid--m-card-row .tsp-news-card{border:1px solid var(--tsp-hairline,#e8e5de);border-radius:9px;overflow:hidden;background-color:var(--tsp-section-bg,#fff)}
.tsp-news-grid--m-card-row .tsp-news-card a{display:grid;grid-template-columns:37% minmax(0,1fr);gap:0;align-items:stretch}
.tsp-news-grid--m-card-row .tsp-news-card__media{aspect-ratio:4/3;margin:0;border-radius:0;height:100%}
.tsp-news-grid--m-card-row .tsp-news-card__content{padding:10px 12px}
.tsp-news-grid--m-card-row .tsp-news-card h3{margin:5px 0 0;line-height:1.3;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.tsp-news-grid--m-card-row .tsp-news-card p{display:none}
.tsp-news-grid--m-card-row .tsp-news-card time{display:block;margin-top:6px;font-size:11px}

/* Tap targets: the whole card is the link, and these minimums keep the
   smallest row (compact thumbnail height) at or above 44px. */
.tsp-news-grid--m-lead-stream .tsp-news-card:not(.is-lead) a,
.tsp-news-grid--m-card-row .tsp-news-card a{min-height:78px}
}

/* v1.10.18: `lead-two` promotes its lead media to an absolute fill layer and
   scrims it with a pseudo-element. The lead-stream family cannot undo either
   (it never sets `position`, and it has no handle on the ::after), so the
   overlay must be dismantled explicitly at the phone tier or the lead would
   render as a scrimmed empty box above unstyled text. Placed after the family
   block so equal specificity resolves this way on source order. */
@container (max-width:520px){
.tsp-news-grid--lead-two .tsp-news-card.is-lead{min-height:0;overflow:visible;border-radius:0}
.tsp-news-grid--lead-two .tsp-news-card.is-lead a{height:auto}
.tsp-news-grid--lead-two .tsp-news-card.is-lead a::after{display:none}
.tsp-news-grid--lead-two .tsp-news-card.is-lead .tsp-news-card__media{position:relative;inset:auto;height:auto;aspect-ratio:16/10;border-radius:var(--tsp-radius,8px);overflow:hidden}
.tsp-news-grid--lead-two .tsp-news-card.is-lead .tsp-news-card__content{position:static;padding:12px 0 0}
.tsp-news-grid--lead-two .tsp-news-card.is-lead h3{color:var(--tsp-title-color,var(--tsp-ink,#16181f))}
.tsp-news-grid--lead-two .tsp-news-card.is-lead time{color:var(--tsp-muted,#676E7B)}
}

/* v1.10.19: review stars. Two stacked star rows — a grey track and a clipped
   coloured fill — so a half point renders exactly without a half-star glyph or
   any image asset. The element is only ever emitted for a rated post, so these
   rules cannot affect an unrated card. */
/* v1.10.23: restyled to the Aperture prototype — a gold serif score reading
   "4.0 / 5" beside the stars. currentColor is deliberately NOT used for the
   empty stars: on the dark Reviews block the card sets a light text colour, and
   inheriting it would render the empty stars as bright as the filled ones. */
.tsp-rating{display:flex;align-items:center;gap:8px;margin:6px 0 0;line-height:1;flex-wrap:wrap}
.tsp-rating__score{font-family:var(--ts-display);font-weight:700;font-size:23px;color:var(--tsp-rating-color,#b8892f);line-height:1}
.tsp-rating__outof{font-size:12px;font-weight:500;color:var(--tsp-rating-outof,#8b90a0);margin-left:3px}
.tsp-rating__track{position:relative;display:inline-block;color:var(--tsp-rating-empty,#d9dce1);font-size:14px;letter-spacing:2px;white-space:nowrap}
.tsp-rating__fill{position:absolute;top:0;left:0;overflow:hidden;color:var(--tsp-rating-color,#b8892f);white-space:nowrap}
/* Unrated review. Small, quiet and italic — it is a status note, not a score. */
.tsp-rating--pending{font-size:11.5px;font-style:italic;color:var(--tsp-rating-outof,#6d7385);gap:4px}
.tsp-rating--pending b{font-style:normal;font-weight:600}
/* Dark Reviews block: the section background comes from the block's own
   backgroundColor control, so the empty-star and caption greys are re-pointed
   when a card sits on a dark section rather than being hardcoded per layout. */
.tsp-news-grid[style*="--tsp-section-bg"] .tsp-rating__track,.tsp-eb--dark .tsp-rating__track{--tsp-rating-empty:#454a59}

/* v1.10.21: utility-bar live date. Deliberately inherits the bar's own font
   size and colour rather than declaring its own, so it matches whatever Blocksy
   header row it is dropped into instead of fighting the theme. */
.tsp-utility-date{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.tsp-utility-date__prefix{opacity:.7}

/* ==========================================================================
   v1.10.32 — "Reviews strip" preset (`review-strip`) + heading note.

   ADDITIVE ONLY, per this file's card-row contract: `editorial-row`,
   `compact-strip` and `lead-mosaic` are untouched. Every rule below is scoped
   to .tsp-news-grid--review-strip.

   Thumb is 1:1 SQUARE by explicit client decision. The Aperture prototype uses
   a 59x88 portrait thumb; that is deliberately NOT followed here.

   Colours come from the block's own custom properties, so the dark band is
   whatever backgroundColor/titleColor/accentColor the editor set rather than a
   hardcoded #16181F.
   ========================================================================== */
.tsp-news-grid--review-strip .tsp-news-grid__items{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:var(--tsp-gap,20px)}
/* The card-row presets give .tsp-news-card a border, radius and background.
   This preset is a bare row, so those are explicitly cleared rather than
   out-specified elsewhere. */
.tsp-news-grid--review-strip .tsp-news-card{border:0;background:none;padding:0;border-radius:0;overflow:visible}
.tsp-news-grid--review-strip .tsp-news-card a{display:grid;grid-template-columns:88px minmax(0,1fr);gap:14px;align-items:center}
.tsp-news-grid--review-strip .tsp-news-card__media{aspect-ratio:1/1;width:88px;border-radius:var(--tsp-radius,6px);overflow:hidden;margin:0}
.tsp-news-grid--review-strip .tsp-news-card__media img{width:100%;height:100%;object-fit:cover;object-position:center}
.tsp-news-grid--review-strip .tsp-news-card__content{padding:0;min-width:0}
.tsp-news-grid--review-strip .tsp-eb-category{background:none;padding:0;letter-spacing:1px;text-transform:uppercase;font-weight:700;color:#b07680}
.tsp-news-grid--review-strip .tsp-news-card h3{font-family:var(--ts-display);font-weight:600;line-height:1.2;margin:5px 0 0;color:var(--tsp-title-color,#fff);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
/* Score above stars in this preset, rather than the inline row used elsewhere. */
.tsp-news-grid--review-strip .tsp-rating{flex-direction:column;align-items:flex-start;gap:0;margin:0}
.tsp-news-grid--review-strip .tsp-rating__score{font-family:var(--ts-display);font-size:23px;font-weight:700;color:var(--tsp-rating-color,#b8892f);margin:5px 0 2px;line-height:1}
.tsp-news-grid--review-strip .tsp-rating__outof{font-size:.55em;color:var(--tsp-rating-color,#b8892f);opacity:.75;margin-left:3px}
.tsp-news-grid--review-strip .tsp-rating__track{font-size:14px;letter-spacing:2px;margin-top:8px;color:#4a4034}
.tsp-news-grid--review-strip .tsp-rating__fill{color:var(--tsp-rating-color,#b8892f)}
/* Unrated: a quiet status note, never a gold zero-score. */
.tsp-news-grid--review-strip .tsp-rating--pending{font-size:11px;font-style:italic;color:#8a8f9a;margin-top:6px}
@media (max-width:600px){
	.tsp-news-grid--review-strip .tsp-news-grid__items{grid-template-columns:1fr}
	.tsp-news-grid--review-strip .tsp-news-card a{grid-template-columns:72px minmax(0,1fr)}
	.tsp-news-grid--review-strip .tsp-news-card__media{width:72px}
}

/* v1.10.32: optional heading note. The row only becomes a flex container when a
   note exists, so every heading without one keeps its current block layout. */
.tsp-eb-heading--has-note{display:flex;justify-content:space-between;align-items:center;gap:16px}
.tsp-eb-heading__note{font-size:10px;letter-spacing:1.5px;text-transform:uppercase;font-weight:700;color:var(--tsp-accent,#C8102E);white-space:nowrap}

/* v1.10.51 — LATEST ticker, matched to the prototype's `.ticker` / `.lbl`.

   Two separate faults made it read as broken on the live page:

   1. It had NO max-width, so inside Blocksy's `.ct-container-full` it ran the
      full viewport instead of lining up under the menu with the rest of the
      content. The prototype constrains it exactly as it constrains the header:
      `max-width:var(--maxw); margin:0 auto`. Doing it here rather than relying
      on the parent means it stays aligned wherever the block is placed.
   2. The LATEST badge was `flex:0 0 19%` — a fifth of the page, so on a wide
      screen it was a huge red slab whose text floated in the middle of it, and
      the headlines were squeezed into what was left. The prototype's badge
      hugs its text (`flex:0 0 auto`) at 700 11px with a 3px radius.

   The gutter uses max() so the prototype's 20px is guaranteed even when the
   block's own padding vars are 0, while a deliberately larger editor value
   still wins. */
.tsp-news-ticker{max-width:var(--tsp-eb-wrap,1200px);margin-left:auto;margin-right:auto;align-items:center;gap:14px;padding-left:max(var(--tsp-pl,0px),20px);padding-right:max(var(--tsp-pr,0px),20px)}
.tsp-news-ticker__label{flex:0 0 auto;padding:4px 10px;border-radius:3px;font-weight:700;font-size:11px;letter-spacing:1px;text-transform:uppercase}
/* The badge no longer stretches, so the track supplies its own leading gap
   rather than inheriting the old label's built-in one. */
.tsp-news-ticker__track{padding-left:0}

/* v1.10.54 — Watch, rebuilt to the prototype's `.watch` (owner's decision).

   The prototype is two columns, 1.6fr / 1fr: the feature fills the left column
   and a stacked thumbnail list runs down the right. Ours was feature-on-top
   spanning full width with a row of tiles beneath — a different section shape,
   not a different skin.

   The markup is one flat list of cards, so the feature can only span the list's
   rows if the row count is known; render_video_grid() emits has-1..has-6 for
   that, the same device the mosaic uses. Spanning a fixed large number instead
   would create empty implicit rows, and every one of them would add a row gap. */
@container (min-width:761px){
.tsp-video-grid--featured-row .tsp-video-grid__items{grid-template-columns:1.6fr 1fr;gap:26px;align-items:start}
.tsp-video-grid--featured-row .tsp-video-card.is-featured{grid-column:1}
.tsp-video-grid--featured-row.has-1 .tsp-video-grid__items{grid-template-columns:minmax(0,1fr)}
.tsp-video-grid--featured-row.has-3 .tsp-video-card.is-featured{grid-row:1/span 2}
.tsp-video-grid--featured-row.has-4 .tsp-video-card.is-featured{grid-row:1/span 3}
.tsp-video-grid--featured-row.has-5 .tsp-video-card.is-featured{grid-row:1/span 4}
.tsp-video-grid--featured-row.has-6 .tsp-video-card.is-featured{grid-row:1/span 5}
/* Right column: the prototype's `.wv` — 120px thumb, text beside it, hairline
   between rows and none above the first. */
.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured){grid-column:2}
.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__link{display:grid;grid-template-columns:120px minmax(0,1fr);gap:12px;align-items:start;padding:11px 0;border-top:1px solid var(--tsp-hairline,#E8E5DE)}
.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured):first-of-type .tsp-video-card__link{border-top:0;padding-top:0}
.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__media{margin:0;border-radius:5px;aspect-ratio:16/9}
.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__body{padding:0;min-width:0}
/* The play badge belongs on the feature; at 120px it would cover the thumb. */
.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__play{width:26px;height:26px}
.tsp-video-grid--featured-row .tsp-video-card.is-featured .tsp-video-card__media{aspect-ratio:16/9;border-radius:8px}
}

/* v1.10.59 Part B — the last five section headings.

   These resolved colour through `var(--tsp-title-color, …)`, and Customizer
   Additional CSS redefines that token to #192a3d. v1.10.58 fixed the story
   titles the same way but its rule lived in typography.css, which is enqueued
   BEFORE this file — so blocks.css line 2 (`.tsp-eb-heading h2`, same
   (0,1,1) specificity) won on source order and the headings stayed wrong.
   Fixing it here, after the rule it has to beat, is what settles it.

   The indirection is dropped rather than its fallback changed: a fallback only
   applies when the token is UNDEFINED, and Additional CSS defines it. Once this
   lands, that Customizer block can be emptied with no visual change.

   Deliberately NOT touched: `.tsp-news-grid--review-strip .tsp-news-card h3`
   uses `var(--tsp-title-color,#fff)` for the dark scorecard, and is (0,2,1) so
   it outranks this anyway — those titles stay white. */
.tsp-eb-heading h2,
.tsp-eb-heading h3,
.tsp-eb-heading h4,
.tsp-eb-heading div,
.tsp-section-intro__title,
.tsp-section-heading{color:var(--ts-ink,#16181F)}

/* Aperture v1.10.62 — hero fills its column (removes dead space under hero).
   v1.10.63: the duplicate `:root{--ts-display:…}` that used to lead this line is
   gone — it lived here only to beat typography.css on source order, and the
   token is now declared once, in typography.css where it belongs. */ .tsp-hero-wrap{height:100%} .tsp-hero-wrap .tsp-hero--single, .tsp-hero-wrap .tsp-hero--single .tsp-hero__grid{height:100%} .tsp-hero-wrap .tsp-hero--single .tsp-hero__item--lead{display:flex;flex-direction:column;height:100%} .tsp-hero-wrap .tsp-hero--single .tsp-hero__item--lead .tsp-hero__media{flex:1 1 auto;aspect-ratio:auto;min-height:326px} .tsp-hero-wrap .tsp-hero--single .tsp-hero__item--lead .tsp-hero__content{flex:0 0 auto}

/* v1.10.64 — newsletter band. FULL-BLEED by construction: the colour is on the
   <section> and the constraint is on an inner wrap, so the red always runs edge
   to edge. Capping the band itself is what turned it into a boxed red rectangle
   in v1.10.59; keeping them as two boxes makes that mistake unavailable. */
/* scroll-margin-top moved to the shared component sheet in v1.10.421 — the
   value here never applied when the band was actually the :target, and it was
   the wrong number on a phone regardless. */
.tsp-newsletter-band{background:var(--tsp-nb-bg,#C8102E);color:#fff;width:100%}
.tsp-newsletter-band__wrap{max-width:var(--tsp-wrap,1200px);margin-inline:auto;padding:40px var(--tsp-gutter,20px);display:flex;align-items:center;justify-content:space-between;gap:40px;flex-wrap:wrap;box-sizing:border-box}
/* v1.10.421 — TWO COLUMNS, and they hold.
 *
 * The band read as left-heavy with a large unused red area on the right, and
 * measurement showed why. Neither column had a bound:
 *
 *   - the form was `flex: 0 1 auto`, so its width came from its own max-content.
 *     A percentage-basis child (the full-width consent line) inflates that, and
 *     the form box measured 752px at 1920 while the controls inside it occupied
 *     393px at its LEFT edge — 359px of dead red inside the form itself;
 *   - text basis 420 + form 752 + gap 30 = 1202, one pixel over the 1200 wrap.
 *     So at 1366 — the commonest laptop width — the two columns had already
 *     wrapped into a stack, with the form left-aligned and 428px of empty band
 *     beside it. The composition the design intended simply never rendered
 *     below 1600.
 *
 * Both columns now take an explicit 46% basis with a matching cap, so they are
 * balanced by construction and the wrap point is a decision rather than an
 * accident. `min-width: 0` stops the consent line's min-content from flooring
 * the form wider than its share.
 */
.tsp-newsletter-band__text{flex:1 1 46%;max-width:560px;min-width:0}
.tsp-newsletter-band__h{font-family:var(--ts-display);font-size:26px;font-weight:700;line-height:1.2;margin:0;color:#fff}
.tsp-newsletter-band__p{font-family:var(--ts-ui);font-size:13.5px;line-height:1.5;margin:6px 0 0;color:#fff;text-align:left}
.tsp-newsletter-band__form{display:flex;align-items:center;gap:var(--tsp-sb-gap,8px);flex-wrap:wrap;flex:1 1 46%;max-width:560px;min-width:0}
/* v1.10.334  these four rules are UNCHANGED in intent; they are re-scoped so
   they actually win. The band always specified a white field and an ink button,
   but neither reached the page:

     input  Blocksy ships `input:is([type="email"], ...)`, which is (0,1,1) --
            an element plus an attribute -- against our single class (0,1,0),
            so the field kept the theme's transparent background and slate
            text. Measured on the red band: 2.49:1, below the 4.5:1 AA needs.
     button Blocksy's `[type="submit"]` ties us at (0,1,0) and loads later, so
            the button took the theme's brand red -- on a brand-red band, which
            left the site's primary CTA with no visible shape at all.

   Adding the parent class makes both (0,2,0), which outranks (0,1,1) and the
   later-loading tie alike. Same fix as the Careers submit button in v1.10.2xx:
   raise specificity, never !important. */
/* v1.10.421 — the appearance of both controls now comes from the shared Scope
   Briefing component (assets/css/scope-briefing.css): background, colour,
   height, radius, type and every interaction state, identical to the article
   placement. What is left here is purely how they share the row — the field is
   the primary control and takes the remaining width, the button takes what its
   label needs. */
.tsp-newsletter-band .tsp-newsletter-band__input{flex:1 1 auto;width:auto;min-width:0}
.tsp-newsletter-band .tsp-newsletter-band__btn{flex:0 0 auto}
.tsp-newsletter-band .tsp-newsletter-band__btn:focus-visible{background:#000}
/* v1.10.421: the result message moved to the shared component sheet, where the
   article placement gets the same treatment — it had none, and was staying off
   the control row only by being longer than the gap beside the field. */

/* v1.10.421: the columns hold to 900, not 1023.
   At 1023 they were still comfortable — 452px each, a 326px field — so
   stacking there threw away a composition that worked and reintroduced the
   original complaint at tablet: at 900 the stacked form sat capped and
   left-aligned with ~380px of empty red beside it. */
@media (max-width:899px){
	.tsp-newsletter-band__wrap{flex-direction:column;align-items:stretch;gap:16px}
	/* Column layout makes flex-basis size the HEIGHT, not the width, so the
	   `flex:1 1 420px` above turned the text into a 420px-tall box holding ~80px
	   of copy — ~340px of dead red space on every phone. Let it size to content. */
	.tsp-newsletter-band__text{flex:0 0 auto;max-width:none}
	/* Stacked under the pitch, and full width. A cap here was worse than no cap:
	   it left the form floating against a wide empty band, which is the exact
	   complaint this patch exists to fix. The form is still a ROW at these
	   widths — only the columns stacked. */
	.tsp-newsletter-band__form{flex:0 0 auto;max-width:none;width:100%}
}

/* Below 600 the row itself becomes a column: at 320 a side-by-side field would
   be 154px wide, which is not an email field. Full-width controls at the shared
   component height keep both comfortably above the minimum tap target.
   Re-scoped alongside the base rules above: those are (0,2,0), so a (0,1,0)
   override in here would lose and the field would keep its desktop sizing on
   every phone. */
@media (max-width:600px){
	.tsp-newsletter-band__form{flex-direction:column;align-items:stretch}
	.tsp-newsletter-band .tsp-newsletter-band__input,.tsp-newsletter-band .tsp-newsletter-band__btn{flex:0 0 auto;width:100%;min-height:44px}
}

/* v1.10.76 — typography test: ticker headlines.
   Was inheriting the 16px body size at weight 400 (no ticker rule existed).
   Family stays Poppins and case stays as authored; only size and weight move. */
.tsp-news-ticker__track a{font-size:13px;font-weight:600}

/* ==========================================================================
   v1.10.77 — typography system: editorial blocks.
   ========================================================================== */

/* §8 ticker badge — 11px/700, 1px tracking, uppercase. Headline was set to
   13px/600 in v1.10.76; leading is added here, nothing else moves. */
.tsp-news-ticker__label{font-size:11px;font-weight:700;letter-spacing:1px;text-transform:uppercase}
/* v1.10.181: the reference's small white status dot, left of the label.
   Drawn as a pseudo-element so the label stays plain text — the badge already
   reads "LIVE" to a screen reader and a decorative glyph in the markup would
   only add noise. The badge is already `display:flex; align-items:center`, so
   this needs a gap and nothing else; letter-spacing is cancelled on the dot so
   the 1px tracking does not push it away from the word. */
.tsp-news-ticker__label{gap:6px;letter-spacing:1px}
.tsp-news-ticker__label::before{
	content:"";
	flex:0 0 auto;
	width:6px;
	height:6px;
	border-radius:50%;
	background:currentColor;
	letter-spacing:0;
}
.tsp-news-ticker__track a{line-height:1.45;letter-spacing:normal}

/* §11 Major editorial section headings take the display serif — this is the
   "journalism" voice, and it is what separates a section head from a UI label.
   Scoped to the editorial block heading and the section intro ONLY: §11 is
   explicit that small sidebar and utility headings must NOT become Georgia, so
   .tsp-sidebar__heading is deliberately excluded. */
.tsp-eb-heading h2,.tsp-eb-heading h3,.tsp-section-intro__title{font-family:var(--ts-font-display);font-size:20px;font-weight:700;line-height:1.25;text-transform:none;letter-spacing:normal}

/* §12 Section / category labels — 10.5px/700, 0.8px, uppercase. */
.tsp-eb-category,.tsp-photo-card__category,.tsp-video-card__category{font-size:10.5px;font-weight:700;letter-spacing:.8px;text-transform:uppercase}

/* ==========================================================================
   v1.10.78 — typography system, remaining components (§13–20, §22, §26).
   Sizes and voices only. No layout, colour, spacing or dimension changes.

   Voice assignment throughout: a title that is READ takes Georgia; a title that
   is SCANNED in a list takes Inter; prose takes Source Serif 4.
   ========================================================================== */

/* §13 Across the Newsroom — lead 19px, normal card 16.5px, both Georgia. */
.tsp-news-grid .tsp-news-card.is-lead h3{font-family:var(--ts-font-display);font-size:19px;font-weight:700;line-height:1.3}
.tsp-news-grid .tsp-news-card h3{font-family:var(--ts-font-display);font-size:var(--ts-title-standard);font-weight:700;line-height:1.35}
/* Compact supporting rows stay at 13.5px — explicitly NOT the 11px the brief
   warns against. v1.10.422: family moves to the display serif. "Scanned, not
   read" was the reasoning for the UI voice; a compact card still carries a real
   story headline, and its neighbours in the same grid were already serif. */
.tsp-news-grid--m-compact-row .tsp-news-card h3,.tsp-news-grid--compact .tsp-news-card h3{font-family:var(--ts-font-display);font-size:var(--ts-title-dense);font-weight:600;line-height:var(--ts-lh-dense)}
/* Excerpts are prose. Kept, not removed (§13). */
.tsp-news-card p,.tsp-feature-card p{font-family:var(--ts-font-body);font-size:13.5px;font-weight:400;line-height:1.55}
.tsp-news-card time,.tsp-eb time{font-family:var(--ts-font-ui);font-size:11.5px;font-weight:400;line-height:1.4}

/* §14 Reviews — titles Georgia; scores are data, so UI voice. The dark
   scorecard's own colour rules are untouched. */
.tsp-news-grid--review-strip .tsp-news-card h3{font-family:var(--ts-font-display);font-size:16px;font-weight:700;line-height:1.3}
.tsp-rating__score{font-family:var(--ts-font-ui);font-size:12px;font-weight:600}
.tsp-rating__outof{font-family:var(--ts-font-ui);font-size:11px;font-weight:500}

/* §17 In Pictures / §18 Watch — all card titles display serif.
   v1.10.422: the lead was serif and every secondary card beside it was Inter,
   inside one grid — the clearest single instance of the split this pass
   removes. Sizes and weights are untouched, so the lead still leads. */
.tsp-photo-gallery--gallery-mosaic .tsp-photo-card.is-lead .tsp-photo-card__title,
.tsp-video-grid .tsp-video-card.is-featured h3{font-family:var(--ts-font-display);font-size:17.5px;font-weight:700;line-height:1.3}
.tsp-photo-card__title,.tsp-video-card h3{font-family:var(--ts-font-display);font-size:var(--ts-title-dense);font-weight:600;line-height:var(--ts-lh-dense)}
.tsp-video-card__duration{font-family:var(--ts-font-ui);font-size:10.5px;font-weight:500}
.tsp-video-card__meta{font-family:var(--ts-font-ui);font-size:11.5px;font-weight:400;line-height:1.4}

/* §20 Trending chips — 11.5px/600. Not heavier: the brief is explicit that the
   pills should not read as overly bold. */
.tsp-trending-now__chip{font-family:var(--ts-font-ui);font-size:11.5px;font-weight:600}

/* §22 Newsletter — heading Georgia; the rest is UI.
   v1.10.421: 20px/12px raised to 24px/13px. At 20px the headline was the
   quietest thing in a full-bleed brand band, and it sat 10px away from the
   article placement's 30px — the same component speaking in two voices. The
   article comes down to 28px in the same patch, so the pair now reads as one
   type system scaled to its context rather than as two products. */
.tsp-newsletter-band__h{font-family:var(--ts-font-display);font-size:24px;font-weight:700;line-height:1.25}
.tsp-newsletter-band__p{font-family:var(--ts-font-ui);font-size:13px;font-weight:400;line-height:1.5}
/* v1.10.421: the control type rules that used to sit here are gone. They set
   the field to 13px and the button to 12px/600 while the article placement ran
   14px/700 — the same component in two voices. Both now take their type from
   the shared Scope Briefing sheet, and this section keeps only the band's own
   headline and pitch. */

/* §26 Pagination and view-all are controls, so UI voice. */
.tsp-eb-pagination a,.tsp-eb-pagination span{font-family:var(--ts-font-ui);font-size:12.5px;font-weight:600}
.tsp-nav-viewall{font-family:var(--ts-font-ui);font-size:11.5px;font-weight:700;letter-spacing:.5px;text-transform:uppercase}

/* §27 Mobile — reduced deliberately per component, not scaled uniformly. */
@container (max-width:520px){
	.tsp-news-grid .tsp-news-card.is-lead h3{font-size:18px}
	.tsp-news-grid .tsp-news-card h3{font-size:var(--ts-title-standard)}
	.tsp-news-ticker__track a{font-size:12.5px}
}

/* v1.10.79 — section-heading weight. Measured 600 against the specified 700;
   qualifying with the block wrapper wins without !important. */
.tsp-eb .tsp-eb-heading h2,.tsp-eb .tsp-eb-heading h3,
.tsp-eb-wrap .tsp-eb-heading h2,.tsp-eb-wrap .tsp-eb-heading h3,
.tsp-eb .tsp-section-intro__title{font-family:var(--ts-font-display);font-size:20px;font-weight:700;line-height:1.25}

/* v1.10.80 — "Visit …" CTAs share one baseline across the Newsroom columns.

   ROOT CAUSE (measured, not assumed): the parent .wp-block-columns is already
   display:flex and already stretches its children, but .tsp-eb-wrap inside each
   column is display:block. A block wrapper does not fill the stretched column,
   so the CTA sits immediately after the content at whatever height that content
   happens to reach. Politics and Movies wrapped to the same height (978px, CTA
   at 156); Sports ran 23px shorter (955px, CTA at 132).

   FIX: make the chain a flex column so the content area absorbs the slack and
   the CTA is pushed to the bottom by `margin-top:auto`. Nothing is given a fixed
   height, nothing is truncated, and no per-column offset exists — so it stays
   correct whatever the real headlines wrap to.

   Scoped to columns at >=782px only. Below that the columns block stacks, each
   section takes its natural height, and forcing equal heights would open large
   blank gaps between stacked sections. 782px is the columns block's own stacking
   point, not a new breakpoint. */
@media (min-width:782px){
	.entry-content .wp-block-column > .tsp-eb-wrap{display:flex;flex-direction:column;height:100%}
	.entry-content .wp-block-column > .tsp-eb-wrap > .tsp-eb{flex:1 1 auto;display:flex;flex-direction:column}
	/* The one line that does the aligning. */
	.entry-content .wp-block-column .tsp-nav-viewall-row{margin-top:auto}
}

/* ============================================================
   News Ticker — previous / next arrows, and separator ownership.
   Appended last on purpose: several rules below intentionally beat the base
   ticker rules near the top of this file, and load order is what makes that
   work without !important.
   ============================================================ */

/* SEPARATOR OWNERSHIP.
   These two rules replace three patches that lived in Customizer > Additional
   CSS. The dot now follows the block's own accentColor rather than a hex
   pasted into the site config, and the last headline gets no trailing dot.
   Specificity here is (0,2,2) against the base rule's (0,1,2), so it wins on
   merit rather than with !important. */
.tsp-news-ticker .tsp-news-ticker__track a::after{color:var(--tsp-accent,#ed1c24);opacity:1}
.tsp-news-ticker .tsp-news-ticker__track a:last-child::after{content:none}

/* NO NATIVE SCROLLBAR, EVER.
   This is the fix for the grey bar and its stepper triangles under the
   headlines. The static track carries overflow-x:auto so it can be paged, and
   on Windows that paints a full classic scrollbar — 15px of gutter that pushed
   the row from ~38px to 53px and read as a second row of browser chrome.
   The track stays scrollable (JS scrollLeft, touch swipe and keyboard all keep
   working); only the bar itself is hidden. Applies with or without arrows,
   because the scrollbar predates them. */
.tsp-news-ticker--static .tsp-news-ticker__track{
	overflow-x:auto;
	overflow-y:hidden;
	scrollbar-width:none;      /* Firefox */
	-ms-overflow-style:none;   /* legacy Edge */
}
.tsp-news-ticker__viewport{scrollbar-width:none;-ms-overflow-style:none}
.tsp-news-ticker--static .tsp-news-ticker__track::-webkit-scrollbar,
.tsp-news-ticker__viewport::-webkit-scrollbar{width:0;height:0;display:none}

/* ARROWS.
   PHP renders the buttons; they stay hidden until news-ticker.js adds
   --js. A reader never sees a control that cannot do anything.

   Styled as the prototype's flat bordered chevron — a deliberate UI control,
   not a scroll indicator. Border and glyph are derived from currentColor
   rather than the prototype's literal light-theme hexes, because this ticker
   is colour-configurable and the default background is near-black: a
   hard-coded #E8E5DE hairline would vanish on a dark ticker. */
.tsp-news-ticker__arrow{display:none}
.tsp-news-ticker--js .tsp-news-ticker__arrow{
	display:flex;align-items:center;justify-content:center;
	flex:0 0 auto;
	/* 28px control: prototype draws 22px, but that is below a usable tap
	   target, so it takes the low end of the agreed 28–32px range. */
	width:28px;height:28px;
	padding:0;margin:0;
	border:1px solid rgba(128,128,128,.32);
	border-radius:4px;
	background:transparent;
	color:inherit;
	opacity:.72;               /* lands near the prototype's slate chevron */
	font-size:13px;line-height:1;cursor:pointer;
	-webkit-appearance:none;appearance:none;
	transition:opacity .15s,color .15s,border-color .15s;
}
.tsp-news-ticker--js .tsp-news-ticker__arrow:hover,
.tsp-news-ticker--js .tsp-news-ticker__arrow:focus-visible{
	color:var(--tsp-accent,#ed1c24);
	border-color:var(--tsp-accent,#ed1c24);
	opacity:1;
}
.tsp-news-ticker--js .tsp-news-ticker__arrow:focus-visible{outline:2px solid var(--tsp-accent,#ed1c24);outline-offset:2px}

/* DISABLED — everything already fits, so there is nothing to page to.
   The buttons keep their space rather than being hidden: removing them would
   reflow the row on exactly the pages where they are least expected to move
   (a two-headline Breaking News ticker). Muted and inert, but still clearly
   the same control rather than something broken. */
.tsp-news-ticker--js .tsp-news-ticker__arrow--disabled{opacity:.3;cursor:default}
.tsp-news-ticker--js .tsp-news-ticker__arrow--disabled:hover,
.tsp-news-ticker--js .tsp-news-ticker__arrow--disabled:focus-visible{
	color:inherit;
	border-color:rgba(128,128,128,.32);
	opacity:.3;
}

/* RTL: the chevrons are directional, so mirror them. Spacing above uses
   flex + gap rather than physical margins, so nothing else needs flipping. */
[dir="rtl"] .tsp-news-ticker__arrow > span{display:inline-block;transform:scaleX(-1)}

/* ONE SCROLLER FOR BOTH LAYOUTS.
   Scoped to --has-arrows and --js so no existing ticker changes. The static
   track normally scrolls itself; handing that job to the viewport lets the
   scroll and static layouts share a single stepping mechanism in JS instead of
   needing two that drift apart. */
/* overflow-x:auto, NOT hidden. Chrome silently ignores smooth scrolling on an
   overflow:hidden element — scrollLeft assignments animate to nowhere and the
   position stays at 0, which is exactly how the arrows shipped inert. The
   element has to be a real scroll container; the bar it would normally paint is
   hidden by the scrollbar rules above. */
.tsp-news-ticker--has-arrows.tsp-news-ticker--js .tsp-news-ticker__viewport{overflow-x:auto;overflow-y:hidden;scroll-behavior:smooth}
.tsp-news-ticker--has-arrows.tsp-news-ticker--js.tsp-news-ticker--static .tsp-news-ticker__track{overflow:visible;width:max-content}

/* v1.10.336  seamless marquee.

   The original keyframe runs translateX(5%) -> translateX(-100%), and those
   percentages are of the TRACK's own width. With a 1318px track in a 1002px
   viewport the tail clears the viewport once the offset passes -316px, so the
   last ~76% of every cycle was a growing empty strip that ended ~95% blank and
   then hard-snapped back. Measured over one 28s cycle, right-hand gap:

     -7 -> 41 -> 120 -> 238 -> 475 -> 713 -> 950px, then snap

   The fix is the standard one: the script repeats the headline list until the
   track holds two identical groups, and this keyframe travels exactly one
   group. As the first group leaves, the second is already in its place, so
   there is no gap and no visible reset. Duration comes from the script, which
   scales it to the cloned width so the perceived speed is unchanged.

   Declared BEFORE the pause and manual rules on purpose: all three are (0,2,0),
   so source order decides, and hover-pause and manual stepping must still win. */
@keyframes tspTickerSeamless{from{transform:translateX(0)}to{transform:translateX(calc(-1 * var(--tsp-seamless-shift,50%)))}}
.tsp-news-ticker--seamless .tsp-news-ticker__track{animation:tspTickerSeamless var(--tsp-seamless-speed,35s) linear infinite}

/* The marquee pauses while the reader is looking at it or tabbing through it. */
.tsp-news-ticker--scroll:hover .tsp-news-ticker__track,
.tsp-news-ticker--scroll:focus-within .tsp-news-ticker__track{animation-play-state:paused}

/* Manual mode: animation off outright while stepping. Paused is not enough —
   a paused transform still offsets the track and fights scrollLeft. */
.tsp-news-ticker--manual .tsp-news-ticker__track{animation:none;transform:none}

@media(prefers-reduced-motion:reduce){
	.tsp-news-ticker--has-arrows.tsp-news-ticker--js .tsp-news-ticker__viewport{scroll-behavior:auto}
}

/* ============================================================
   OVERLAY TILES — lead-mosaic and two-leads-four.
   Caption sits ON the image. Scoped entirely to
   .tsp-news-card--overlay, which PHP emits only for those two presets, so
   compact-strip, editorial-row, media-list and lead-two are untouched.
   Appended last: several rules here must beat earlier preset and mobile
   rules of equal specificity, and load order is what does that.
   ============================================================ */

.tsp-news-card--overlay{position:relative;background:transparent;border-radius:8px;overflow:hidden;height:100%;min-height:150px}
.tsp-news-card--overlay > a{position:relative;display:block;height:100%;text-decoration:none;color:inherit}

/* The media becomes the tile's backdrop rather than a block in the flow. */
.tsp-news-card--overlay .tsp-news-card__media{position:absolute;inset:0;width:100%;height:100%;aspect-ratio:auto;border-radius:0;overflow:hidden;margin:0}
.tsp-news-card--overlay .tsp-news-card__media img{width:100%;height:100%;object-fit:cover;object-position:center;display:block;transition:transform .45s ease}

/* No featured image: a tinted panel, never a broken or empty tile. */
.tsp-news-card--overlay .tsp-eb-placeholder{position:absolute;inset:0;display:block;background:linear-gradient(135deg,#2b2f3a,#181b22)}

/* The gradient is a child of the media, so it covers the photo AND the
   placeholder above — the caption keeps its contrast either way. */
.tsp-news-card--overlay .tsp-news-card__media::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;background:linear-gradient(180deg,rgba(10,10,14,0) 38%,rgba(10,10,14,.88) 96%)}

/* Specificity (0,3,0) deliberately: an earlier rule sets padding:0 on
   two-leads-four non-lead content at the same weight, and a (0,2,0) selector
   here would silently lose to it. */
.tsp-news-grid .tsp-news-card--overlay .tsp-news-card__content{position:absolute;left:0;right:0;bottom:0;z-index:2;padding:14px;min-width:0;color:var(--tsp-title-color,#fff)}

/* No font-family here: story titles already resolve to the editorial serif
   through the shared typography system, and restating it would fork that. */
.tsp-news-grid .tsp-news-card--overlay .tsp-story-title{margin:0;color:var(--tsp-title-color,#fff);font-size:14px;font-weight:700;line-height:1.3;overflow-wrap:break-word}
.tsp-news-grid .tsp-news-card--overlay .tsp-eb-category{display:inline-block;background:var(--tsp-accent,#C8102E);color:#fff;font-size:8.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;padding:3px 8px;border-radius:3px;margin:0 0 8px;line-height:1.5}
.tsp-news-grid .tsp-news-card--overlay .tsp-news-card__meta{display:block;margin-top:5px;font-size:10.5px;font-weight:500;line-height:1.4;color:var(--tsp-text-color,#c3c7d1)}

/* Lead tile: larger caption, roomier padding. */
.tsp-news-grid .tsp-news-card--overlay.is-lead .tsp-news-card__content{padding:20px}
.tsp-news-grid .tsp-news-card--overlay.is-lead .tsp-story-title{font-size:21px;line-height:1.2}

/* two-leads-four keeps its 2-column, 2-lead structure; only the tiles change. */
.tsp-news-grid--two-leads-four .tsp-news-card--overlay.is-lead{min-height:230px}
.tsp-news-grid.tsp-news-grid--two-leads-four .tsp-news-card--overlay.is-lead .tsp-story-title{font-size:19px}

.tsp-news-card--overlay:hover .tsp-news-card__media img,
.tsp-news-card--overlay:focus-within .tsp-news-card__media img{transform:scale(1.045)}
.tsp-news-card--overlay > a:focus-visible{outline:2px solid var(--tsp-accent,#C8102E);outline-offset:-2px;border-radius:8px}

@media (prefers-reduced-motion:reduce){
	.tsp-news-card--overlay .tsp-news-card__media img{transition:none}
	.tsp-news-card--overlay:hover .tsp-news-card__media img,
	.tsp-news-card--overlay:focus-within .tsp-news-card__media img{transform:none}
}

/* ---- Tablet: two columns, lead across the top ---- */
@container (max-width:760px){
	.tsp-news-grid--lead-mosaic .tsp-news-grid__items{grid-template-rows:auto}
	/* grid-row must be reset too. Leaving the 1/3 span from the desktop rule
	   would make a full-width lead also two rows tall and push the supports
	   into a phantom third row. */
	.tsp-news-grid--lead-mosaic .tsp-news-card.is-lead{grid-column:1/-1;grid-row:auto;min-height:260px}
	.tsp-news-grid--lead-mosaic .tsp-news-grid__items .tsp-news-card:not(.is-lead){grid-row:auto;grid-column:auto}
}

/* ---- Phones: one column, 4:3 tiles, captions still overlaid ---- */
@container (max-width:520px){
	.tsp-news-card--overlay{aspect-ratio:4/3;min-height:0;border-radius:var(--tsp-radius,8px)}
	.tsp-news-grid--lead-mosaic .tsp-news-card--overlay.is-lead,
	.tsp-news-grid--two-leads-four .tsp-news-card--overlay.is-lead{min-height:0}
	/* The shared mobile presets stack media above a padded caption. Overlay
	   tiles opt out: the caption stays on the image, which is the whole point
	   of the preset and is what the prototype does at this width. */
	.tsp-news-grid--m-lead-stream .tsp-news-card--overlay .tsp-news-card__media,
	.tsp-news-grid--m-card-row .tsp-news-card--overlay .tsp-news-card__media{position:absolute;inset:0;aspect-ratio:auto;margin:0;border-radius:0}
	.tsp-news-grid .tsp-news-card--overlay .tsp-news-card__content{position:absolute;padding:14px}
	.tsp-news-grid .tsp-news-card--overlay.is-lead .tsp-news-card__content{padding:16px}
	.tsp-news-grid .tsp-news-card--overlay.is-lead .tsp-story-title{font-size:18px}
	.tsp-news-grid .tsp-news-card--overlay .tsp-story-title{font-size:15px;display:block;-webkit-line-clamp:unset;overflow:visible}
	.tsp-news-grid .tsp-news-card--overlay .tsp-eb-category{font-size:9px}
	.tsp-news-grid .tsp-news-card--overlay .tsp-news-card__meta{font-size:11px}
}

/* v1.10.111 — LATEST ticker on phones: the arrows come out.

   Measured at 390px: label 68px + prev 28 + next 28 + gaps = 206px of the row,
   leaving a 184px reading window for headlines 367-474px wide. The marquee then
   has to drag each headline through a slot smaller than half the screen.

   The prototype's mobile ticker (`.ticker` in preview-mobile-app.html) has no
   arrows — just the red tag and a swipeable trail — so removing them here is
   the design, not a compromise. It also retires two 28x28 controls that were
   under the 44px touch floor.

   The MARQUEE IS UNTOUCHED. `--scroll` still animates the track, and the
   viewport keeps `overflow-x:auto`, so a reader can still swipe it by hand.

   @container, not @media, per the wrapper standard: .tsp-news-ticker declares
   container-type:inline-size, and arrows are descendants of it so they can
   query it. The `--js` class is included because news-ticker.js sets
   `display:flex` at (0,2,0) — a bare (0,1,0) rule would lose. */
@container (max-width:520px){
	.tsp-news-ticker--js .tsp-news-ticker__arrow{display:none}
}

/* v1.10.111 — ticker arrows reach the 44px touch floor on phones and tablets.

   28px was chosen against the prototype's 22px chevron as "the low end of the
   agreed 28-32px range", which is a fine DESKTOP pointer target and half a
   finger. Below 782px they become 44x44.

   @media, not @container, on purpose: this is a property of the INPUT (touch)
   and of the viewport, not of how wide the block happens to be rendered. A
   ticker placed in a 400px desktop sidebar should keep the pointer-sized
   control; the same 400px on a phone should not. Container width cannot tell
   those apart.

   Below ~520px of container the arrows are display:none (above), so this only
   takes effect in the band where they are actually shown. Desktop above 782px
   is untouched. */
@media (max-width:782px){
	.tsp-news-ticker--js .tsp-news-ticker__arrow{width:44px;height:44px;font-size:15px}
}

/* ==========================================================================
   v1.10.164 — "state-desk": one desk of Across the Telugu States
   --------------------------------------------------------------------------
   A NEW News Grid preset, not a variation of an existing one, for the same
   reason the cinematic Hero and the Scope Briefing are new: the Customizer
   owns several `--sidebar-lead-compact` and `--lead-mosaic` rules, and
   wp-custom-css prints after this file.

   One block renders ONE desk — lead + three supporting stories — so National,
   Andhra Pradesh and Telangana stay three independent blocks with their own
   category, their own View All and their own paging. Nothing about the query,
   the navigation controller or the dedupe registry changes.

   All sizing is CONTAINER-relative: a desk is ~370px beside its siblings at
   1600 but ~728px stacked at 768, so viewport media queries would be wrong.
   ========================================================================== */

.tsp-news-grid--state-desk {
	--tsp-desk-gap: 14px;
	--tsp-desk-rule: #E8E5DE;
	/* Arrow button size. Named because the desk header reserves this height
	   whether or not the desk actually renders arrows — see the alignment rule
	   in the "Across the Telugu States" section below. Note the block's own
	   `--tsp-nav-arrow-size` stays at its 40px default here; this preset sizes
	   its buttons directly, so the two must not be confused. */
	--tsp-desk-arrow: 32px;
	/* v1.10.175: the horizontal breathing room for the desk HEADER and the LEAD
	   IMAGE only — deliberately not padding on the desk itself.
	   Measured before the change, every element sat 1px from the card edge (i.e.
	   against the border) EXCEPT the lead kicker and headline, which the shared
	   card rule already insets by 10px. So the card had one line at 11px and
	   everything else flush, and the header and lead image were the two pieces
	   that read as touching the border. 10px puts both on the existing 11px text
	   line rather than inventing a new one.
	   Padding the desk instead would have taken 20px from every supporting row's
	   text column, which is the one thing this change must not do — the rows and
	   the footer keep their full-bleed alignment. */
	--tsp-desk-inset: 10px;
	container-type: inline-size;
	padding: 16px 16px 14px;
	border: 1px solid var(--tsp-desk-rule);
	border-radius: 8px;
	background: #fff;
	/* v1.10.172: a column so the footer can be anchored to the bottom with
	   `margin-top:auto` rather than floating directly under the last row. Desks
	   are equal-height by construction (the parent grid stretches them), and a
	   desk with fewer stories — Telangana has one page of three — must spend that
	   difference as quiet space above its footer, NOT by stretching its rows.
	   That is the whole reason the section looked loose. */
	display: flex;
	flex-direction: column;
}

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

.tsp-news-grid--state-desk .tsp-eb-heading {
	display: flex;
	align-items: center;
	gap: 10px;
	margin: 0 0 6px;
	padding: 0;
	border: 0;
}
/* v1.10.422 — this rule was never reaching the page, and the fix is the `h3`.
 *
 * It asked for Inter 15/800 and the heading has always rendered Georgia 20/700.
 * The selector list covers `h2` and `> *` but not `h3`, and the markup emits an
 * h3: `.tsp-eb .tsp-eb-heading h3` in the same file is (0,2,1), while the `> *`
 * branch here is only (0,2,0), so the generic display-serif rule won on
 * specificity and only the letter-spacing and text-transform from this block
 * ever applied. The project's own cascade-resolution test has been reporting
 * these declarations as skipped.
 *
 * Now the declarations match what renders, so intent and output agree, and the
 * heading is display type by decision rather than by accident. h3 is added so
 * the rule can actually win.
 *
 * The uppercase and .04em tracking are KEPT — "NATIONAL", "ANDHRA PRADESH" and
 * "TELANGANA" are a deliberate desk-strip treatment and the tracking is what
 * makes serif capitals readable at this size. */
.tsp-news-grid--state-desk .tsp-eb-heading h2,
.tsp-news-grid--state-desk .tsp-eb-heading h3,
.tsp-news-grid--state-desk .tsp-eb-heading > * {
	margin: 0;
	font-family: var(--ts-display, Georgia, serif);
	font-size: 20px;
	font-weight: 700;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: var(--ts-ink, #16181F);
}

/* The desk emblem. Drawn as a MASK so one file per desk tints itself with
   currentColor — vector-crisp at any DPI, no coloured raster, no external
   request, and decorative by construction (a pseudo-element is never read). */
.tsp-news-grid--state-desk .tsp-state-desk__emblem {
	display: block;
	flex: 0 0 auto;
	width: 26px;
	height: 26px;
	background-color: var(--ts-red, #C8102E);
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
}

/* MAP SILHOUETTES — GENERATED FROM GEODATA, NOT DRAWN BY HAND (v1.10.174).
 *
 * v1.10.173 shipped hand-drawn approximations of these three shapes and they
 * read as abstract blobs, because a shape you can recall is not the shape a
 * reader recognises. These are derived from real geometry instead.
 *
 * SOURCE: 760 Indian DISTRICT polygons tagged with `st_nm`
 * (github.com/udit-001/india-maps-data, india.geojson). Districts rather than
 * ready-made state outlines is what makes one pipeline serve all three: they
 * dissolve into a state boundary, and all 36 states dissolve into the national
 * outline, so India and its states are guaranteed to agree with each other. It
 * is an India-sourced dataset carrying Jammu and Kashmir and Ladakh as states.
 *
 * PIPELINE (scripted end to end, no hand editing at any step): project with the
 * cos(mean latitude) correction so nothing is stretched east-west -> rasterise
 * by scanline using NONZERO WINDING, which dissolves shared district edges and
 * still subtracts holes -> keep the largest connected component, which drops the
 * offshore islands that would be sub-pixel here and would otherwise shrink the
 * mainland to make room -> trace the boundary (Moore-neighbour) -> simplify
 * (Douglas-Peucker) -> normalise into this 24x24 viewBox.
 *
 * APPARENT SIZE is normalised by INK, not by bounding box. Fitted to the same
 * box the three measured 28.5% / 20.1% / 49.7% coverage, so Telangana read as a
 * slab beside Andhra Pradesh's sliver. Per-icon padding brings them to roughly
 * 30% / 22% / 34%: Andhra Pradesh takes the whole box because a long diagonal
 * shape cannot reach the others' weight without overflowing the viewBox (which
 * an SVG clips), and Telangana is pulled in. Equalising exactly would shrink
 * Telangana's extent until it read as a smaller icon, so this closes most of the
 * gap rather than all of it.
 *
 * WHEN EDITING ONE OF THESE: the prefixed and unprefixed `mask-image` values
 * must stay byte-identical, or one engine renders a plain red square.
 *
 * STILL NOT CARTOGRAPHY. Simplified to ~140 points for a 26px icon, islands
 * dropped, no boundary information carried — fine as a desk emblem, not fine
 * anywhere a reader could take it for an authoritative map. Depictions of
 * India's borders are subject to specific legal requirements in India, so if
 * these are ever used larger the outlines want approving against an official
 * source. */

/* National — India. */
.tsp-state-desk__emblem--national {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M6 0.4L6.5 0.4L8.2 1.7L9.4 1.3L10.2 1.6L10 2.3L9.2 2.9L9.2 3.4L9.5 3.5L9.7 3.9L9.2 4.1L8.9 3.9L8.8 4.2L9.1 5L9.3 4.9L9.7 5.3L10.7 5.8L10.2 6.3L10 7L12 8.1L13 8.1L14.3 8.8L15.9 9L16.1 7.7L16.5 7.6L16.4 8.3L16.8 8.6L18.9 8.6L18.9 8.1L18.7 8.1L18.6 7.8L19.4 7.8L19.9 7.2L20.3 7.1L20.8 6.6L21.4 6.9L21.9 6.5L22.1 6.7L22 6.8L22.3 7L22.1 7.3L22.9 7.5L22.9 7.7L22.5 8L22.7 8.3L22.3 8.1L21.2 8.8L20.5 10.9L19.8 10.8L19.9 11.5L19.7 11.7L19.6 12.4L19.4 12.4L19.1 11L18.6 11.7L18.3 11.2L18.4 10.9L18.9 10.7L19.1 10.1L19.3 10.1L19.1 10L17.3 9.8L17.2 9.1L16.9 9.2L16.7 8.9L16.3 8.9L16 9.1L16 9.4L16.6 9.8L16.3 9.9L15.9 10.3L16.4 10.6L16.3 11.1L16.6 11.5L16.7 12.5L16.2 12.5L16.1 12.7L16.1 12.3L15.8 12.7L15.2 12.9L15.2 13.5L14.7 14.1L13.7 14.6L13 15.4L11.6 16.5L11.7 16.8L10.9 17L10.7 17.5L10.5 17.3L10.2 17.5L10 18.2L10.2 19.5L9.8 20.7L9.8 21.8L9.4 21.9L9.1 22.5L9.3 22.6L8.8 22.8L8.2 23.6L7.4 22.9L6.8 21L6.3 20.3L5.8 18.5L5.1 17.3L4.4 12.5L4.8 12.2L4.3 12.2L4.1 13.1L3.1 13.5L1.8 12.3L2.6 12L3.1 11.5L2 11.8L1.1 11.1L1.6 10.9L1.6 10.6L2.6 10.7L3.4 10.5L3.1 9.5L2.7 9.4L2.7 8.9L2.2 8.7L2.2 8.3L2.8 7.6L3.1 7.9L3.9 7.7L4.3 7.1L4.8 6.8L5.1 6.1L6.1 5.2L5.9 5.1L6 4.6L6.6 4.3L5.3 3.6L5.1 2.6L5.6 2L5.3 1.8L5.3 1.6L4.4 1.3L4.9 0.7Z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M6 0.4L6.5 0.4L8.2 1.7L9.4 1.3L10.2 1.6L10 2.3L9.2 2.9L9.2 3.4L9.5 3.5L9.7 3.9L9.2 4.1L8.9 3.9L8.8 4.2L9.1 5L9.3 4.9L9.7 5.3L10.7 5.8L10.2 6.3L10 7L12 8.1L13 8.1L14.3 8.8L15.9 9L16.1 7.7L16.5 7.6L16.4 8.3L16.8 8.6L18.9 8.6L18.9 8.1L18.7 8.1L18.6 7.8L19.4 7.8L19.9 7.2L20.3 7.1L20.8 6.6L21.4 6.9L21.9 6.5L22.1 6.7L22 6.8L22.3 7L22.1 7.3L22.9 7.5L22.9 7.7L22.5 8L22.7 8.3L22.3 8.1L21.2 8.8L20.5 10.9L19.8 10.8L19.9 11.5L19.7 11.7L19.6 12.4L19.4 12.4L19.1 11L18.6 11.7L18.3 11.2L18.4 10.9L18.9 10.7L19.1 10.1L19.3 10.1L19.1 10L17.3 9.8L17.2 9.1L16.9 9.2L16.7 8.9L16.3 8.9L16 9.1L16 9.4L16.6 9.8L16.3 9.9L15.9 10.3L16.4 10.6L16.3 11.1L16.6 11.5L16.7 12.5L16.2 12.5L16.1 12.7L16.1 12.3L15.8 12.7L15.2 12.9L15.2 13.5L14.7 14.1L13.7 14.6L13 15.4L11.6 16.5L11.7 16.8L10.9 17L10.7 17.5L10.5 17.3L10.2 17.5L10 18.2L10.2 19.5L9.8 20.7L9.8 21.8L9.4 21.9L9.1 22.5L9.3 22.6L8.8 22.8L8.2 23.6L7.4 22.9L6.8 21L6.3 20.3L5.8 18.5L5.1 17.3L4.4 12.5L4.8 12.2L4.3 12.2L4.1 13.1L3.1 13.5L1.8 12.3L2.6 12L3.1 11.5L2 11.8L1.1 11.1L1.6 10.9L1.6 10.6L2.6 10.7L3.4 10.5L3.1 9.5L2.7 9.4L2.7 8.9L2.2 8.7L2.2 8.3L2.8 7.6L3.1 7.9L3.9 7.7L4.3 7.1L4.8 6.8L5.1 6.1L6.1 5.2L5.9 5.1L6 4.6L6.6 4.3L5.3 3.6L5.1 2.6L5.6 2L5.3 1.8L5.3 1.6L4.4 1.3L4.9 0.7Z'/%3E%3C/svg%3E");
}

/* Andhra Pradesh — dissolved from its 14 districts. */
.tsp-state-desk__emblem--andhra {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M23.8 1.9L24 2L22.1 4.4L20.7 5.1L19.2 6.7L17.5 7.6L16.6 8.3L16.4 8.7L16.5 8.9L16.8 8.9L16.6 9.8L14.9 10.6L13.9 10.5L13.5 10.7L13.1 11.7L12.5 12.5L12.2 12.5L12.1 12L11.7 12L11 12.2L10.6 12.6L10.1 13.5L9.8 14.7L10 15.5L10.3 16L10.1 17.5L10.5 18.5L10.5 19.2L10.4 19.4L10 19.4L9.8 19.3L9.6 19.8L9.1 19.9L9 20.2L8.8 20.3L8.7 20L8.3 20.1L8.3 19.9L8 19.9L8 20.4L7.6 20.6L7.4 20.5L7.2 20.9L6.4 20.6L5.9 20.8L5.6 21L5.5 21.7L4.9 22.1L4.5 21.9L4.5 21.5L5.2 21L5.5 20.1L4.8 19.8L4.9 19.1L4.3 19.2L4.1 18.7L4.1 18.3L3.7 18.2L3.6 17.9L3.2 18.1L3 18.4L2.1 18.8L2 18.3L1.2 18.2L0.9 18.6L0.7 18.4L0.8 18.1L0.5 17.7L0.4 17.3L0.7 17.3L0.9 17.7L1.7 17.8L1.9 18.2L2 18L1.9 17.8L1.9 17.3L2.2 17.3L2.2 16.9L2 16.8L1.8 17L1.1 16.8L1 17.1L0.7 17.1L0.4 16.8L0.4 16.3L0 16L0.3 14.9L0 14.7L0.1 14.4L0.8 14.7L1 14.6L1.2 14.3L1.2 13.8L0.9 13.7L0.8 13.4L0.8 12.7L1 12.7L0.8 12.1L0.9 11.9L1.5 11.7L4.1 12.1L4.3 12L4.5 11.6L4.9 11.4L5.4 11.5L5.5 11.3L6 11.6L6.5 11.2L6.5 11L6.8 10.9L7.4 10.9L7.4 10L7.5 9.8L8 9.8L9.1 9.4L9.6 9.6L9.9 9.2L9.9 8.6L10.3 8.4L10.6 8.6L10.7 8.9L11.4 9.2L11.5 8.7L10.8 8.5L11.5 8L12.2 8.4L12.5 7.8L13.2 7.8L13.3 7.5L13.6 7.4L13.6 7.2L12.7 6.7L12.4 6.2L12.7 6.1L12.9 6.2L13.2 5.8L13.5 6L14.6 5.9L15.8 5.2L16.5 5.4L16.8 4.9L16.7 4.7L16.8 4.1L17.2 3.7L17.5 4.2L17.5 4.5L18 4.3L18.2 4L18.6 4.3L18.9 4.1L18.7 3.4L19.1 2.9L19.4 3L20 2.6L19.7 2.3L19.8 2.2L20.1 2.4L20.2 2.1L20.7 1.9L21 2.5L21.1 2.2L21.4 2.8L21.8 2.8L22 3L22.7 2.9L23.3 2.1L23.5 2.2Z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M23.8 1.9L24 2L22.1 4.4L20.7 5.1L19.2 6.7L17.5 7.6L16.6 8.3L16.4 8.7L16.5 8.9L16.8 8.9L16.6 9.8L14.9 10.6L13.9 10.5L13.5 10.7L13.1 11.7L12.5 12.5L12.2 12.5L12.1 12L11.7 12L11 12.2L10.6 12.6L10.1 13.5L9.8 14.7L10 15.5L10.3 16L10.1 17.5L10.5 18.5L10.5 19.2L10.4 19.4L10 19.4L9.8 19.3L9.6 19.8L9.1 19.9L9 20.2L8.8 20.3L8.7 20L8.3 20.1L8.3 19.9L8 19.9L8 20.4L7.6 20.6L7.4 20.5L7.2 20.9L6.4 20.6L5.9 20.8L5.6 21L5.5 21.7L4.9 22.1L4.5 21.9L4.5 21.5L5.2 21L5.5 20.1L4.8 19.8L4.9 19.1L4.3 19.2L4.1 18.7L4.1 18.3L3.7 18.2L3.6 17.9L3.2 18.1L3 18.4L2.1 18.8L2 18.3L1.2 18.2L0.9 18.6L0.7 18.4L0.8 18.1L0.5 17.7L0.4 17.3L0.7 17.3L0.9 17.7L1.7 17.8L1.9 18.2L2 18L1.9 17.8L1.9 17.3L2.2 17.3L2.2 16.9L2 16.8L1.8 17L1.1 16.8L1 17.1L0.7 17.1L0.4 16.8L0.4 16.3L0 16L0.3 14.9L0 14.7L0.1 14.4L0.8 14.7L1 14.6L1.2 14.3L1.2 13.8L0.9 13.7L0.8 13.4L0.8 12.7L1 12.7L0.8 12.1L0.9 11.9L1.5 11.7L4.1 12.1L4.3 12L4.5 11.6L4.9 11.4L5.4 11.5L5.5 11.3L6 11.6L6.5 11.2L6.5 11L6.8 10.9L7.4 10.9L7.4 10L7.5 9.8L8 9.8L9.1 9.4L9.6 9.6L9.9 9.2L9.9 8.6L10.3 8.4L10.6 8.6L10.7 8.9L11.4 9.2L11.5 8.7L10.8 8.5L11.5 8L12.2 8.4L12.5 7.8L13.2 7.8L13.3 7.5L13.6 7.4L13.6 7.2L12.7 6.7L12.4 6.2L12.7 6.1L12.9 6.2L13.2 5.8L13.5 6L14.6 5.9L15.8 5.2L16.5 5.4L16.8 4.9L16.7 4.7L16.8 4.1L17.2 3.7L17.5 4.2L17.5 4.5L18 4.3L18.2 4L18.6 4.3L18.9 4.1L18.7 3.4L19.1 2.9L19.4 3L20 2.6L19.7 2.3L19.8 2.2L20.1 2.4L20.2 2.1L20.7 1.9L21 2.5L21.1 2.2L21.4 2.8L21.8 2.8L22 3L22.7 2.9L23.3 2.1L23.5 2.2Z'/%3E%3C/svg%3E");
}

/* Telangana — dissolved from its 34 districts. */
.tsp-state-desk__emblem--telangana {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M7.8 2.6L8.3 3L8.9 3L10 3.2L10.2 3.6L10.6 3.8L10.5 4.2L11.2 4.3L11.6 4.6L11.9 4.1L12.4 4.1L12.9 4.5L14 4L14.9 4.6L15.1 5.1L14.9 6L14.6 6.3L14.9 6.6L15 7.4L14.8 7.6L15.7 8.3L16.4 8.1L16.8 8.6L17.2 8.5L18.1 9.1L18.5 10L18.5 10.6L18.9 10.5L19 10.8L19.5 10.7L19.4 11.2L19.6 12.3L20 12.4L19.9 12.6L19.5 12.4L19.1 12.6L19.2 13.1L19.7 13.7L21 14.2L20.8 14.6L20.4 14.6L20.4 15L19.6 15.2L19.3 15L19 15.3L19 15.7L18.9 15.9L17.7 15.3L16.8 16.1L17.5 16.2L17.8 16.4L17.7 17.1L16.6 16.6L16.5 16.1L16 15.9L15.5 16.1L15.4 16.4L15.4 17.2L15 17.7L14.2 17.3L12.8 17.8L12.6 18L11.9 18L11.7 18.4L11.7 19.6L11.5 19.7L10.9 19.5L10.5 19.7L10.3 19.8L10.4 20.1L9.6 20.6L9 20.3L8.8 20.5L8.1 20.3L7.5 20.6L7.1 21.3L6.7 21.4L5.9 21.1L5.3 21.2L4.3 21L4.2 19.6L4.6 19.1L4.1 18.9L3.7 18.9L3.3 18.8L3 18.5L3.8 18.3L4 17.9L3.9 17.3L4.1 17L4 16.3L4.2 15.9L4 15.5L3.6 15.3L3.6 15L4.2 14.1L5 13.7L3.9 13.3L4 12.8L4.8 11.6L4.4 11.2L4.6 11L4.5 10.5L4.6 10.1L4.4 10L4.3 9.7L4.6 9.4L4.6 8.9L5.2 8.8L5.2 8.3L5.5 8.2L5.7 7.7L6.1 7.5L5.7 7.2L5.5 6.5L5.8 6L5.8 5.4L6.1 5.2L6.6 5.6L7.1 5.7L7.3 4.8L7.8 4.5L7.6 3.6L7.9 3.4L8 3.2Z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M7.8 2.6L8.3 3L8.9 3L10 3.2L10.2 3.6L10.6 3.8L10.5 4.2L11.2 4.3L11.6 4.6L11.9 4.1L12.4 4.1L12.9 4.5L14 4L14.9 4.6L15.1 5.1L14.9 6L14.6 6.3L14.9 6.6L15 7.4L14.8 7.6L15.7 8.3L16.4 8.1L16.8 8.6L17.2 8.5L18.1 9.1L18.5 10L18.5 10.6L18.9 10.5L19 10.8L19.5 10.7L19.4 11.2L19.6 12.3L20 12.4L19.9 12.6L19.5 12.4L19.1 12.6L19.2 13.1L19.7 13.7L21 14.2L20.8 14.6L20.4 14.6L20.4 15L19.6 15.2L19.3 15L19 15.3L19 15.7L18.9 15.9L17.7 15.3L16.8 16.1L17.5 16.2L17.8 16.4L17.7 17.1L16.6 16.6L16.5 16.1L16 15.9L15.5 16.1L15.4 16.4L15.4 17.2L15 17.7L14.2 17.3L12.8 17.8L12.6 18L11.9 18L11.7 18.4L11.7 19.6L11.5 19.7L10.9 19.5L10.5 19.7L10.3 19.8L10.4 20.1L9.6 20.6L9 20.3L8.8 20.5L8.1 20.3L7.5 20.6L7.1 21.3L6.7 21.4L5.9 21.1L5.3 21.2L4.3 21L4.2 19.6L4.6 19.1L4.1 18.9L3.7 18.9L3.3 18.8L3 18.5L3.8 18.3L4 17.9L3.9 17.3L4.1 17L4 16.3L4.2 15.9L4 15.5L3.6 15.3L3.6 15L4.2 14.1L5 13.7L3.9 13.3L4 12.8L4.8 11.6L4.4 11.2L4.6 11L4.5 10.5L4.6 10.1L4.4 10L4.3 9.7L4.6 9.4L4.6 8.9L5.2 8.8L5.2 8.3L5.5 8.2L5.7 7.7L6.1 7.5L5.7 7.2L5.5 6.5L5.8 6L5.8 5.4L6.1 5.2L6.6 5.6L7.1 5.7L7.3 4.8L7.8 4.5L7.6 3.6L7.9 3.4L8 3.2Z'/%3E%3C/svg%3E");
}

/* Short red rule UNDER the desk name, as in the reference.
 *
 * v1.10.172: it was rendering ABOVE the header. The bar is the desk's own
 * `::before`, so it is the first child in DOM order, and its `order:-1` did
 * nothing at all while the desk was `display:block` — order only applies to a
 * flex/grid item. Measured on the approved reference: the rule sits at y167-169
 * with the emblem glyph occupying y125-158, i.e. clearly beneath the heading row.
 *
 * Now that the desk is a flex column, `order` is live — so the HEADER is pulled
 * ahead of the bar instead, which leaves the bar between the header and the lead
 * image where the design puts it. Ordering the header rather than the bar keeps
 * the bar at its natural `order: 0` alongside the viewport and footer, so the
 * remaining children stay in DOM order. */
.tsp-news-grid--state-desk::before {
	content: "";
	display: block;
	width: 46px;
	height: 3px;
	/* The left margin matches the header's inset below, so the rule keeps
	   sitting under the emblem rather than staying pinned to the card border. */
	margin: 0 0 12px var(--tsp-desk-inset);
	background: var(--ts-red, #C8102E);
}
.tsp-news-grid--state-desk .tsp-nav-header { order: -1; }
/* The carousel keeps its natural height; the footer takes up the slack — see the
   `margin-top:auto` in the controls rule below, which is where the footer's other
   spacing already lives so the two cannot drift apart. */
.tsp-news-grid--state-desk .tsp-nav-viewport { flex: 0 0 auto; }

/* Desk-level View All sits on the heading line. */
.tsp-news-grid--state-desk .tsp-nav-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	/* 12px before the inset. Taking 20px out of the header for the inset left
	   "ANDHRA PRADESH" — the longest of the three names, 221.8px against
	   National's 123px — exactly 4.1px short of one line, so it wrapped to two
	   and dropped that desk's whole interior 9px below its siblings'. The room is
	   taken back from the header's own gaps rather than from the inset or the
	   heading type, neither of which should move: 4px here and 6px off the View
	   All padding gives ~6px of slack at the desktop desk width.
	   The emblem-to-title gap is deliberately NOT part of that trade — it is the
	   one distance that would visibly loosen the icon from its title. */
	gap: 8px;
	margin: 0;
	/* Padding on the header, so the emblem and its title move inward together as
	   one unit and View All comes in by the same amount from the right. Insetting
	   the emblem on its own would break its relationship with the title. */
	padding-inline: var(--tsp-desk-inset);
}
.tsp-news-grid--state-desk .tsp-nav-viewall,
.tsp-news-grid--state-desk .tsp-state-desk__viewall {
	font-family: var(--ts-ui, inherit);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--ts-red, #C8102E);
	text-decoration: none;
	white-space: nowrap;
}
/* The desk-header VIEW ALL from the reference. A SEPARATE class from the footer's
   MORE <DESK> link even though both point at the same archive: the two sit in
   different places in the design and the footer link carries the row chrome
   (border-top, space-between) that this one must not inherit. Padding gives it a
   comfortable tap target without moving the text off the heading baseline. */
.tsp-news-grid--state-desk .tsp-state-desk__viewall {
	flex: 0 0 auto;
	display: inline-block;
	/* Left padding trimmed from 8px to 2px to give the longest desk name its line
	   back after the header inset; the 8px header gap now provides that
	   separation. Vertical padding is untouched — it is the tap target. */
	padding: 6px 0 6px 2px;
}
.tsp-news-grid--state-desk .tsp-state-desk__viewall:hover,
.tsp-news-grid--state-desk .tsp-state-desk__viewall:focus-visible {
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* ---------------------------------------------------------------- grid ---- */

/* THE DESK OWNS ITS OWN ROW LAYOUT — and has to say so twice to keep it.
 *
 * v1.10.172. This rule was `.tsp-news-grid--state-desk .tsp-news-grid__items`
 * (0,2,0) and was LOSING, which is what made the whole section too tall. The
 * winner was the shared mobile tier near the top of this file:
 *
 *   @container (max-width:520px){
 *     .tsp-news-grid[class*='tsp-news-grid--m-'] .tsp-news-grid__items{
 *       display:grid; grid-template-rows:none; gap:22px } }
 *
 * at (0,3,0) — an attribute selector counts as a class. Two things had to be
 * true at once for it to reach a DESKTOP desk, and both were:
 *
 *   1. the desk carries `tsp-news-grid--m-state-desk`, so `[class*='--m-']`
 *      matches it; and
 *   2. `.tsp-news-grid--state-desk` declares `container-type: inline-size`, so
 *      that 520px query is measured against THE DESK, not the viewport — and a
 *      desk is ~369px wide inside a 1600px page. The mobile tier was therefore
 *      permanently on at every width.
 *
 * The damage was not the `display:grid` itself but what followed from it: the
 * rows became grid tracks with `align-content: normal`, which computes to
 * STRETCH, and `.tsp-nav-page` has a fixed height so every page in the carousel
 * is equal. So the leftover height was distributed into the rows — measured at
 * 124px each where the content needs ~86px — plus a 22px gap the desk never
 * asked for. Hence "supporting rows stretching and creating large empty space".
 *
 * Fixed by specificity, not by `!important` and not by touching the shared
 * mobile tier (which other presets rely on): `.tsp-news-grid` is added so this
 * is also (0,3,0) and, being later in the file, wins the tie. Flex column with
 * `gap: 0` restores natural row heights — the rows carry their own padding and
 * hairline, so a gap here would double-space them — and `justify-content:
 * flex-start` states the intent explicitly: leftover height collects at the
 * bottom of the desk as quiet space instead of being shared out among rows.
 */
.tsp-news-grid.tsp-news-grid--state-desk .tsp-news-grid__items,
.tsp-news-grid.tsp-news-grid--state-desk .tsp-nav-page {
	display: flex;
	flex-direction: column;
	gap: 0;
	justify-content: flex-start;
}

/* LEAD — 16:9 picture, red kicker, serif headline, deck, relative time. */
.tsp-news-grid--state-desk .tsp-news-card.is-lead { display: block; }
.tsp-news-grid--state-desk .tsp-news-card.is-lead .tsp-news-card__media {
	/* `width:auto` rather than `100%`, so the inset comes out of the width instead
	   of pushing the image past the card edge. The box is block-level, so auto
	   fills whatever the margins leave.
	   `aspect-ratio` still owns the height, so 16:9 is exact at every width — the
	   image is simply ~20px narrower and therefore ~11px shorter than before,
	   which is inherent to insetting it and is the only dimension that moves.
	   `object-fit: cover` on the img is untouched. */
	width: auto;
	margin-inline: var(--tsp-desk-inset);
	aspect-ratio: 16 / 9;
	overflow: hidden;
	border-radius: 4px;
	margin-bottom: 12px;
}
.tsp-news-grid--state-desk .tsp-news-card__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform .3s ease;
}
.tsp-news-grid--state-desk .tsp-news-card.is-lead .tsp-eb-category {
	display: block;
	margin: 0 0 6px;
	font-family: var(--ts-ui, inherit);
	font-size: 10.5px;
	font-weight: 700;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: var(--ts-red, #C8102E);
}
.tsp-news-grid--state-desk .tsp-news-card.is-lead .tsp-story-title {
	margin: 0 0 8px;
	font-family: var(--ts-display, Georgia, serif);
	font-weight: 700;
	font-size: clamp(17px, 4.6cqw, 21px);
	line-height: 1.22;
	color: var(--ts-ink, #16181F);
	display: -webkit-box;
	/* v1.10.425: 2 > 3. Two lines is the preferred outcome and four of six lead
	   headlines still land there — but the other two need three, and a two-line
	   ceiling was cutting them MID-WORD at 1366, 1440 and 1920. The owner's rule
	   is two preferred, three permitted; this is the "permitted" case, and the
	   card grows only for the headlines that actually need it. */
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.tsp-news-grid--state-desk .tsp-news-card.is-lead p {
	margin: 0 0 8px;
	font-family: var(--ts-ui, inherit);
	font-size: 12.5px;
	line-height: 1.5;
	color: var(--ts-muted, #676E7B);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
/* Times carry the reference's small clock. Drawn as a background rather than an
   inline glyph so the markup stays plain text: a screen reader reads the date and
   is not told about a decorative icon. `em`-based position keeps it on the text's
   optical centre if the size ever changes. */
.tsp-news-grid--state-desk .tsp-news-card time {
	display: block;
	padding-left: 15px;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='%23676E7B' stroke-width='2'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5.4l3.4 2' stroke-linecap='round'/%3E%3C/g%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-size: 11px 11px;
	background-position: left 0.22em;
	font-family: var(--ts-ui, inherit);
	font-size: 11px;
	color: var(--ts-muted, #676E7B);
}

/* Reference order in the lead is KICKER, HEADLINE, EXCERPT, TIME. The shared
   card markup emits `<time>` before the excerpt `<p>` — deliberately, because
   most presets show a time and no excerpt — so this preset reorders in CSS
   rather than branching the markup every other preset depends on. Flex column +
   `order` is the whole change; nothing moves in the DOM, so the reading order a
   screen reader announces still matches the visual order. */
.tsp-news-grid--state-desk .tsp-news-card.is-lead .tsp-news-card__content {
	display: flex;
	flex-direction: column;
}
.tsp-news-grid--state-desk .tsp-news-card.is-lead time {
	order: 1;
	margin: 0;
}
/* The lead's closing rule is inset with the same treatment as the row dividers
   below it — otherwise it would be the one hairline in the desk still running
   into the card border, which is the inconsistency this pass exists to remove.
   Transparent border keeps the box height, pseudo-element draws the visible rule. */
.tsp-news-grid--state-desk .tsp-news-card.is-lead {
	position: relative;
	padding-bottom: 12px;
	border-bottom: 1px solid transparent;
	margin-bottom: 12px;
}
.tsp-news-grid--state-desk .tsp-news-card.is-lead::after {
	content: "";
	position: absolute;
	left: var(--tsp-desk-inset);
	right: var(--tsp-desk-inset);
	bottom: 0;
	height: 1px;
	background: var(--tsp-desk-rule);
}

/* SUPPORTING — landscape thumb on the LEFT, headline + time on the right.

   v1.10.427: the thumbnail moved from column 2 to column 1. The right-hand
   placement was never in the markup — the template emits media then content,
   like every other card — it was THIS rule reversing them with an explicit
   grid-column. Trending, Sports, More From and the Watch list all read
   thumbnail-first, so the three desks were the odd component out. One rule
   fixes all three, because National, Andhra Pradesh and Telangana are the same
   preset.
   Sans-serif here on purpose: the lead is the only serif in the desk, which is
   what makes the hierarchy scan. */
.tsp-news-grid--state-desk .tsp-news-card:not(.is-lead) > a {
	display: grid;
	grid-template-columns: 96px minmax(0, 1fr);
	align-items: center;
	gap: 12px;
	text-decoration: none;
}
.tsp-news-grid--state-desk .tsp-news-card:not(.is-lead) .tsp-news-card__media {
	grid-column: 1;
	grid-row: 1;
	width: 96px;
	height: 64px;
	overflow: hidden;
	border-radius: 4px;
	background: #eef1f4;
}
.tsp-news-grid--state-desk .tsp-news-card:not(.is-lead) .tsp-news-card__content {
	grid-column: 2;
	grid-row: 1;
	min-width: 0;
	/* The shared card rule pads this box by 10px all round. In a compact row the
	   row itself already owns the vertical rhythm (11px top and bottom, plus its
	   hairline), so that padding was adding 20px of height per row on top of it —
	   measured 101px of content in an 86px row. Horizontal padding goes too: the
	   row is a grid, and its 12px column gap is what separates text from thumb. */
	padding: 0;
}
/* No kicker in a supporting row. The approved reference shows headline + time
   only; the chip belongs to the LEAD, where it is the desk's one piece of
   colour. Emitting it here also cost ~17px a row and repeated the desk's own
   name back at the reader ("TELANGANA" inside the Telangana desk). Hidden rather
   than removed from the markup because `showCategory` is one block attribute
   shared by the lead and the rows, and the lead genuinely wants it. */
.tsp-news-grid--state-desk .tsp-news-card:not(.is-lead) .tsp-eb-category {
	display: none;
}
/* v1.10.422: display serif. The desk's LEAD card was already display type and
   the supporting cards beside it were Inter — the same split as In Pictures and
   Watch, inside the "Across the Telugu States" strip. */
.tsp-news-grid--state-desk .tsp-news-card:not(.is-lead) .tsp-story-title {
	margin: 0 0 5px;
	font-family: var(--ts-display, Georgia, serif);
	font-weight: 700;
	/* v1.10.423: dense tier token, up from a hardcoded 13px.
	 *
	 * v1.10.424 — the clamp goes 2 > 3, and this is the severe one. Measured on
	 * staging at 1366 and 1440: TWELVE of thirteen supporting headlines were
	 * cut, losing roughly 335 characters between them. Two lines is simply not
	 * enough for a real headline in a ~380px desk column, and no font size fixes
	 * that — the sweep showed 14.5, 15, 15.5 and 16px all cutting twelve.
	 *
	 * Three lines takes it to two of thirteen and ~46 characters, for +58 to
	 * +73px of page height, under 1%. That trade is the whole point: the brief
	 * is explicit that truncation must not be solved by hiding more text. */
	font-size: var(--ts-title-dense);
	line-height: var(--ts-lh-dense);
	color: var(--ts-ink, #16181F);
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
/* Supporting rows take the same inset as the header and the lead image, so the
   desk has ONE content line from its border instead of three different ones.
   The row is the right place for it: `.tsp-news-card__content` was zeroed above,
   so this cannot double up, and the 96px thumbnail keeps its size — the text
   column absorbs the 20px (367.3 - 20 - 12 gap - 96 thumb = 239.3px of headline).
   Measured before the change: headline and time both sat 1px from the card edge,
   i.e. against the border. Nothing was actually clipped — scrollWidth equalled
   clientWidth and both bleeds were 0 — but text touching a border reads as if it
   were, which is what this fixes. */
.tsp-news-grid--state-desk .tsp-news-card:not(.is-lead) {
	position: relative;
	padding: 11px var(--tsp-desk-inset);
	/* The hairline is drawn by the pseudo-element below so it can be inset with
	   the content. The border stays in the box model as TRANSPARENT rather than
	   being removed, so every row keeps the exact height it had and no vertical
	   spacing moves. */
	border-bottom: 1px solid transparent;
}
/* Inset divider, matching the approved reference: measured there, the card spans
   x30-492 and the hairline runs x49-477 — inset on both sides, and starting at
   the same x as the supporting text. A rule that runs into the card border is
   the thing the reference specifically avoids. */
.tsp-news-grid--state-desk .tsp-news-card:not(.is-lead)::after {
	content: "";
	position: absolute;
	left: var(--tsp-desk-inset);
	right: var(--tsp-desk-inset);
	bottom: 0;
	height: 1px;
	background: var(--tsp-desk-rule);
}
.tsp-news-grid--state-desk .tsp-news-card:not(.is-lead):last-child { border-bottom: 0; }
.tsp-news-grid--state-desk .tsp-news-card:not(.is-lead):last-child::after { content: none; }

/* ------------------------------------------------------------- controls ---- */

/* Footer: paging arrows LEFT, MORE <DESK> RIGHT, as in the reference. Both come
   from Section_Navigation, composed into this one row by render_news_grid() for
   this preset — `space-between` then places them without either side needing to
   know the other exists.
   `margin-top: auto` is the bottom anchor for the desk's flex column: it eats
   whatever height a shorter desk did not use, so Telangana's footer lines up
   with National's instead of its rows stretching to meet it. */
.tsp-news-grid--state-desk .tsp-nav-footer,
.tsp-news-grid--state-desk .tsp-nav-viewall-row {
	position: relative;
	display: flex;
	align-items: center;
	gap: 12px;
	margin-top: auto;
	/* Same inset as the rows above: the arrows come in from the left and the
	   MORE link from the right, both landing on the desk's one content line.
	   Vertical padding is unchanged, so footer height and alignment do not move. */
	padding: 12px var(--tsp-desk-inset) 0;
	/* Transparent for the same reason as the row dividers — the box model keeps
	   its 1px so nothing shifts vertically, and the visible rule is the inset
	   pseudo-element below. */
	border-top: 1px solid transparent;
}
.tsp-news-grid--state-desk .tsp-nav-footer::before,
.tsp-news-grid--state-desk .tsp-nav-viewall-row::before {
	content: "";
	position: absolute;
	left: var(--tsp-desk-inset);
	right: var(--tsp-desk-inset);
	top: 0;
	height: 1px;
	background: var(--tsp-desk-rule);
}
/* The MORE link hugs the RIGHT edge whether or not this desk has arrows.
   `space-between` alone was wrong: Telangana renders one page, so it has no
   arrows, and its single child was being pushed to the LEFT while National's and
   Andhra Pradesh's sat right — the three MORE links have to line up. `margin-left:
   auto` takes the free space from the link's left in both cases, so no rule has
   to know whether arrows exist. */
.tsp-news-grid--state-desk .tsp-nav-viewall {
	margin-left: auto;
	/* The shared nav link carries a red underline; the reference's MORE link is
	   plain red type, and the desk footer already has its own rule above it. */
	border-bottom: 0;
}
.tsp-news-grid--state-desk .tsp-nav-btn {
	width: var(--tsp-desk-arrow);
	height: var(--tsp-desk-arrow);
	border-radius: 50%;
	border: 1px solid var(--tsp-desk-rule);
	background: #fff;
	color: var(--ts-ink, #16181F);
}
.tsp-news-grid--state-desk .tsp-nav-btn:hover:not(:disabled),
.tsp-news-grid--state-desk .tsp-nav-btn:focus-visible:not(:disabled) {
	background: var(--ts-red, #C8102E);
	border-color: var(--ts-red, #C8102E);
	color: #fff;
}
.tsp-news-grid--state-desk .tsp-nav-btn:disabled { opacity: .35; }
@media (pointer: coarse) {
	.tsp-news-grid--state-desk { --tsp-desk-arrow: 44px; }
}

/* --------------------------------------------------------------- hover ---- */

.tsp-news-grid--state-desk .tsp-news-card a:hover .tsp-story-title,
.tsp-news-grid--state-desk .tsp-news-card a:focus-visible .tsp-story-title {
	color: var(--ts-red, #C8102E);
}
.tsp-news-grid--state-desk .tsp-news-card a:hover .tsp-news-card__media img {
	transform: scale(1.03);
}

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

/* A desk stacked full width can afford a larger lead and a bigger thumb. */
@container (min-width: 560px) {
	.tsp-news-grid--state-desk .tsp-news-card.is-lead .tsp-story-title { font-size: clamp(19px, 2.6cqw, 24px); }
	.tsp-news-grid--state-desk .tsp-news-card:not(.is-lead) > a { grid-template-columns: 128px minmax(0, 1fr); }
	.tsp-news-grid--state-desk .tsp-news-card:not(.is-lead) .tsp-news-card__media { width: 128px; height: 78px; }
}
/* Very narrow: keep the rows readable rather than squeezing a thumbnail in. */
@container (max-width: 300px) {
	.tsp-news-grid--state-desk .tsp-news-card:not(.is-lead) > a { grid-template-columns: minmax(0, 1fr); }
	.tsp-news-grid--state-desk .tsp-news-card:not(.is-lead) .tsp-news-card__media { display: none; }
}

@media (prefers-reduced-motion: reduce) {
	.tsp-news-grid--state-desk .tsp-news-card__media img { transition: none; }
	.tsp-news-grid--state-desk .tsp-news-card a:hover .tsp-news-card__media img { transform: none; }
}

/* ==========================================================================
   v1.10.166 — "Across the Telugu States" parent composition
   --------------------------------------------------------------------------
   Everything is scoped to `.tsp-across-states`, the pattern's own wrapper
   class. Deliberately NOT a bare `.wp-block-columns` rule and NOT a `:has()`
   probe: both would reach other column blocks on the same page.

   RESPONSIVE MODEL. The desks are laid out from the WRAPPER's width, never
   from a desk's own width. A desk is ~370px inside a 1600px desktop layout and
   ~728px stacked on a phone, so desk width says nothing about the device — that
   confusion is exactly what put the compact-row phone tier on desktop in
   v1.10.164. The wrapper is the container; the desk only styles its interior.
   ========================================================================== */

.tsp-across-states {
	--tsp-as-rule: #E4E1DA;
	--tsp-as-gap: 26px;
	container-type: inline-size;
	container-name: tsp-across;
	margin-block: 8px 0;
}

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

.tsp-across-states__head {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	align-items: end;
	gap: 8px 20px;
	padding-bottom: 11px;
	border-bottom: 1px solid var(--tsp-as-rule);
}
/* v1.10.172: was 22px here and still measured 24px to the desk row, because the
   theme puts `margin-bottom:24px` on block-level wrappers and its stylesheet
   loads after this one — equal specificity, so source order decided and the
   theme won. Scoping to the section makes this (0,2,0) and settles it without
   `!important`.
   On the approved reference the section rule sits at y104 with the desk cards
   beginning at ~y115: about 9px once the reference's 1.27x scale is removed. This
   stops deliberately short of that — the desks carry 16px of their own top
   padding, so 9px here would read as the rule touching the cards.

   v1.10.199: 14px -> 11px, matching the head's padding-bottom, so the rule stays
   centred between the subtitle and the desks. With the subtitle's stray 1.5em
   finally gone (see the note on `__sub`), the subtitle-to-desk measure was 28px;
   11px either side of the rule brings it to 22px, the requested 20-24px. */
.tsp-across-states .tsp-across-states__head {
	margin-bottom: 11px;
}
.tsp-across-states__head h2 {
	grid-column: 1;
	margin: 0;
	padding-left: 14px;
	border-left: 5px solid var(--ts-red, #C8102E);
	font-family: var(--ts-display, Georgia, serif);
	font-weight: 700;
	font-size: clamp(24px, 3cqw, 36px);
	line-height: 1.12;
	letter-spacing: -.01em;
	color: var(--ts-ink, #16181F);
}
/* v1.10.199: the `margin: 0` below never applied. Blocksy's layout rule
   `:is(.is-layout-flow, .is-layout-constrained) > :where(:not(h1..h6))` sets
   `margin-block-end: var(--theme-content-spacing)`, and `:where()` contributes
   nothing to specificity while `:is()` takes its most specific argument — so that
   rule is (0,1,0), exactly the same as this one, and its stylesheet loads later.
   Source order decided and the theme won, adding 1.5em (20.25px) under the
   subtitle. Identical to the failure the note above this block records for the
   head's own margin, and settled the same way: scoping to the section makes it
   (0,2,0). This is not a second override — it is the existing declaration finally
   taking effect. */
.tsp-across-states .tsp-across-states__sub {
	margin: 0;
}
.tsp-across-states__sub {
	grid-column: 1;
	margin: 0;
	padding-left: 19px; /* clears the accent rule so it aligns under the title */
	font-family: var(--ts-ui, system-ui, sans-serif);
	font-size: 13.5px;
	line-height: 1.4;
	color: var(--ts-muted, #676E7B);
}
.tsp-across-states__all {
	grid-column: 2;
	grid-row: 1 / span 2;
	align-self: center;
	margin: 0;
	text-align: right;
}
.tsp-across-states__all a {
	font-family: var(--ts-ui, system-ui, sans-serif);
	font-size: 11.5px;
	font-weight: 700;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: var(--ts-red, #C8102E);
	text-decoration: none;
	white-space: nowrap;
	/* Comfortable tap target without moving the text off its baseline. */
	display: inline-block;
	padding: 12px 2px;
}
.tsp-across-states__all a:hover,
.tsp-across-states__all a:focus-visible { text-decoration: underline; text-underline-offset: 3px; }

/* -------------------------------------------------------------- desks ----- */

.tsp-across-states .tsp-across-states__desks {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--tsp-as-gap);
	align-items: stretch;
}
/* Gutenberg gives each column a flex-basis; the grid owns the widths here, so
   the three desks are equal by construction and National cannot dominate. */
.tsp-across-states .tsp-across-states__desks > .wp-block-column {
	/* No !important needed: the pattern's columns carry no width attribute, so
	   Gutenberg emits no inline flex-basis here for this rule to fight. If an
	   editor later sets explicit column widths, those become inline styles and
	   will win — which is the correct outcome, since that is a deliberate
	   editorial choice rather than a default to override. */
	flex-basis: auto;
	min-width: 0;
	display: flex;
}
.tsp-across-states .tsp-across-states__desks > .wp-block-column > * { width: 100%; }

/* A desk whose category yields a single page renders no arrow controls, so its
   header row collapses from the 32px control height to the 26px heading height
   and the ENTIRE desk interior rides 6px above its siblings — measured on the
   QA page as Telangana's emblem, lead image, kicker and headline all sitting
   6px high against National and Andhra Pradesh.

   Reserving the control height on every desk fixes it at the source. The desks
   are equal by construction, so their header rows have to be too — matching
   heights by hand on a per-desk basis is what this composition exists to avoid.
   The header is already `align-items:center`, so the shorter heading centres
   into the reserved row and lands on its siblings' baseline.

   Scoped to this section: a lone state-desk block elsewhere has nothing to
   align to and keeps its tight header. */
.tsp-across-states .tsp-news-grid--state-desk .tsp-nav-header {
	min-height: var(--tsp-desk-arrow, 32px);
}

/* --------------------------------------------------------- tablet/mobile -- */

/* 1024 and below the three desks stop being readable side by side — the desk
   drops under ~300px, where the headline breaks to single words. Stacking is a
   deliberate choice here, not a wrap. Threshold is the WRAPPER's width.

   Specifically its CONTENT box: `container-type: inline-size` measures inside
   the padding, and the theme gives this wrapper 20px each side. So the flip is
   at a 1080px wrapper, not 1040 — measured, three columns down to 1081 and
   stacked at 1080. The wrapper's parents add no gutters, so that is also the
   viewport width. Every tablet at 1024 and below stacks, as intended; anything
   measuring the wrapper in devtools will read 1080, and both numbers are right. */
@container tsp-across (max-width: 1040px) {
	.tsp-across-states .tsp-across-states__desks { grid-template-columns: minmax(0, 1fr); gap: 30px; }
}

/* Phone: title and link SHARE the top row; the subtitle sits under both.
 *
 * v1.10.430 — this rule used to stack all three, on the reasoning that the link
 * would be squeezed onto the title line. That was true when the heading read
 * "Across India & the Telugu States". It stopped being true when the short
 * mobile label was introduced: the visible heading is now "Politics", and
 * measured on staging it is 80px wide against a 149px link —
 *
 *     320px  need 245 / avail 280   spare 35
 *     390px  need 245 / avail 350   spare 105
 *     430px  need 245 / avail 390   spare 145
 *
 * so it fits comfortably at every phone width, including 320. Stacking was
 * costing a whole 38px row of vertical space for nothing, and it read as
 * unfinished: a short title with an empty half-row beside it.
 *
 * The `a` keeps its 10px block padding, so the tap target is unchanged. */
@container tsp-across (max-width: 600px) {
	.tsp-across-states__head {
		grid-template-columns: auto minmax(0, 1fr);
		align-items: center;
		gap: 2px 12px;
	}
	.tsp-across-states__head h2 {
		grid-column: 1;
		grid-row: 1;
	}
	.tsp-across-states__sub {
		grid-column: 1 / -1;
		grid-row: 2;
	}
	.tsp-across-states__all {
		grid-column: 2;
		grid-row: 1;
		text-align: right;
		align-self: center;
	}
	.tsp-across-states__all a { padding: 10px 2px; }
	.tsp-across-states .tsp-across-states__desks { gap: 26px; }
}

@media (prefers-reduced-motion: reduce) {
	.tsp-across-states * { scroll-behavior: auto; }
}

/* ================================================ missing-media placeholder ==
   The last tier of the image chain in Video_Poster: what a card shows when the
   post has no featured image, no video poster and the site has nominated no
   fallback asset. It is reached by real, ordinary posts — post 3159 has no
   featured image at all — so it is part of the design, not an error state, and
   it used to be `background:#ddd`: a flat grey rectangle that reads as a broken
   image rather than as a story without a photograph.

   Deliberately restrained, and deliberately CSS-only. No HTTP request, nothing
   to upload, nothing to configure, and it cannot 404 the way a nominated asset
   can. The mark is an inline SVG data URI at a FIXED 38px rather than a
   percentage, so it stays the same quiet UI element on a 96x64 supporting thumb
   and on a 368x207 lead instead of scaling up into a logo on the big card.

   Geometry is inherited, not set: width/height are 100% from the base rule
   above, so the placeholder fills whatever box the preset gave it and the
   card's own aspect-ratio, radius and overflow still own the shape. A fallback
   card therefore occupies exactly the space a photographed one would, which is
   what keeps the desks aligned and the layout from shifting.

   Not applied where a surface already has its own treatment: the overlay news
   card and the Scope Verdict posters both set `background` on a two-class
   selector, so their dark gradients keep winning on specificity regardless of
   source order — those cards put text over the media and need the dark ground.
   ------------------------------------------------------------------------- */
.tsp-eb-placeholder {
	background-color: #F6F4EF;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='4' y='5' width='10' height='2.4' rx='1.2' fill='%23C8102E'/%3E%3Crect x='4' y='11' width='16' height='2' rx='1' fill='%23CFCAC0'/%3E%3Crect x='4' y='15' width='16' height='2' rx='1' fill='%23CFCAC0'/%3E%3Crect x='4' y='19' width='10' height='2' rx='1' fill='%23CFCAC0'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: center;
	background-size: 38px auto;
	box-shadow: inset 0 0 0 1px #E8E5DE;
}

/* ==========================================================================
   v1.10.201 — MOVIES SHOWCASE
   Reference: Images/movies_desktop.png, Images/movies_mobile.png

   A preset of its own rather than a restyle of `two-leads-four`. That preset's
   presentation is owned by a large block of Customizer CSS ("Batch 3A/3C/3F")
   which converts overlay tiles into title-below-image cards with roughly thirty
   `!important` declarations. Reproducing this reference on top of it would have
   meant out-importanting all of them. A new layout id, deliberately kept OUT of
   OVERLAY_LAYOUTS so it never carries `.tsp-news-card--overlay`, is matched by
   none of those rules — so everything below is plain CSS with no `!important`,
   and Politics/lead-two/lead-mosaic elsewhere keep the treatment they were given.

   Geometry is taken from the reference PNGs by measuring their tile boundaries,
   so the ratios are the reference's own rather than guesses:
     - four columns, gap 12px, leads spanning two -> at a 1200px container this
       reproduces the reference's 594px leads and 291px supports exactly
     - lead tile 5:4, caption sitting ON the image
     - supporting image 7:5, caption below it
   ========================================================================== */

.tsp-news-grid--movies-showcase .tsp-news-grid__items {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 12px;
	/* Stretch, not start: the four supporting cards are bordered boxes, so a
	   two-line headline next to a three-line one left their bottom edges ragged.
	   Stretch aligns them to the tallest in the row, which is content-driven —
	   no fixed height, and a longer headline simply makes the whole row taller.
	   The leads are unaffected: both are aspect-ratio driven at equal width, so
	   the row already fits them exactly. */
	align-items: stretch;
}

/* The rule the reference draws under the section header. On the nav header so
   it spans the full measure and sits between the header and the tiles. */
.tsp-news-grid--movies-showcase .tsp-nav-header {
	align-items: center;
	padding-bottom: 10px;
	margin-bottom: 14px;
	border-bottom: 2px solid var(--tsp-accent, #C8102E);
}

/* VIEW ALL and the arrows travel together on the heading line. */
.tsp-showcase__actions {
	display: flex;
	align-items: center;
	gap: 14px;
	flex: 0 0 auto;
}
.tsp-news-grid--movies-showcase .tsp-nav-viewall--showcase {
	font-family: var(--ts-font-ui, inherit);
	font-size: 12px;
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--tsp-accent, #C8102E);
	text-decoration: none;
	white-space: nowrap;
	border: 0;
	padding: 0;
}
.tsp-news-grid--movies-showcase .tsp-nav-viewall--showcase:hover,
.tsp-news-grid--movies-showcase .tsp-nav-viewall--showcase:focus-visible {
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* ---------------------------------------------------------------- leads --- */

.tsp-news-grid--movies-showcase .tsp-news-card.is-lead {
	grid-column: span 2;
	position: relative;
	border-radius: 8px;
	overflow: hidden;
	background: #0F1115;
}
.tsp-news-grid--movies-showcase .tsp-news-card.is-lead > a {
	display: block;
	position: relative;
	/* v1.10.204: 5/4 -> 7/5. The tile measured 574x459 at the 1200px container,
	   which read as too tall against the supporting row and the section below.
	   Four proportions were rendered and measured before choosing:

	     4/3    431px  -6.1%   lead +23% taller than a support   caption 44%
	     7/5    410px -10.7%   lead +17% taller                  caption 47%
	     3/2    383px -16.6%   lead  +9% taller                  caption 50%
	     16/10  359px -21.8%   lead  +2% taller                  caption 53%

	   7/5 is the only one inside the requested 8-12% band, and the hierarchy is
	   what settles it: by 3/2 the leads stand just 9% taller than the cards they
	   are meant to dominate, and by 16/10 they are level with them. At 7/5 the
	   caption still occupies under half the tile, so the photograph stays the
	   subject.

	   It is applied to the WIDE tier only — see the min-width rule below. A
	   support card's height is mostly its text block, which does not shrink as the
	   column narrows, while the lead is pure aspect and does. So the two converge
	   on their own as the container narrows: measured at a 984px container the
	   trim left the lead just 2% taller than a support, against 14% before it.
	   That is the flattening this ticket warns about, so the narrow half of the
	   desktop range keeps the taller 5/4 it already had. */
	aspect-ratio: 5 / 4;
	text-decoration: none;
	color: inherit;
}
/* The trim, where the section actually read as too tall. Above this the lead is
   ~574px wide and 7/5 gives it 410px against a 351px support: 17% taller, which
   holds the hierarchy while taking the requested ~10% off. */
@container (min-width: 1051px) {
	.tsp-news-grid--movies-showcase .tsp-news-card.is-lead > a { aspect-ratio: 7 / 5; }
}
.tsp-news-grid--movies-showcase .tsp-news-card.is-lead .tsp-news-card__media {
	position: absolute;
	inset: 0;
	margin: 0;
	aspect-ratio: auto;
	border-radius: 0;
	overflow: hidden;
}
.tsp-news-grid--movies-showcase .tsp-news-card.is-lead .tsp-news-card__media img,
.tsp-news-grid--movies-showcase .tsp-news-card.is-lead .tsp-eb-placeholder {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	display: block;
	transition: transform .5s ease;
}
/* The photograph stays dominant: the scrim covers only the lower half, and only
   as far as the caption needs to stay legible. */
.tsp-news-grid--movies-showcase .tsp-news-card.is-lead .tsp-news-card__media::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	background: linear-gradient(180deg, rgba(8, 9, 12, 0) 42%, rgba(8, 9, 12, .55) 66%, rgba(8, 9, 12, .92) 100%);
}
.tsp-news-grid--movies-showcase .tsp-news-card.is-lead .tsp-news-card__content {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 2;
	display: block;
	padding: 22px;
	background: none;
}
.tsp-news-grid--movies-showcase .tsp-news-card.is-lead .tsp-eb-category {
	display: inline-block;
	margin: 0 0 10px;
	padding: 4px 9px;
	border-radius: 3px;
	background: var(--tsp-accent, #C8102E);
	color: #fff;
	font-family: var(--ts-font-ui, inherit);
	font-size: 10px;
	font-weight: 800;
	letter-spacing: .1em;
	line-height: 1.4;
	text-transform: uppercase;
}
.tsp-news-grid--movies-showcase .tsp-news-card.is-lead .tsp-story-title {
	margin: 0;
	color: #fff;
	font-size: clamp(19px, 2.05cqw, 26px);
	font-weight: 700;
	line-height: 1.24;
	/* A measure, not a truncation: the reference leads run two to three lines and
	   a longer real headline simply takes a third or fourth. */
	max-width: 22em;
	overflow-wrap: break-word;
}
.tsp-news-grid--movies-showcase .tsp-news-card.is-lead .tsp-news-card__meta {
	display: block;
	margin-top: 10px;
	color: rgba(255, 255, 255, .82);
	font-family: var(--ts-font-ui, inherit);
	font-size: 12px;
	font-weight: 500;
	line-height: 1.4;
}
.tsp-news-grid--movies-showcase .tsp-news-card.is-lead:hover .tsp-news-card__media img,
.tsp-news-grid--movies-showcase .tsp-news-card.is-lead:focus-within .tsp-news-card__media img {
	transform: scale(1.04);
}
.tsp-news-grid--movies-showcase .tsp-news-card.is-lead > a:focus-visible {
	outline: 2px solid #fff;
	outline-offset: -4px;
	border-radius: 8px;
}

/* ----------------------------------------------------------- supporting --- */

.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) {
	grid-column: span 1;
	background: #fff;
	border: 1px solid var(--tsp-hairline, #E8E5DE);
	border-radius: 8px;
	overflow: hidden;
}
.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) > a {
	display: flex;
	flex-direction: column;
	height: 100%;
	text-decoration: none;
	color: inherit;
}
.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__media {
	position: relative;
	inset: auto;
	flex: 0 0 auto;
	width: 100%;
	margin: 0;
	aspect-ratio: 7 / 5;
	border-radius: 0;
	overflow: hidden;
}
.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__media img,
.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) .tsp-eb-placeholder {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	display: block;
}
.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__content {
	position: static;
	display: block;
	padding: 12px 13px 14px;
	background: none;
}
.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) .tsp-eb-category {
	display: block;
	margin: 0 0 6px;
	padding: 0;
	background: none;
	color: var(--tsp-accent, #C8102E);
	font-family: var(--ts-font-ui, inherit);
	font-size: 10px;
	font-weight: 800;
	letter-spacing: .1em;
	line-height: 1.4;
	text-transform: uppercase;
}
.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) .tsp-story-title {
	margin: 0;
	color: var(--ts-ink, #16181F);
	font-size: 15px;
	font-weight: 700;
	line-height: 1.32;
	/* v1.10.206: the same three-line clamp the phone list rows already carry.
	   Measured in the browser at a 1200px container, three of the four headlines
	   ran to three lines and one to four; because the cards are bordered boxes
	   stretched to equal height, that single headline pushed the whole row to
	   351px — 86% of the lead's height, where the reference sits at 79%. Clamping
	   the outlier lets the row settle at its natural three-line height and
	   restores the separation. No fixed height: the grid still derives the row
	   from its content, so a row whose headlines all fit in two lines is shorter
	   again. The leads are deliberately left unclamped. */
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__meta {
	display: block;
	margin-top: 8px;
	color: var(--ts-muted, #676E7B);
	font-family: var(--ts-font-ui, inherit);
	font-size: 12px;
	line-height: 1.4;
}

/* =============================================== intermediate and phone === */

/* Below ~900px of CONTAINER the four-across supporting row stops working: each
   support drops under ~200px, where the headline breaks to single words. The
   leads go full width and the supports pair up. Container-relative, so the
   preset behaves the same wherever it is placed. */
@container (max-width: 900px) {
	.tsp-news-grid--movies-showcase .tsp-news-grid__items {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
	.tsp-news-grid--movies-showcase .tsp-news-card.is-lead { grid-column: 1 / -1; }
	.tsp-news-grid--movies-showcase .tsp-news-card.is-lead > a { aspect-ratio: 16 / 9; }
}

/* Phone: the reference stacks two cinematic leads, then turns the four
   supporting stories into a compact newsroom list — thumbnail left, headline
   and byline right. Measured off movies_mobile.png: thumbnail ~104px on a 350px
   measure, rows ~16px apart, separated by a hairline rather than card chrome. */
@container (max-width: 560px) {
	.tsp-news-grid--movies-showcase .tsp-news-grid__items {
		grid-template-columns: minmax(0, 1fr);
		gap: 16px;
	}
	.tsp-news-grid--movies-showcase .tsp-news-card.is-lead > a { aspect-ratio: 4 / 3; }
	.tsp-news-grid--movies-showcase .tsp-news-card.is-lead .tsp-news-card__content { padding: 16px; }
	.tsp-news-grid--movies-showcase .tsp-news-card.is-lead .tsp-story-title { font-size: 19px; max-width: none; }

	/* Supports become rows: no card box, a hairline between them instead. */
	.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) {
		border: 0;
		border-radius: 0;
		background: none;
		border-top: 1px solid var(--tsp-hairline, #E8E5DE);
		padding-top: 16px;
	}
	.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) > a {
		display: grid;
		grid-template-columns: 104px minmax(0, 1fr);
		gap: 14px;
		align-items: start;
	}
	.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__media {
		aspect-ratio: 3 / 2;
		border-radius: 6px;
	}
	.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__content {
		padding: 0;
	}
	/* The kicker is the one thing the reference list rows drop — the section is
	   already titled Movies and every row would repeat it. */
	.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) .tsp-eb-category { display: none; }
	.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) .tsp-story-title {
		font-size: 15px;
		/* The list is a rhythm, and one five-line headline destroys it: measured on
		   the deployed page the rows ran 99px to 159px against a reference that
		   holds them even. Three lines keeps real headlines readable — the
		   reference's own run to two — while stopping a long one from turning its
		   row into a paragraph. The lead headlines are deliberately NOT clamped. */
		display: -webkit-box;
		-webkit-line-clamp: 3;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}
	.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__meta { margin-top: 6px; }
}

/* Very narrow: keep the thumbnail useful rather than letting it squeeze the
   headline into single words.

   300px of CONTAINER, not 360: the wrapper is the viewport less its gutters, so
   a 390px phone is a 350px container and a 360px phone is a 320px one. Keyed at
   360 this tier fired on both, giving them the 88px fallback thumbnail where the
   reference shows ~104px. 300 leaves it for the genuinely narrow case (a 320px
   phone is a 280px container). */
@container (max-width: 300px) {
	.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) > a {
		grid-template-columns: 88px minmax(0, 1fr);
		gap: 12px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.tsp-news-grid--movies-showcase .tsp-news-card.is-lead .tsp-news-card__media img { transition: none; }
	.tsp-news-grid--movies-showcase .tsp-news-card.is-lead:hover .tsp-news-card__media img,
	.tsp-news-grid--movies-showcase .tsp-news-card.is-lead:focus-within .tsp-news-card__media img { transform: none; }
}

/* ==========================================================================
   v1.10.216 — WATCH (video-grid, featured-row)
   References: Images/watch_desktop.png, Images/watch_mobile.png

   The preset already gave feature-left / list-right. What the reference asks for
   on top of it: the feature's caption moves ON to the image, and the four
   supporting videos become a 2x2 open grid instead of a stacked list.

   OMITTED ON PURPOSE: view counts, LIVE, EXCLUSIVE and "Streamed x ago" all
   appear in the reference and none of them has a field anywhere in the platform.
   They are left out rather than faked. Duration keeps its existing gate, so a
   video without `_tsp_video_duration` simply shows no badge and no placeholder.

   Everything is scoped to `.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row`, so no other block and
   no frozen section can be reached. No !important.
   ========================================================================== */

/* ------------------------------------------------- desktop composition ----

   v1.10.225 — the approved desktop redesign (Images/watch_desktop.png).

   What changed, and why the previous composition is replaced outright rather
   than overridden again: v1.10.216 gave the feature `height:100%` with
   `aspect-ratio:auto` and a 340px floor so it could stretch to the height of a
   2x2 support grid. That is what made it a giant poster — measured 906x566 at
   1600 (the media overflowing its own 592px column and being clipped), and
   1159x724 inside a 1540px-tall section at 1024. Stacking a sixth override on
   that would have left the stretch rules in place and fought them; the block is
   rewritten to the new architecture instead.

   The reference's own geometry, read off the file: it is horizontally stretched
   by ~1.18 (its support thumbnails measure 223x106, and 223/1.18 = 189, which
   with the same height is exactly 16:9 — the ratio a YouTube thumbnail actually
   is). Undoing that stretch, the mockup maps almost exactly onto the 1200px
   content measure this site already uses:

       feature image   631 x 283   -> 2.23:1, so 21/9 (the ratio the base preset
                                      already declares for this element)
       support thumb   189 x 106   -> 16/9 exactly
       columns         631 / 528 with a 30px gap  -> 1.2fr / 1fr
       feature block   391 tall vs support column 429 — balanced, feature
                       slightly shorter, which is why it is NOT stretched here

   Cascade note: CSS.getMatchedStylesForNode on the items grid, the feature media
   and the support link returns rules from blocks.css only — no Customizer or
   theme rule reaches this section, so these values land without a fight.
   ---------------------------------------------------------------------------- */

@container (min-width: 861px) {

	/* Two columns, not three. The 2x2 support grid is gone: the supports are a
	   single stacked column of horizontal rows, so they auto-place down column 2
	   and the feature holds column 1. The base preset's `has-N` rules already
	   span the feature across the right number of rows, so no span is restated
	   here — only `align-self:start`, which is what stops it stretching. */
	/* Row gap MUST be zero. The supports are rows of one grid, so a `gap`
	   shorthand puts 30px between each of them on top of their own padding and
	   divider — measured, that pushed the support column 161px per row against a
	   131px row, and left a 198px hole under the feature. The rows carry their
	   own separation; only the two columns need a gap. */
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-grid__items {
		grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
		gap: 0 30px;
		align-items: start;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row.has-5 .tsp-video-card.is-featured,
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured {
		grid-column: 1;
		align-self: start;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) {
		grid-column: 2;
	}

	/* --- the feature: landscape image, caption BELOW it --- */

	/* Every stretch/overlay declaration from v1.10.216 is unwound explicitly:
	   the link stops being a positioned, clipping box and the media stops
	   filling it. Unwinding by hand rather than by shorthand keeps it obvious
	   what is being answered. */
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured .tsp-video-card__link {
		position: static;
		display: block;
		height: auto;
		border-radius: 0;
		overflow: visible;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured .tsp-video-card__media {
		height: auto;
		min-height: 0;
		margin: 0 0 12px;
		border-radius: 10px;
		aspect-ratio: 21 / 9;
	}

	/* The scrim existed only to make white caption text legible on the image.
	   With the caption below the image there is nothing to make legible, and a
	   gradient over the photograph would now be pure decoration. */
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured .tsp-video-card__media::after {
		display: none;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured .tsp-video-card__body {
		position: static;
		padding: 0;
	}

	/* Back to ink on a light surface. The size is fixed rather than the old
	   container-relative clamp: at 21/9 the headline no longer has to hold its
	   own against a full-bleed image, and 21px sits in the brief's 20-22px. */
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured h3 {
		margin: 9px 0 0;
		color: var(--tsp-title-color, inherit);
		font-size: 21px;
		line-height: 1.3;
		font-weight: 700;
		display: -webkit-box;
		-webkit-line-clamp: 3;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured .tsp-video-card__meta {
		color: var(--ts-muted, #676E7B);
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured .tsp-video-card__play {
		width: 64px;
		height: 64px;
		top: 50%;
		z-index: 2;
	}

	/* --- the four supports: horizontal editorial rows --- */

	/* 188px against a ~528px column is the reference's 36% once its horizontal
	   stretch is undone, and at 16/9 that thumbnail is 106px tall — which is what
	   sets the row height, since the chip, a three-line headline and the date
	   together come to a little less. */
	/* Padding is 4px, not 7px. Measured, the row is set by its TEXT column at
	   116px, not by the 106px thumbnail, so every px here is a px of the 108px
	   hole that was left under the feature. */
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__link {
		display: grid;
		grid-template-columns: 188px minmax(0, 1fr);
		gap: 14px;
		align-items: start;
		padding: 4px 0;
		border-top: 1px solid var(--tsp-hairline, #E8E5DE);
	}

	/* The chip is inline-block, so it sits on a line box that is taller than the
	   chip itself — 5px of leading above it and a descender gap below, none of it
	   visible, all of it row height. As a block it contributes only its own box.
	   Support rows only: the feature's chip is fine where it is. */
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-eb-category {
		display: block;
		width: fit-content;
	}

	/* `:not(.is-featured):first-of-type` — inherited from the base preset — can
	   never match: first-of-type among the articles IS the feature, which the
	   :not() then excludes. So the top support row has always drawn a divider
	   with nothing above it. The adjacent sibling selector actually names "the
	   support right after the feature". */
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured + .tsp-video-card .tsp-video-card__link {
		border-top: 0;
		padding-top: 0;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__media {
		margin: 0;
		border-radius: 7px;
		aspect-ratio: 16 / 9;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__play {
		width: 36px;
		height: 36px;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__play::after {
		border-width: 6px 0 6px 10px;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) h3 {
		margin: 4px 0 0;
		font-size: 15px;
		line-height: 1.35;
		display: -webkit-box;
		-webkit-line-clamp: 3;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__meta {
		margin-top: 5px;
	}
}

/* The narrow end of desktop: the support column loses about 90px, so a 188px
   thumbnail would leave the headline breaking to single words. The thumbnail
   gives the width back rather than the text column absorbing all of it. */
@container (min-width: 861px) and (max-width: 1039px) {
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__link {
		grid-template-columns: 152px minmax(0, 1fr);
		gap: 12px;
	}
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured h3 {
		font-size: 19px;
	}

	/* The feature goes 16/9 here rather than 21/9. The support rows are set by
	   their text, so they barely shrink with the column, but a 21/9 feature does
	   — at 1024 it fell to 520x223 and left a 96px hole beneath it. 16/9 gives
	   the image back ~70px, closes the hole, and stops the crop reading as a
	   letterbox strip at tablet width. */
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured .tsp-video-card__media {
		aspect-ratio: 16 / 9;
	}
}

/* ------------------------------------------------------ shared details ---- */

/* The category chip sits on the image for the feature and above the headline
   for the supports — one rule, because the chip itself is identical. */
.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-eb-category {
	display: inline-block;
	background: var(--tsp-accent, #C8102E);
	color: #fff;
	font-family: var(--ts-font-ui, inherit);
	font-size: 9.5px;
	font-weight: 800;
	letter-spacing: .1em;
	text-transform: uppercase;
	padding: 3px 7px;
	border-radius: 3px;
	line-height: 1.5;
}

/* The metadata line. Relative date only — the reference's "12.4K views" has no
   field to read from, so nothing stands in for it. */
.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card__meta {
	display: block;
	margin-top: 7px;
	color: var(--ts-muted, #676E7B);
	font-family: var(--ts-font-ui, inherit);
	font-size: 12px;
	line-height: 1.4;
}

/* Play button: white disc, red triangle, per the reference. The existing rule
   paints a near-white disc with a dark triangle; only the colours and a
   restrained hover change here. */
.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card__play {
	background: rgba(255, 255, 255, .94);
	box-shadow: 0 6px 20px -8px rgba(0, 0, 0, .6);
	transition: transform .18s ease, background .18s ease;
}

.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card__play::after {
	border-color: transparent transparent transparent var(--tsp-accent, #C8102E);
}

.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card__link:hover .tsp-video-card__play,
.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card__link:focus-visible .tsp-video-card__play {
	transform: translate(-50%, -50%) scale(1.06);
	background: #fff;
}

/* The platform's light-surface headline hover, measured on Across the Telugu
   States and Movies. Not the Reviews gold — that belongs to a dark panel. */
.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card__link h3 {
	transition: color .18s ease;
}

.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card__link:hover h3,
.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card__link:focus-visible h3 {
	color: var(--tsp-accent, #C8102E);
}

/* v1.10.225 — the desktop exception that kept the feature's headline white on
   hover is gone with the overlay. The caption now sits on the same light
   surface as every other headline in the section, so it takes the same red and
   the feature stops being the one card that does not respond. The PHONE feature
   still overlays its image, and its own rule inside the max-width:860px block
   keeps white there. */

@media (prefers-reduced-motion: reduce) {
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card__play,
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card__link h3 { transition: none; }
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card__link:hover .tsp-video-card__play { transform: translate(-50%, -50%); }
}

/* ------------------------------------------------- phone composition ------ */

/* Deliberately a list, not a collapsed desktop grid: full-width cinematic
   feature, then four compact rows with the thumbnail left. */
@container (max-width: 860px) {
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-grid__items {
		grid-template-columns: minmax(0, 1fr);
		gap: 0;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured {
		grid-column: 1;
		grid-row: auto;
		margin-bottom: 16px;
	}

	/* v1.10.228 — the phone feature drops the overlay too, so the section reads
	   the same way at every width: image, then category, headline and date under
	   it.

	   Two reasons beyond consistency. The source is a 16:9 YouTube still, so the
	   old 16/11 box was cropping the SIDES off every feature — at 390 that cut
	   straight through the subject. And the caption sat on the image at 3 lines
	   plus a chip and a date, which is what forced the play button up to 34% to
	   avoid a collision. Below the image, none of that applies. */
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured .tsp-video-card__link {
		position: static;
		display: block;
		border-radius: 0;
		overflow: visible;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured .tsp-video-card__media {
		margin: 0 0 10px;
		border-radius: 10px;
		aspect-ratio: 16 / 9;
	}

	/* The scrim went with the overlay: there is no white text over the image to
	   keep legible any more. */
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured .tsp-video-card__media::after {
		display: none;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured .tsp-video-card__body {
		position: static;
		padding: 0;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured h3 {
		margin: 8px 0 0;
		color: var(--tsp-title-color, inherit);
		font-size: 18px;
		line-height: 1.3;
		font-weight: 700;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured .tsp-video-card__meta {
		color: var(--ts-muted, #676E7B);
	}

	/* A real touch target, per the brief's ~44px floor. Back to a true centre:
	   the 34% offset existed only because the caption used to sit on the image
	   and the button landed on the headline. */
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured .tsp-video-card__play {
		width: 60px;
		height: 60px;
		z-index: 2;
		top: 50%;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured h3 {
		display: -webkit-box;
		-webkit-line-clamp: 3;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	/* v1.10.228 — the white-on-hover exception is gone with the overlay. Every
	   headline in the section, feature included, now sits on the light surface
	   the section-wide red hover was written for. */

	/* --- the four supporting rows --- */

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) {
		grid-column: 1;
	}

	/* Proportional, not a fixed 136px. A single column spans anything from a
	   280px container to a 640px one here, and a fixed thumbnail that reads
	   correctly at 390 (about 39% of the row) collapses to 21% at 635 — the
	   video shrinking to a stamp beside a headline running the full measure.
	   38% holds the same proportion the wide and tablet layouts use, at every
	   width in the band. */
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__link {
		display: grid;
		grid-template-columns: minmax(0, 38%) minmax(0, 1fr);
		gap: 12px;
		align-items: start;
		padding: 12px 0;
		border-top: 1px solid var(--tsp-hairline, #E8E5DE);
	}

	/* Same correction as the desktop block: the selector this replaces could
	   never match, so the first phone row also drew a divider above nothing. */
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured + .tsp-video-card .tsp-video-card__link {
		border-top: 0;
		padding-top: 0;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__media {
		margin: 0;
		border-radius: 7px;
		aspect-ratio: 16 / 9;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__play {
		width: 34px;
		height: 34px;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__play::after {
		border-width: 6px 0 6px 10px;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) h3 {
		margin: 0;
		font-size: 14.5px;
		line-height: 1.32;
		display: -webkit-box;
		-webkit-line-clamp: 3;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	/* The row's chip is dropped: the section is already titled Watch and every
	   row would repeat the same category, which is what the mobile reference
	   shows on its rows. The feature keeps its chip. */
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-eb-category {
		display: none;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__meta {
		margin-top: 6px;
	}
}

/* v1.10.228 — the tablet band, designed rather than inherited.

   Between 561 and 860 the feature is already full width, but the supports were
   still one column: at a 728px container that gave a 136px thumbnail against a
   580px text column — the thumbnail about 19% of the row, so the video still
   read as a stamp beside a headline running the full measure.

   Two-up restores the desktop proportion instead of inventing a new one: each
   row lands near 420px at the top of the band and 300px at the bottom, keeping
   the thumbnail in the same ~36-42% of its row that the wide layout uses. The
   rows stay horizontal, so the section keeps one language at every width rather
   than switching to a card grid in the middle. */
@container (min-width: 561px) and (max-width: 860px) {
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-grid__items {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		column-gap: 22px;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card.is-featured {
		grid-column: 1 / -1;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) {
		grid-column: auto;
	}

	/* Two-up means supports 1 AND 2 start the first row, and 3 AND 4 start the
	   second — so the two that open each pair carry no divider. Counting is over
	   ALL articles, and article 1 is the feature, so supports 1 and 2 are
	   articles 2 and 3. */
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:nth-of-type(2) .tsp-video-card__link,
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:nth-of-type(3) .tsp-video-card__link {
		border-top: 0;
		padding-top: 0;
	}

	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__link {
		grid-template-columns: minmax(0, 32%) minmax(0, 1fr);  /* v1.10.425: 38%>32% — the thumbnail was taking two fifths of the row */
		gap: 12px;
	}
}

/* Very narrow: keep the thumbnail useful rather than letting it squeeze the
   headline into single words. */
@container (max-width: 380px) {
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) .tsp-video-card__link {
		grid-template-columns: minmax(0, 26%) minmax(0, 1fr);  /* v1.10.425: 40%>26% at the narrowest tier */
		gap: 10px;
	}
}

/* --- v1.10.218: the Watch masthead ------------------------------------------
   Heading and standfirst left, the archive link right, aligned on the heading's
   own line. Scoped to the Watch preset so no other video layout is affected. */
.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-grid__hd {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	align-items: baseline;
	column-gap: 24px;
	margin-bottom: 16px;
}

.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-grid__titles { min-width: 0; }

/* v1.10.232 — View All and the prev/next controls as one action group, aligned
   on the heading's line rather than the standfirst's. `align-items: baseline`
   on the header would drop the buttons onto the text baseline, so the group is
   centred within itself and the header row aligns to its first line. */
.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-grid__actions {
	display: flex;
	align-items: center;
	gap: 16px;
	flex: 0 0 auto;
}

/* The arrows are the shared .tsp-nav-btn component; only their size and the
   gap between them are set here, so hover, focus-visible and the disabled
   state all stay with section-nav.css and match every other section. */
.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-grid__actions .tsp-nav-controls {
	display: flex;
	align-items: center;
	gap: 8px;
}

.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-grid__actions .tsp-nav-btn {
	width: 32px;
	height: 32px;
}

/* The viewport must not clip the section's own composition, and the pages must
   not inherit a scrollbar. section-nav.css already handles the track; this only
   stops the page box adding height of its own. */
.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-nav-page > .tsp-video-grid__items {
	margin: 0;
}

/* The heading keeps whatever the shared heading component gives it - the red
   accent bar included - so only its trailing margin is adjusted here. */
.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-grid__hd .tsp-eb-heading,
.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-grid__hd h2 { margin-bottom: 0; }

.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-grid__sub {
	margin: 5px 0 0;
	font-family: var(--ts-body, Georgia, serif);
	font-style: italic;
	font-size: 13.5px;
	line-height: 1.45;
	color: var(--ts-muted, #676E7B);
	max-width: 60ch;
}

/* The platform's established red archive link, same treatment the other
   sections use. Never a second CTA: this is the only one in the section. */
.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-nav-viewall--watch {
	justify-self: end;
	white-space: nowrap;
	font-family: var(--ts-font-ui, inherit);
	font-size: 12px;
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--tsp-accent, #C8102E);
	text-decoration: none;
	border: 0;
	padding: 0;
}

.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-nav-viewall--watch:hover,
.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-nav-viewall--watch:focus-visible {
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* Phone: the actions drop under the standfirst rather than squeezing the
   heading. v1.10.232 — the group moves, not just the link, so View All and the
   arrows stay together on their own row instead of the arrows being orphaned. */
@container (max-width: 520px) {
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-grid__hd {
		grid-template-columns: minmax(0, 1fr);
		row-gap: 10px;
	}
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-grid__actions {
		justify-self: start;
	}
}

/* ==========================================================================
   v1.10.246 — SPORTS SHOWCASE (news-grid, `sports-showcase`)
   Reference: Images/sports_desktop.png

   One dominant lead on the left, six supporting stories in a 3x2 grid on the
   right. A new layout id rather than a variation of an existing preset, for the
   same reason `movies-showcase` and `state-desk` are their own ids: it owns its
   media layout at every width and inherits none of the shared card rules.

   NO new markup and no renderer branch. The shared news-grid card already emits
   media, category chip, headline, time and (lead only) excerpt, and this preset
   is registered in `$lead_layouts`, which is what makes the excerpt render on
   the feature alone. The feature's caption sits ON its image by CSS rather than
   through OVERLAY_LAYOUTS, because that constant would turn all seven cards
   into overlays and strip the supporting captions the reference shows below
   their images.

   Container queries on .tsp-eb-wrap throughout, never @media — the project's
   responsive model. Tiers, by CONTAINER width:
       >= 1000   1 lead + 3x2 grid      (desktop reference)
       641-999   1 lead + 2x3 grid      (deliberate tablet composition)
       <= 640    1 lead + compact rows  (phone)
       <= 380    same rows, tightened   (small phone)

   OMITTED ON PURPOSE: the reference mockup shows a comment count on every card.
   Telugu Scope has no comment metric surfaced through this architecture, so it
   is left out rather than invented. Category, headline and time are real.
   ========================================================================== */

/* Header: heading left, one archive link right, on the heading's own line. */
.tsp-eb.tsp-news-grid--sports-showcase .tsp-sports__actions {
	display: flex;
	align-items: center;
	gap: 14px;
	flex: 0 0 auto;
}

.tsp-eb.tsp-news-grid--sports-showcase .tsp-nav-viewall--sports {
	font-family: var(--ts-font-ui, inherit);
	font-size: 12px;
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--tsp-accent, #C8102E);
	text-decoration: none;
	white-space: nowrap;
	border: 0;
	padding: 0;
}

.tsp-eb.tsp-news-grid--sports-showcase .tsp-nav-viewall--sports:hover,
.tsp-eb.tsp-news-grid--sports-showcase .tsp-nav-viewall--sports:focus-visible {
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* ---------------------------------------------------------- shared card ---- */

.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card {
	min-width: 0;
	background: #fff;
	border: 1px solid var(--tsp-hairline, #E8E5DE);
	border-radius: 10px;
	overflow: hidden;
}

.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card > a {
	display: block;
	height: 100%;
	color: inherit;
	text-decoration: none;
}

.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card__media {
	position: relative;
	overflow: hidden;
	background: #eee;
	margin: 0;
}

.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card__media img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* The chip sits ON the image, bottom-left, exactly as the reference draws it —
   on the supporting cards and on the feature alike. */
.tsp-eb.tsp-news-grid--sports-showcase .tsp-eb-category {
	display: inline-block;
	background: var(--tsp-accent, #C8102E);
	color: #fff;
	font-family: var(--ts-font-ui, inherit);
	font-size: 9.5px;
	font-weight: 800;
	letter-spacing: .1em;
	text-transform: uppercase;
	padding: 3px 7px;
	border-radius: 3px;
	line-height: 1.5;
}

/* v1.10.422: display serif — these are Sports story headlines. */
.tsp-eb.tsp-news-grid--sports-showcase .tsp-story-title {
	margin: 0;
	font-family: var(--ts-font-display, Georgia, serif);
	font-weight: 700;
	color: var(--tsp-title-color, #16181F);
	transition: color .18s ease;
}

.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card > a:hover .tsp-story-title,
.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card > a:focus-visible .tsp-story-title {
	color: var(--tsp-accent, #C8102E);
}

.tsp-eb.tsp-news-grid--sports-showcase time,
.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card__meta {
	display: block;
	font-family: var(--ts-font-ui, inherit);
	color: var(--ts-muted, #676E7B);
}

/* ------------------------------------------------- the feature (all tiers) -- */

/* The caption sits on the image. The scrim is transparent across the top so the
   photograph keeps its subject, deepening only where the text sits. */
.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead > a {
	position: relative;
	display: block;
}

.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead .tsp-news-card__media::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	background: linear-gradient(180deg, rgba(8, 9, 12, 0) 42%, rgba(8, 9, 12, .58) 68%, rgba(8, 9, 12, .93) 100%);
}

.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead .tsp-news-card__content {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 2;
	padding: 20px;
}

.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead .tsp-story-title {
	margin: 10px 0 0;
	color: #fff;
}

.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead > a:hover .tsp-story-title,
.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead > a:focus-visible .tsp-story-title {
	color: #fff;
}

.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead p {
	margin: 8px 0 0;
	font-family: var(--ts-font-ui, inherit);
	font-size: 13.5px;
	line-height: 1.45;
	color: rgba(255, 255, 255, .86);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead time,
.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead .tsp-news-card__meta {
	margin-top: 10px;
	color: rgba(255, 255, 255, .82);
	font-size: 11.5px;
}

/* ------------------------------------------ desktop: lead + 3 x 2 grid ----- */

@container (min-width: 1000px) {
	/* 2fr against three 1fr tracks puts the feature at ~40% of the row, which is
	   what the reference draws, and spanning both rows is what makes the feature
	   and the grid finish level without either being given a fixed height. */
	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-grid__items {
		display: grid;
		grid-template-columns: minmax(0, 2fr) repeat(3, minmax(0, 1fr));
		grid-auto-rows: 1fr;
		gap: 16px;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead {
		grid-column: 1;
		grid-row: 1 / 3;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead .tsp-news-card__media {
		height: 100%;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead .tsp-story-title {
		font-size: 27px;
		line-height: 1.22;
		display: -webkit-box;
		-webkit-line-clamp: 4;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	/* Supporting cards: image on top, caption below, chip on the image. */
	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__media {
		aspect-ratio: 16 / 9;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__content { position: relative; }

	/* The chip belongs ON the image, but it is a child of __content, which is a
	   SIBLING of __media — so it cannot be positioned against the media box.
	   Anchoring it to the top edge of the content and lifting it clear puts it
	   over the picture without touching the markup. */
	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-eb-category {
		position: absolute;
		left: 0;
		bottom: calc(100% + 10px);
		z-index: 2;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__content {
		padding: 12px 12px 14px;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-story-title {
		font-size: 14.5px;
		line-height: 1.34;
		display: -webkit-box;
		-webkit-line-clamp: 3;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) time,
	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__meta {
		margin-top: 9px;
		font-size: 11.5px;
	}
}

/* The chip is absolutely placed inside the media on every tier for supporting
   cards; the media is the positioning context. */
.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__media { position: relative; }

/* ------------------------------------------- tablet: lead + 2 x 3 grid ----- */

@container (min-width: 641px) and (max-width: 999px) {
	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-grid__items {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 14px;
	}

	/* Feature spans the full width and leads; the six then fall into 2 x 3
	   beneath it. Deliberately not a shrunken desktop row — at this width a 40%
	   feature would leave the supporting cards under 200px. */
	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead {
		grid-column: 1 / -1;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead .tsp-news-card__media {
		aspect-ratio: 16 / 7;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead .tsp-story-title {
		font-size: 23px;
		line-height: 1.24;
		display: -webkit-box;
		-webkit-line-clamp: 3;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__media {
		aspect-ratio: 16 / 9;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__content { position: relative; }

	/* The chip belongs ON the image, but it is a child of __content, which is a
	   SIBLING of __media — so it cannot be positioned against the media box.
	   Anchoring it to the top edge of the content and lifting it clear puts it
	   over the picture without touching the markup. */
	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-eb-category {
		position: absolute;
		left: 0;
		bottom: calc(100% + 10px);
		z-index: 2;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__content {
		padding: 11px 12px 13px;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-story-title {
		font-size: 14px;
		line-height: 1.33;
		display: -webkit-box;
		-webkit-line-clamp: 3;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) time,
	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__meta {
		margin-top: 8px;
		font-size: 11px;
	}
}

/* --------------------------------- phone: lead + six compact media rows ---- */

/* Seven stacked cards would make Sports the longest section on the page, so the
   six supporting stories become thumbnail rows and only the feature keeps its
   picture at full width. */
@container (max-width: 640px) {
	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-grid__items {
		display: grid;
		grid-template-columns: minmax(0, 1fr);
		gap: 0;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead {
		margin-bottom: 14px;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead .tsp-news-card__media {
		aspect-ratio: 16 / 10;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead .tsp-story-title {
		font-size: 19px;
		line-height: 1.26;
		display: -webkit-box;
		-webkit-line-clamp: 3;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead p { display: none; }

	/* Rows: no card chrome, a hairline between them instead — the same compact
	   editorial row language Watch and Trending use on phones. */
	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) {
		background: none;
		border: 0;
		border-radius: 0;
		border-top: 1px solid var(--tsp-hairline, #E8E5DE);
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead + .tsp-news-card {
		border-top: 0;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) > a {
		display: grid;
		grid-template-columns: minmax(0, 32%) minmax(0, 1fr);  /* v1.10.425: 38%>32%, same reason as Watch */
		gap: 12px;
		align-items: center;
		padding: 11px 0;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__media {
		aspect-ratio: 16 / 10;
		border-radius: 6px;
	}

	/* On a row the chip belongs above the headline, not on a 130px thumbnail. */
	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-eb-category {
		position: static;
		margin-bottom: 4px;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__content {
		padding: 0;
		min-width: 0;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-story-title {
		font-size: 13.5px;
		line-height: 1.32;
		display: -webkit-box;
		-webkit-line-clamp: 3;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) time,
	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__meta {
		margin-top: 5px;
		font-size: 11px;
	}
}

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

@container (max-width: 380px) {
	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead .tsp-story-title { font-size: 17px; }
	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card.is-lead .tsp-news-card__content { padding: 14px; }

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) > a {
		grid-template-columns: minmax(0, 30%) minmax(0, 1fr);  /* v1.10.425: 40%>30% at the narrowest tier */
		gap: 10px;
		padding: 10px 0;
	}

	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-story-title { font-size: var(--ts-title-dense); }
	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) time,
	.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-news-card__meta { font-size: 10.5px; }
}

/* ==========================================================================
   v1.10.250 — MORE FROM TELUGU SCOPE
   Reference: Images/more_from_telugu_scope.png

   Three sibling desks — Technology, Business, Lifestyle — each an ordinary News
   Grid on the `more-desk` preset with its own category, so the desks stay
   genuinely independent sources rather than one query sliced three ways.

   The reference draws each desk in its own accent (purple / blue / pink). That
   is deliberately NOT reproduced: Telugu Scope has one accent, and three more
   would invent a colour language the rest of the paper does not speak. The
   desks are separated by their kicker and their card, not by hue.

   DESKTOP TIER ONLY in this patch. Tablet, mobile and small-mobile follow as
   their own steps so each is inspected on the real page before the next starts.
   ========================================================================== */

.tsp-news-grid--more-desk {
	--tsp-more-rule: #E8E5DE;
	--tsp-more-red: var(--tsp-red, #C8102E);
	/* The desk is its own responsive context: on desktop it is a ~370px column
	   inside a three-across row, so every composition rule below has to resolve
	   against the DESK, never the viewport. */
	container-type: inline-size;
	padding: 20px 18px 18px;
	border: 1px solid var(--tsp-more-rule);
	border-radius: 10px;
	background: #fff;
	/* A column so the CTA can be bottom-anchored with margin-top:auto. Desks are
	   equal height by construction, and a desk whose stories are shorter must
	   spend the difference as quiet space above its button rather than by
	   stretching its rows — the mistake that made the state desks read loose. */
	display: flex;
	flex-direction: column;
}

/* ------------------------------------------------------------- kicker ---- */

/* The desk name is a kicker, not a heading competing with the section's own
   title: small, tracked, brand red, with a short rule under it. */
.tsp-news-grid--more-desk .tsp-eb-heading {
	margin: 0 0 14px;
	padding: 0 0 8px;
	border: 0;
	position: relative;
}
/* v1.10.422: family only. "TECHNOLOGY", "BUSINESS", "LIFESTYLE" name editorial
   desks, so they join the display system — but the compact 12.5px red uppercase
   treatment stays. Raising them to the 20px section-heading size would rebuild
   the strip's header row and its underline rather than unify a family, and §17
   freezes the desktop composition. Documented as a deliberate scale exception:
   family unified, eyebrow scale retained. */
.tsp-news-grid--more-desk .tsp-eb-heading > *,
.tsp-news-grid--more-desk .tsp-eb-heading h2,
.tsp-news-grid--more-desk .tsp-eb-heading h3 {
	margin: 0;
	font-family: var(--ts-display, Georgia, serif);
	font-size: 12.5px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: var(--tsp-more-red);
}
/* The short underline from the reference. On the heading wrapper rather than a
   new element, so no markup exists solely to be decorated. */
.tsp-news-grid--more-desk .tsp-eb-heading::after {
	content: "";
	position: absolute;
	left: 0;
	bottom: 0;
	width: 34px;
	height: 3px;
	background: var(--tsp-more-red);
	border-radius: 2px;
}

/* -------------------------------------------------------------- stories --- */

.tsp-news-grid--more-desk .tsp-news-grid__items {
	display: flex;
	flex-direction: column;
	gap: 0;
}

/* Absorbs the slack in a desk whose stories are shorter, which is what puts the
   three CTAs on one line.

   It has to be the VIEWPORT, not the items list: Section Navigation wraps the
   list in `.tsp-nav-viewport`, so the list is a grandchild of the desk and
   growing it moves nothing in the desk's own column layout. The CTA cannot do
   this with margin-top:auto either — that would collapse the gap above it. */
.tsp-news-grid--more-desk > .tsp-nav-viewport {
	flex: 1 1 auto;
}

/* Lead: a 16:9 still, then the headline, then its timestamp. */
.tsp-news-grid--more-desk .tsp-news-card.is-lead {
	display: block;
	padding: 0 0 14px;
}
.tsp-news-grid--more-desk .tsp-news-card.is-lead .tsp-news-card__media {
	display: block;
	aspect-ratio: 16 / 9;
	border-radius: 6px;
	overflow: hidden;
	margin-bottom: 11px;
}
.tsp-news-grid--more-desk .tsp-news-card.is-lead .tsp-news-card__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
.tsp-news-grid--more-desk .tsp-news-card.is-lead .tsp-story-title {
	font-family: var(--ts-display, Georgia, serif);
	font-size: 18px;
	line-height: 1.28;
	font-weight: 700;
	margin: 0 0 8px;
}

/* Supporting rows: a small square still on the left, headline and time right.
   Separated from the lead and from each other by the same hairline the desk
   card uses, so the desk reads as one list rather than three loose blocks. */
/* The row grid goes on the ANCHOR, not on the card.
   A card's only child is the <a> that wraps both the media and the content, so
   putting the two-column grid on the card itself placed that entire link in the
   78px thumbnail track — every supporting headline then wrapped one word per
   line. Nothing measured caught it: the columns were correct, the card width was
   correct, and the text was unreadable. */
.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead) {
	display: block;
	padding: 13px 0;
	border-top: 1px solid var(--tsp-more-rule);
}
.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead) > a {
	display: grid;
	grid-template-columns: 78px minmax(0, 1fr);
	gap: 12px;
	align-items: start;
	text-decoration: none;
	color: inherit;
}
.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead) .tsp-news-card__media {
	display: block;
	aspect-ratio: 1 / 1;
	border-radius: 5px;
	overflow: hidden;
}
.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead) .tsp-news-card__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead) .tsp-story-title {
	font-family: var(--ts-display, Georgia, serif);
	font-size: 14px;
	line-height: 1.32;
	font-weight: 600;
	margin: 0 0 6px;
}

/* The desk's own category chip is redundant — the kicker above already states
   the section, and every card in the desk carries the same one. */
.tsp-news-grid--more-desk .tsp-eb-category {
	display: none;
}

.tsp-news-grid--more-desk time,
.tsp-news-grid--more-desk .tsp-news-card__meta {
	font-family: var(--ts-ui, system-ui, sans-serif);
	font-size: 11.5px;
	color: var(--tsp-muted, #676E7B);
}

/* ----------------------------------------------------------------- CTA ---- */

/* Bottom-anchored so the three buttons line up across desks of unequal text
   length, which is what makes the row read as three parallel cards. */
.tsp-more-desk__cta {
	display: block;
	margin: 18px auto 0;
	padding: 11px 18px;
	max-width: 240px;
	border: 1px solid var(--tsp-more-red);
	border-radius: 5px;
	font-family: var(--ts-ui, system-ui, sans-serif);
	font-size: 12px;
	font-weight: 700;
	letter-spacing: .07em;
	text-transform: uppercase;
	text-align: center;
	color: var(--tsp-more-red);
	text-decoration: none;
	transition: background-color .18s ease, color .18s ease;
}
.tsp-more-desk__cta:hover,
.tsp-more-desk__cta:focus-visible {
	background: var(--tsp-more-red);
	color: #fff;
}

/* ============================================ the section around the desks == */

.tsp-more-scope__head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 4px 16px;
	margin-bottom: 18px;
}
.tsp-more-scope__head h2 {
	position: relative;
	margin: 0;
	padding-left: 14px;
	font-family: var(--ts-display, Georgia, serif);
	font-size: 27px;
	line-height: 1.15;
	font-weight: 700;
}
/* The red bar the reference sets against the section title. */
.tsp-more-scope__head h2::before {
	content: "";
	position: absolute;
	left: 0;
	top: .12em;
	bottom: .12em;
	width: 5px;
	border-radius: 2px;
	background: var(--tsp-red, #C8102E);
}
.tsp-more-scope__sub {
	flex: 1 1 100%;
	margin: 0;
	padding-left: 14px;
	font-family: var(--ts-ui, system-ui, sans-serif);
	font-size: 13.5px;
	color: var(--tsp-muted, #676E7B);
}

/* Desks are stretched to equal height so their bottom-anchored CTAs align. */
.tsp-more-scope .wp-block-columns {
	align-items: stretch;
	gap: 20px;
}
.tsp-more-scope .wp-block-column {
	display: flex;
}
.tsp-more-scope .wp-block-column > .tsp-eb {
	flex: 1 1 auto;
}

/* The rule that closes the section in the reference. */
.tsp-more-scope {
	padding-bottom: 22px;
	border-bottom: 2px solid var(--tsp-red, #C8102E);
}

/* ---------------------------------------------------------------- tablet ---
   v1.10.254 — three desks across stops working well before the columns stack.

   Between roughly 780 and 1040 the section still renders three columns, which
   squeezes each desk under ~260px: the lead headline breaks to five or six
   lines and the supporting rows lose their text column. Two desks on the first
   row and the third below reads far better at that size, and it is the
   arrangement the work order asks for.

   Expressed as a CONTAINER query against the section — not a media query — so
   it responds to the space the section actually has, which is what the
   responsive standard in this project requires. The section therefore declares
   itself a container above.

   Bounded at BOTH ends on purpose. Without the lower bound this rule would beat
   core's `.wp-block-column{flex-basis:100%}` below 782px on specificity and
   force two cramped columns onto phones. */
.tsp-more-scope {
	container-type: inline-size;
}

@container (min-width: 640px) and (max-width: 1040px) {
	/* GRID, not flex-wrap. Core ships `flex-wrap:nowrap !important` above 782px,
	   so wrapping the row would mean answering one !important with another —
	   which this project does not do outside the editor stylesheet. Switching the
	   display mode sidesteps the fight entirely: core sets no !important on
	   `display`, and once the row is a grid its flex rules are inert.

	   The third desk sits alone on the second row at half width, keeping the
	   section's left edge rather than centring itself under the gap. */
	.tsp-more-scope .wp-block-columns {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 20px;
		align-items: stretch;
	}
}

/* ---------------------------------------------------------------- phones ---
   v1.10.256 — the desks stack full width below ~640, and at that point the
   desktop rhythm is too generous: three desks at ~790px each is 2,350px of
   scrolling for nine stories.

   Tightened rather than redesigned. The composition is identical — kicker,
   16:9 lead, two thumbnail rows, CTA — because a reader moving between the
   phone and the desktop should recognise the same section, and because the
   supporting rows are already the compact pattern. What changes is the spacing
   and the type scale, which is where the height actually is.

   Keyed to the DESK's own container, not the viewport: a desk is its own
   container at every width, so this fires when the desk is narrow rather than
   when the phone is. */
@container (max-width: 470px) {
	.tsp-news-grid--more-desk {
		padding: 16px 14px 14px;
	}
	.tsp-news-grid--more-desk .tsp-eb-heading {
		margin-bottom: 11px;
		padding-bottom: 7px;
	}
	.tsp-news-grid--more-desk .tsp-news-card.is-lead {
		padding-bottom: 11px;
	}
	.tsp-news-grid--more-desk .tsp-news-card.is-lead .tsp-news-card__media {
		margin-bottom: 9px;
	}
	.tsp-news-grid--more-desk .tsp-news-card.is-lead .tsp-story-title {
		font-size: 17px;
		margin-bottom: 6px;
	}
	.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead) {
		padding: 10px 0;
	}
	.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead) > a {
		grid-template-columns: 68px minmax(0, 1fr);
		gap: 10px;
	}
	.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead) .tsp-story-title {
		font-size: 13.5px;
		margin-bottom: 4px;
	}
	.tsp-more-desk__cta {
		margin-top: 14px;
		padding: 10px 16px;
	}
}

/* Small phones. The CTA stops being a fixed pill and simply spans the desk —
   at 280px a 185px button floating in the middle reads as unfinished, and a
   full-width control is also the easier tap target. */
@container (max-width: 320px) {
	.tsp-news-grid--more-desk {
		padding: 14px 12px 12px;
	}
	.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead) > a {
		grid-template-columns: 60px minmax(0, 1fr);
		gap: 9px;
	}
	.tsp-more-desk__cta {
		max-width: none;
		font-size: 11.5px;
		letter-spacing: .05em;
	}
}

/* ==========================================================================
   v1.10.258 — MORE FROM TELUGU SCOPE, revised to the approved reference
   Reference: Images/more_from_telugu_scope.png (updated)

   Header now carries a badge and VIEW ALL; the desk shows one lead and THREE
   supporting stories; the footer carries paging on the left and an editorial
   MORE link on the right.

   The badges are drawn here, locally: a tinted circle from `background-color`
   with the glyph as an inline SVG data URI on top. No icon font, no external
   request, no raster file. They are pseudo-elements, so assistive technology
   never announces them — which is the correct handling for decoration that
   repeats the desk name sitting right beside it.
   ========================================================================== */

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

.tsp-news-grid--more-desk .tsp-nav-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	margin-bottom: 14px;
}
.tsp-news-grid--more-desk .tsp-eb-heading {
	display: flex;
	align-items: center;
	gap: 10px;
	margin: 0;
	padding-bottom: 8px;
}
/* The badge. 30px circle, glyph at 15px — deliberately subordinate to the desk
   name it sits beside. */
.tsp-news-grid--more-desk .tsp-eb-heading::before {
	content: "";
	flex: 0 0 auto;
	width: 30px;
	height: 30px;
	border-radius: 50%;
	background-color: rgba(200, 16, 46, .09);
	background-repeat: no-repeat;
	background-position: center;
	background-size: 15px 15px;
}
/* The short rule under the desk name only — absolute, so it stays out of the
   header's flex flow and tracks the name rather than the badge. */
.tsp-news-grid--more-desk .tsp-eb-heading::after {
	left: 40px;
	width: 30px;
}

/* Technology — a microchip. */
.tsp-news-grid--more-desk.tsp-more-desk--technology .tsp-eb-heading::before {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23C8102E' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='7' y='7' width='10' height='10' rx='1.5'/%3E%3Cpath d='M10 3v3M14 3v3M10 18v3M14 18v3M3 10h3M3 14h3M18 10h3M18 14h3'/%3E%3C/svg%3E");
}
/* Business — a rising chart. */
.tsp-news-grid--more-desk.tsp-more-desk--business .tsp-eb-heading::before {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23C8102E' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 19V9M10 19v-6M16 19V5M4 19h16'/%3E%3C/svg%3E");
}
/* Lifestyle — a leaf. */
.tsp-news-grid--more-desk.tsp-more-desk--lifestyle .tsp-eb-heading::before {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23C8102E' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 4C10 4 4 9 4 16c0 2 1 4 1 4s2-9 15-11'/%3E%3Cpath d='M5 20c2-6 7-9 13-10'/%3E%3C/svg%3E");
}

.tsp-more-desk__viewall {
	flex: 0 0 auto;
	font-family: var(--ts-ui, system-ui, sans-serif);
	font-size: 11.5px;
	font-weight: 700;
	letter-spacing: .07em;
	text-transform: uppercase;
	color: var(--tsp-red, #C8102E);
	text-decoration: none;
	white-space: nowrap;
}
.tsp-more-desk__viewall:hover,
.tsp-more-desk__viewall:focus-visible { text-decoration: underline; }

/* -------------------------------------------------------------- footer ---- */

.tsp-more-desk__foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	margin-top: 14px;
	padding-top: 13px;
	border-top: 1px solid var(--tsp-more-rule);
}
/* Circular paging controls, bottom-left. Sized down from the block's 40px
   default because a desk is a ~370px column, not a full-width section. */
.tsp-news-grid--more-desk .tsp-nav-arrows { display: flex; gap: 8px; }
.tsp-news-grid--more-desk .tsp-nav-arrow {
	width: 30px;
	height: 30px;
	border-radius: 50%;
	border: 1px solid var(--tsp-more-rule);
	background: #fff;
	color: var(--tsp-ink, #16181F);
}
/* The disabled state has to READ as disabled — Lifestyle holds one page, and a
   control that looks live but does nothing is worse than one that says so. */
.tsp-news-grid--more-desk .tsp-nav-arrow[disabled],
.tsp-news-grid--more-desk .tsp-nav-arrow[aria-disabled="true"] {
	opacity: .38;
	cursor: default;
}

/* The CTA is now an editorial text link, not the previous outlined button. */
.tsp-more-desk__cta {
	display: inline;
	margin: 0;
	padding: 0;
	max-width: none;
	border: 0;
	border-radius: 0;
	background: none;
	font-family: var(--ts-ui, system-ui, sans-serif);
	font-size: 11.5px;
	font-weight: 700;
	letter-spacing: .07em;
	text-transform: uppercase;
	text-align: right;
	color: var(--tsp-red, #C8102E);
	text-decoration: none;
	white-space: nowrap;
}
.tsp-more-desk__cta:hover,
.tsp-more-desk__cta:focus-visible {
	background: none;
	color: var(--tsp-red, #C8102E);
	text-decoration: underline;
}

/* --------------------------------------------------------------- density -- */

/* Four stories now, so the lead gives back some of its room and the rows sit
   tighter. The desk sizes around its content: the viewport still absorbs the
   slack so the three footers align, but there is far less slack to absorb. */
.tsp-news-grid--more-desk .tsp-news-card.is-lead { padding-bottom: 12px; }
.tsp-news-grid--more-desk .tsp-news-card.is-lead .tsp-story-title { font-size: 17px; margin-bottom: 6px; }
.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead) { padding: 11px 0; }
.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead) .tsp-story-title { font-size: var(--ts-title-dense); }

@container (max-width: 470px) {
	.tsp-more-desk__foot { margin-top: 12px; padding-top: 11px; }
	.tsp-news-grid--more-desk .tsp-eb-heading::before { width: 26px; height: 26px; background-size: 13px 13px; }
	.tsp-news-grid--more-desk .tsp-eb-heading::after { left: 36px; }
}
@container (max-width: 320px) {
	/* At 280px the desk name, the badge and VIEW ALL stop fitting on one line.
	   Wrapping the link under the name keeps every touch target full size
	   instead of shrinking the type to force a single row. */
	.tsp-news-grid--more-desk .tsp-nav-header { flex-wrap: wrap; gap: 4px 10px; }
	.tsp-more-desk__viewall { font-size: 11px; }
	.tsp-more-desk__cta { font-size: 11px; letter-spacing: .05em; }
}

/* v1.10.260 — the footer's LEFT ZONE, present whether or not it holds arrows.

   A desk with one page gets no arrows from Section_Navigation, which is right.
   What was wrong is that the CTA then became the footer's only child and
   `space-between` pushed it left, so Lifestyle's link sat under its thumbnails
   while Technology's and Business's stayed right.

   Reserving the column keeps one shared footer architecture: same zones, same
   height, same baseline across all three desks, with no per-desk rule and no
   placeholder control pretending a second page exists. min-height matches the
   30px arrow so an empty zone and a populated one measure identically. */
.tsp-more-desk__pager {
	display: flex;
	align-items: center;
	gap: 8px;
	min-height: 30px;
	flex: 0 0 auto;
}

/* v1.10.261 — the desk links join the shared control language.

   They were a bespoke component: `.tsp-more-desk__viewall` and
   `.tsp-more-desk__cta` at one class of specificity, which an inherited link
   rule outranked — so both rendered navy (rgb(58,79,102)) while every other
   section's control rendered brand red. `--tsp-red` is not a :root token, so
   the var() fallback never rescued it either.

   They now carry `.tsp-nav-viewall` — the same base every other preset uses
   (movies-showcase, sports-showcase, the state desk) — and the modifiers below
   carry ONLY geometry. Colour, size, weight, tracking, uppercase, hover and
   focus all come from the design system, so this component cannot drift from it
   again. The two bespoke rule sets above are now dead selectors: nothing emits
   those class names any more. */
.tsp-nav-viewall--more {
	flex: 0 0 auto;
	white-space: nowrap;
}
.tsp-nav-viewall--more-cta {
	white-space: nowrap;
	text-align: right;
}

/* The base `.tsp-nav-viewall` ships the SECTION-level scale (14px/600/.5px),
   which is right for a full-width section header and too loud inside a ~370px
   desk. Across the Telugu States solves this on `.tsp-state-desk__viewall` at
   11px/700/.88px, and these desks sit at the same size in the same row, so they
   take the same desk-scale values rather than inventing a third one. Colour,
   uppercase, hover and focus still come from the base. */
.tsp-nav-viewall--more,
.tsp-nav-viewall--more-cta {
	font-size: 11px;
	font-weight: 700;
	letter-spacing: .08em;
}

/* ==========================================================================
   v1.10.263 — design-system alignment with Across the Telugu States
   ========================================================================== */

/* Desk titles are DARK, not red. Red is an accent and an action colour here —
   the icon, the short rule, VIEW ALL and MORE — exactly as the state desks use
   it. Making the title red too left the desk with no tonal hierarchy and four
   competing reds. Reuses the ink token already used throughout this stylesheet
   rather than introducing another near-black. */
.tsp-news-grid--more-desk .tsp-eb-heading > *,
.tsp-news-grid--more-desk .tsp-eb-heading h2,
.tsp-news-grid--more-desk .tsp-eb-heading h3 {
	color: var(--tsp-ink, #16181F);
}

/* The section-wide red rule is gone. Every desk already carries a border, the
   rows carry separators and the next section brings its own separation, so the
   rule was a fourth division doing no work. The short red accent under each
   desk title is untouched — that one identifies the desk. The space it
   occupied is kept so the transition into the next section does not tighten. */
.tsp-more-scope {
	border-bottom: 0;
	padding-bottom: 26px;
}

/* Breathing room between the completed header (title + accent) and the lead
   image. The accent sits at the header's bottom edge, so at 14px the rule was
   almost touching the image. */
.tsp-news-grid--more-desk .tsp-nav-header {
	margin-bottom: 18px;
}

/* The desk links take the DESK type scale, not the section scale.
   Scoped to the desk (0,2,0) because the base `.tsp-nav-viewall` size and
   weight are themselves set at two classes — at one class my modifier lost
   size and weight while winning letter-spacing, which is why the links
   rendered 14px/600 against the state desks' 11px/700. Colour, uppercase,
   hover and focus still come from the shared base. */
.tsp-news-grid--more-desk .tsp-nav-viewall--more,
.tsp-news-grid--more-desk .tsp-nav-viewall--more-cta {
	font-size: 11px;
	font-weight: 700;
	letter-spacing: .08em;
}

/* ==========================================================================
   v1.10.264 — footer parity, header breathing room, row rhythm
   ========================================================================== */

/* FOOTER PARITY. `min-height` on the pager zone did not equalise the footers:
   an empty flex box with no in-flow content establishes no line box, so the
   footer's height fell to the CTA's text height and Lifestyle sat ~14px
   shorter than the two desks with arrows.

   An explicit height matches the real arrow box (30px) whether or not the zone
   holds buttons, so the footer row is the same height in all three desks by
   construction. Shared rule, no Lifestyle selector, no fake control. */
.tsp-more-desk__pager {
	height: 30px;
	min-height: 0;
}
/* The footer row itself is sized by the pager zone, so the CTA centres against
   the same box in every desk rather than defining the height in one of them. */
.tsp-more-desk__foot {
	align-items: center;
	min-height: 30px;
}

/* HEADER BREATHING ROOM. The badge sat tight against the desk name and the
   accent rule sat tight under it. Both open up by a couple of pixels — the
   icons are NOT enlarged. */
.tsp-news-grid--more-desk .tsp-eb-heading {
	gap: 12px;
	padding-bottom: 10px;
}

/* SUPPORTING ROW RHYTHM. 11px read as compressed against the separators;
   13px gives the thumbnail/headline/date group room without materially
   changing section height (2px per row, six rows across the section). */
.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead) {
	padding: 13px 0;
}

/* ==========================================================================
   v1.10.265 — the desk's internal content gutter

   Measured on the live 1440 render, the desk computed to `16px 0px 14px`: zero
   horizontal padding. Header, lead image, supporting thumbnails, dividers and
   footer all sat 1px from the card border — only the text looked inset, and
   only because the shared card rule already insets it ~10px.

   Solved the way Across the Telugu States solves it: ONE named inset applied to
   the desk's own rows, not blanket padding on the desk. Padding the desk would
   compound with the card's existing text inset and take ~27px off every
   supporting headline's column — the one thing that comment warns against.

   The card's own text inset is therefore zeroed here and the single gutter
   below replaces it, so image edge and text edge land on the SAME vertical
   axis instead of two axes 11px apart.

   Desk-scoped (0,2,0) so it cannot bleed into a frozen component, and so it
   outranks whatever zeroed the horizontal padding in the first place. */
.tsp-news-grid--more-desk {
	--tsp-more-inset: 16px;
}
.tsp-news-grid--more-desk .tsp-nav-header,
.tsp-news-grid--more-desk .tsp-news-card.is-lead,
.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead),
.tsp-news-grid--more-desk .tsp-more-desk__foot {
	padding-inline: var(--tsp-more-inset);
}
/* One axis, not two: the row now carries the gutter, so the card's own text
   inset would double it. */
.tsp-news-grid--more-desk .tsp-news-card__content {
	padding-inline: 0;
}

/* v1.10.266 — the clock before every date.

   The reference sets each date with a small clock, the way the utility bar sets
   its date with a calendar. Same technique as that one and as the other icons
   in this stylesheet: a CSS mask tinted with `currentColor`, so the glyph
   tracks the metadata's own muted grey instead of introducing a second colour
   to keep in step, and no markup is needed to carry it.

   A pseudo-element is also the correct accessibility answer here — the date is
   already a semantic <time>, and a decorative clock beside it must not be
   announced. Scoped to this desk so no frozen section gains an icon. */
.tsp-news-grid--more-desk time {
	display: inline-flex;
	align-items: center;
}
.tsp-news-grid--more-desk time::before {
	content: "";
	flex: 0 0 auto;
	width: 12px;
	height: 12px;
	margin-right: 6px;
	background-color: currentColor;
	opacity: .85;
	-webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
	-webkit-mask-position: center; mask-position: center;
	-webkit-mask-size: contain; mask-size: contain;
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3 2'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3 2'/%3E%3C/svg%3E");
}

/* v1.10.269 — one lead zone, so the supporting rows share a baseline.

   Everything above the headline already aligned: card top, header, lead image
   top AND bottom, headline top. The only variable was the headline's own
   height — three lines in Technology, two in Business, one in Lifestyle — which
   pushed supporting row 1 to three different Y positions 43px apart.

   The zone is reserved on the headline itself, sized in `em` at the headline's
   own line-height, so the value is DERIVED from the type scale rather than
   copied as a pixel from the reference. Three lines is the longest legitimate
   lead headline at this measure; a fourth would grow the zone naturally rather
   than clip, because this is min-height, not height.

   Only while the desks sit side by side. The line count is published as a
   custom property from the SECTION container — the desk is itself a container,
   so a query written inside it would resolve against the desk's ~371px and
   never match. On tablet and phone the desks stack, nothing needs to align
   across them, and reserving three lines would just be dead space, so the
   property stays 0. */
.tsp-news-grid--more-desk {
	--tsp-lead-lines: 0;
}
@container (min-width: 1041px) {
	.tsp-news-grid--more-desk {
		--tsp-lead-lines: 3;
	}
}
.tsp-news-grid--more-desk .tsp-news-card.is-lead .tsp-story-title {
	min-height: calc(var(--tsp-lead-lines, 0) * 1.28em);
}

/* v1.10.270 — reserve the lead title zone while the desks sit side by side.

   Why a media query here, in a codebase that otherwise uses @container:
   a desk is ~371px wide at desktop (three across) and ~350px stacked on a
   phone. Those are the same number. No query written against the DESK can tell
   the two compositions apart, and the section-level query attempted in .269
   did not take effect. The thing that actually differs is the viewport, and
   this is a decision about the SECTION's column arrangement rather than about
   the desk's own width — so the viewport is the honest signal.

   Three lines is the longest legitimate lead headline at this measure, sized in
   `em` at the headline's own line-height so it tracks the type scale rather
   than a pixel copied from the reference. min-height, not height: a longer
   headline grows the zone instead of clipping.

   Below 1041 the desks stack, nothing needs to align across them, and the
   titles return to their natural height. */
@media (min-width: 1041px) {
	.tsp-news-grid--more-desk .tsp-news-card.is-lead .tsp-story-title {
		min-height: calc(3 * 1.28em);
	}
}

/* v1.10.271 — reserve the supporting headline zone too.

   With the lead zone fixed, rows 1 and 3 and the footer aligned to 0px, but
   row 2 still sat 17-18px apart across desks: exactly one line of supporting
   leading (13.5px x 1.32). One desk's first supporting headline wraps to three
   lines where the others take two, so row 2 started lower in that desk.

   Same remedy as the lead, one level down: reserve three lines rather than
   clamp. The headline stays whole and readable - no line-clamp, no ellipsis,
   no overflow hidden - and rows begin on a shared band because the zone no
   longer depends on how a particular headline happens to wrap.

   Viewport-scoped for the same reason the lead zone is: a desk is ~371px wide
   three-across and ~350px stacked, so the desk's own container cannot tell the
   two compositions apart. Below 1041 the desks stack, nothing aligns across
   them, and the titles take their natural height. */
@media (min-width: 1041px) {
	.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead) .tsp-story-title {
		min-height: calc(2 * 1.32em);
	}
}

/* ==========================================================================
   v1.10.319 — More From Telugu Scope: the supporting rows paid for their
   vertical spacing twice.

   Measured on the live 1920 render, one secondary row decomposed to:

     row 114px = 14 above (13px row padding + 1px rule)
                 + 78 thumbnail
                 + 22 below

   but the CONTENT column measured 87px against the thumbnail's 78 — because
   `.tsp-news-card__content` carries `padding: 10px 0` of its own INSIDE a row
   that already pads 13px top and bottom. Every supporting story therefore
   spent 20px on padding it had already been given, which is the empty band
   under each one.

   v1.10.265 zeroed this element's padding-inline for exactly this desk and for
   exactly this reason ("one axis, not two") — it simply never revisited the
   block axis. This is the other half of that fix.

   It also corrects an alignment error worth more than the pixels: the 10px top
   padding pushed the headline BELOW the thumbnail's top edge, so the two
   columns of a thumbnail+text row did not start on the same line.

   The row's own 13px padding is deliberate and untouched — a previous pass
   recorded that 11px "read as compressed against the separators". Nothing here
   changes the thumbnail, the headline, the date, the separators, the lead
   story, the desk header, View All, the pager or the footer links. */
.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead) .tsp-news-card__content {
	padding-block: 0;
}

/* ==========================================================================
   v1.10.320 — More From Telugu Scope: the desk was running the MOBILE grid on
   desktop, so every story carried a 22px gap under it.

   `.tsp-news-grid--more-desk .tsp-news-grid__items` already asked for
   `display:flex; gap:0`. It never applied at any width where the three desks
   sit side by side, and the reason is the container-query trap this project
   has hit before: container queries measure the CONTAINER, not the viewport.

   Measured on the live 1920 render, each desk's `.tsp-eb-wrap` is 473px wide
   with container-type:inline-size. So

       @container (max-width: 520px)
       .tsp-news-grid[class*="tsp-news-grid--m-"] .tsp-news-grid__items
       { display:grid; gap:22px; grid-template-columns:1fr }

   MATCHES on a 1920 desktop -- 473 < 520 -- and at (0,3,0) it outranks the
   desk's own (0,2,0) rule. The desk has been laid out as a single-column
   mobile grid the whole time, with a 22px row gap after the lead story and
   after every supporting row. That is the remaining white space.

   Fixed by specificity, not by touching the mobile rule -- that rule is correct
   for genuinely narrow single-column grids elsewhere, and the desk simply is
   not one of those even though its container is narrow. (0,4,0) is a clear win
   rather than a source-order tie, because a tie is exactly how the submit
   button lost to Blocksy in v1.10.309.

   The 22px does not vanish from the desk: `.tsp-nav-viewport` keeps
   flex-grow:1, so a desk with fewer stories pools the reclaimed space ONCE at
   its bottom above the pager, which is where unequal-story-count slack is meant
   to go. Equal desk heights, pager alignment, the footer links and independent
   desk paging are all untouched. */
.tsp-eb.tsp-news-grid.tsp-news-grid--more-desk .tsp-news-grid__items {
	display: flex;
	flex-direction: column;
	gap: 0;
}

/* ==========================================================================
   v1.10.366 — MORE FROM TELUGU SCOPE, CONSERVATIVE PHONE COMPACTION
   ========================================================================== */

/* VIEWPORT-SCOPED, NOT CONTAINER-SCOPED. The rest of this desk's responsive
   work is keyed to `@container (max-width: 470px)` because a desk is its own
   container and is narrow at every width. That is exactly why it cannot be used
   here: in the three-column desktop band each desk measures about 380px, so a
   container query fires on the desktop composition too, and the desktop More
   From architecture is frozen. `@media` is the only scope that means "phones".

   Appended at the end of the file on purpose: these selectors tie with the
   `@container` rules above at (0,3,0), so source order is what decides. */
@media (max-width: 781.98px) {

	/* ONE DESTINATION PER DESK. Each desk carried two links to the same category
	   archive -- "View All" in the header and "More Technology" in the footer.

	   The FOOTER one is the keeper, and the header's is the one that goes. Hiding
	   the footer link was tried first and looked wrong the moment it was
	   rendered: the pager was left alone at the left end of a 42px row with the
	   full desk width empty beside it, which reads as a row that failed to load
	   rather than a deliberate one. Keeping the footer CTA balances that row
	   against the arrows, and it is the better label of the two -- "More
	   Technology" names the destination where "View All" only gestures at it.
	   The header is then just the desk's name and its accent rule, which is all
	   a section heading needs. */
	.tsp-news-grid--more-desk .tsp-nav-header .tsp-nav-viewall--more {
		display: none;
	}

	/* The lead still leads. 16:9 on a 316px column is 178px of picture before a
	   reader reaches the second story in the desk; at 2.2:1 it is about 144px
	   and still the widest, most prominent image in the section. Cropping is
	   `object-fit: cover` and centred, so the subject is kept. */
	.tsp-news-grid--more-desk .tsp-news-card.is-lead .tsp-news-card__media {
		aspect-ratio: 2.2 / 1;
	}

	/* `padding-block` only. The horizontal inset is owned by the desk's
	   `--tsp-more-inset` rule further up; a `padding` shorthand here would
	   silently reset it and pull every row out to the card's edge. */
	.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead) {
		padding-block: 8px;
	}
}

/* ==========================================================================
   v1.10.371 — ACROSS INDIA DESKS, HEADLINES THAT FINISH ON PHONES
   ========================================================================== */

/* Same root cause as the briefing, same fix: `-webkit-line-clamp: 2` on
   headlines that need three. Measured at 390 across National, Andhra Pradesh
   and Telangana -- every lead cut ("...surrenders to Telangana police after
   forty years..."), and ten of eleven supporting rows cut. The three desks share
   one component and one cause, so they share one rule.

   The lead's EXCERPT keeps its two lines. It is supporting prose rather than the
   headline, two lines of it already carry the context, and a third would push
   the lead card past the point where the rows below it stay in view. A clamp is
   allowed to remain where what shows already communicates the story.

   `@media`, not `@container`: `.tsp-news-grid--state-desk` declares
   `container-type: inline-size` and sits in a three-column band on desktop, so
   each desk is its own ~380px container there. A container query would repaint
   the frozen desktop composition. */
@media (max-width: 781.98px) {

	/* v1.10.424: 3 > 4 on the supporting cards. On a phone the desk is a single
	   column, so a headline wraps to more lines than it does in the desktop
	   band; measured at 390, three lines cut five of thirteen at 16px and two at
	   14.5px, and four lines cuts none. The lead keeps three — it is larger, so
	   three lines already carry it. */
	.tsp-news-grid--state-desk .tsp-news-card.is-lead .tsp-story-title {
		-webkit-line-clamp: 3;
	}

	.tsp-news-grid--state-desk .tsp-news-card:not(.is-lead) .tsp-story-title {
		-webkit-line-clamp: 4;
	}

	/* ONE DESTINATION PER DESK, and the footer one is the keeper -- the same
	   decision the More From desks reached, but re-tested here rather than
	   copied. Hiding the footer link instead left the pager alone at the left of
	   an otherwise empty row, exactly as it did there. Keeping it balances the
	   row against the arrows, and removing the header link also gives the desk
	   name its width back: "ANDHRA PRADESH" was wrapping to two lines beside
	   "View All" and now sits on one. */
	.tsp-news-grid--state-desk .tsp-state-desk__viewall {
		display: none;
	}
}

/* ==========================================================================
   v1.10.374 — MOVIES SUPPORTING ROWS, ONE MORE LINE ON PHONES
   ========================================================================== */

/* The showcase rows were already at three lines, not two, so this is a smaller
   correction than the audit implied. Two of six live headlines still stopped
   before their meaning arrived, and one of them badly: "'Spider-Man: Brand New
   Day' director Destin Daniel Cretton on capturing" ends exactly where the
   sentence starts to mean something.

   Four lines is the smallest fix that reaches it -- the same headline then
   reads "...on capturing the spectacle without", which is the story. Five would
   finish the sentence outright and cost another 20px a row for the last three
   words; the objective is comprehension, not every word, so it stops at four.

   Row heights are content-sized here (a two-line row measures 86px against a
   three-line row's 99px), so there is no fixed-track trap of the kind the
   Scope Briefing had -- verified: spill is 0 at 360, 375 and 390.

   The overlay LEADS are untouched. They carry no clamp at all and already run
   to four lines when a headline needs it. */
@media (max-width: 781.98px) {
	.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) .tsp-story-title {
		-webkit-line-clamp: 4;
	}
}

/* ==========================================================================
   v1.10.379 — ACROSS INDIA: A CONCISE PHONE LABEL
   ========================================================================== */

/* Both labels are in the heading (see Templates\Section_Labels) and this shows
   one. `display:none` takes the other out of the accessibility tree too, so a
   screen reader is offered exactly one heading at any width — the <h2>, its
   level and its place in the outline never change.

   Wide is the default so that if this stylesheet is ever missing the reader
   still gets the full, accurate title rather than the abbreviation.

   781.98, matching every other phone boundary in the project: `max-width:782`
   and core's `min-width:782` both match at 782. */
.tsp-across-states__t--narrow { display: none; }

@media (max-width: 781.98px) {
	.tsp-across-states__t--wide { display: none; }
	.tsp-across-states__t--narrow { display: inline; }
}

/* A view-all is a control, so it has to be big enough to hit.
 *
 * Measured at 390: these three rendered 19px tall, under WCAG 2.2 SC 2.5.8's
 * 24x24 minimum, while every other view-all already cleared it on the 10px
 * vertical padding it happens to carry. Only these three had none.
 *
 * min-height rather than padding because all three are already flex: centring
 * inside a taller box leaves the text exactly where it was. The showcase and
 * watch rows are 32-44px tall already because of a sibling, so nothing moves
 * there at all. The sports row is the one place the link sits alone, so that
 * row grows 19px -> 24px, which is the whole visible cost of the fix.
 */
.tsp-news-grid--movies-showcase .tsp-nav-viewall--showcase,
.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-nav-viewall--watch,
.tsp-eb.tsp-news-grid--sports-showcase .tsp-nav-viewall--sports {
	min-height: 24px;
	align-items: center;
}

/* v1.10.421 — the iOS 16px rule and the consent notice both moved to
 * assets/css/scope-briefing.css, where the article placement reads the same
 * declarations instead of a second copy of them. The consent colour also
 * changed there: 78% white on #C8102E measures ~3.97:1, under AA for 12px text,
 * and is now 88% at ~4.8:1. */

/* v1.10.421 — the white-in-all-states field rules, the autofill treatment and
 * the white focus ring that used to close this file are gone. They existed here
 * AND verbatim in article.css, and that is exactly how the focus-ring fix got
 * written into article.css and never reached the homepage: an article does not
 * load blocks.css and the homepage does not load article.css, so one of the two
 * copies is always the one you did not edit. They live once now, in
 * assets/css/scope-briefing.css, which both placements depend on. */

/* ==========================================================================
   v1.10.425 — mobile headline composition. One intentional rule per family.

   Measured first, on the rendered homepage: for every real headline, the
   narrowest text column that fits it in two lines and in three, against the
   width its card actually gives it. Several families were only a handful of
   pixels short of a three-line fit, which is a geometry problem — the
   thumbnail track was simply taking too much of a narrow row. None of these
   change a font size, and none of them hide more text.

   Fenced at 380 because below it these cards collapse to a single column and
   a two-track template would put the headline in the thumbnail slot. That is
   not hypothetical: an earlier draft of this pass did exactly that and cut the
   state-desk headline column from 258px to 162px at 320.
   ========================================================================== */
@media (max-width: 380px) {
	/* Movies: 180px given, 172px needed for three lines. 88 > 72 clears it. */
	.tsp-news-grid--movies-showcase .tsp-news-card:not(.is-lead) > a {
		grid-template-columns: 72px minmax(0, 1fr);
	}
	/* More From: 177px given, 188px needed — the closest miss on the page. */
	.tsp-news-grid--more-desk .tsp-news-card:not(.is-lead) > a {
		grid-template-columns: 48px minmax(0, 1fr);
	}
}

/* State desk supporting: 205px given at 375, 207px needed. Two pixels. Fenced
   above 380 because at 320 this card is already single-column and full width. */
@media (min-width: 381px) and (max-width: 480px) {
	.tsp-news-grid--state-desk .tsp-news-card:not(.is-lead) > a {
		grid-template-columns: 84px minmax(0, 1fr);
	}
}

/* Watch supporting is the one family geometry cannot fully rescue at 320: its
   headlines run 87 characters at the median and 100 at the longest, and three
   lines need 205px in a row that is only 280px wide in total. The thumbnail is
   already down to 26% there. Rather than shrink the picture to a stamp or the
   type below the approved size, the narrowest tier is allowed a fourth line —
   which shows MORE of the headline, not less. Above 380 the widened track
   carries it in three. */
@media (max-width: 380px) {
	.tsp-eb.tsp-video-grid.tsp-video-grid--featured-row .tsp-video-card:not(.is-featured) h3 {
		-webkit-line-clamp: 4;
	}
}

/* v1.10.430 — ticker headlines meet the minimum target size.
 *
 * Measured on staging at 390: each ticker link is a bare inline anchor 18px
 * tall, under the 24px floor WCAG 2.5.8 sets for a pointer target. The links
 * are wide (366-474px), so only the vertical dimension fails — an inline box
 * takes its height from the line box and nothing was giving it any.
 *
 * inline-flex with a min-height rather than padding: the track is a fixed-height
 * flex row with a running marquee, and vertical padding on the anchor would
 * push the separator dot off centre. This changes the hit area only; the type,
 * the spacing and the animation are untouched. */
.tsp-news-ticker__track a {
	display: inline-flex;
	align-items: center;
	min-height: 24px;
}

/* v1.10.430 — Sports supporting rows drop the redundant category chip.
 *
 * Measured across the four compact-row families on the homepage at 390:
 *
 *   sports-showcase   6 rows, kicker rendered, ALL SIX read "Sports"
 *   movies-showcase   6 rows, no kicker
 *   state-desk        3 rows, no kicker
 *   more-desk         2 rows, no kicker
 *
 * So Sports is the only one of the four that labels its supporting stories, and
 * the label repeats the section heading immediately above them six times over.
 * It carries no information a reader does not already have, and on a phone it
 * costs 20px a row — 120px of scrolling for nothing.
 *
 * Scoped to supporting rows only: the LEAD card keeps its kicker, exactly as
 * the other three families do. Nothing else about the row changes. */
.tsp-eb.tsp-news-grid--sports-showcase .tsp-news-card:not(.is-lead) .tsp-eb-category {
	display: none;
}

/* ==========================================================================
   v1.10.446 — a column whose block renders nothing must not reserve space.

   The homepage lays Hero and The Scope Briefing side by side as a Gutenberg
   two-column row: 60% and 40% of a 1200px container. Since v1.10.445 a section
   with no stories renders nothing at all for a reader, which is right — but the
   COLUMN it lived in is theme markup and knows nothing about that, so it kept
   its 40% track.

   Measured on Telugu staging at 1440: the Briefing column was 454px wide, 0
   element children, 0 bytes of markup, and the Hero was pinned to 682px beside
   it with roughly a third of the page blank. The Hero is the lead image of the
   front page; there is no reading of that composition where it should be
   two-fifths narrower because a neighbour has nothing to say.

   `:has()` rather than `:empty`, because a column left with only whitespace
   text nodes is not `:empty` and that is exactly the shape WordPress emits.

   SCOPED to rows that actually contain one of our sections. An empty column is
   a legitimate layout device — people use them as spacers — so this must not
   become a global rule that collapses somebody's deliberate gutter. A row
   pairing a Platform section with a genuinely empty column is not that. */
.wp-block-columns:has(> .wp-block-column .tsp-hero-wrap, > .wp-block-column .tsp-eb-wrap, > .wp-block-column .tsp-sidebar-wrap)
	> .wp-block-column:not(:has(*)) {
	display: none;
}

/* `flex-grow`, NOT `flex-basis`.
 *
 * Gutenberg writes the column width as an INLINE `style="flex-basis:60%"`, so a
 * stylesheet cannot override it without `!important` — and the one sanctioned
 * `!important` in this project is the editor sheet, for reasons documented in
 * ARCHITECTURE.md. Nothing sets `flex-grow` inline, so asking the surviving
 * column to grow reaches the same result through a property that is actually
 * ours to set: the basis stays 60%, the collapsed sibling frees the other 40%,
 * and the column takes it. Verified at 1440 — 696px to the full 1200px
 * container. */
/* No sibling test, because `:has()` CANNOT BE NESTED inside `:has()`.
 *
 * The obvious way to write this was
 * `.wp-block-columns:has(> .wp-block-column:not(:has(*))) > …`, which is
 * invalid CSS: a `:has()` inside a `:has()` argument makes the whole selector
 * unparseable, so the browser drops the rule silently. The column collapsed and
 * the Hero stayed 696px, which looked like a specificity problem and was not.
 *
 * The condition turns out to be unnecessary anyway. When both columns are
 * present their bases already sum to 100% (60 + 40) and the gap pushes them
 * over it, so there is no free space and `flex-grow` does nothing. It only has
 * an effect in exactly the case this is for: a sibling collapsed and left room. */
/* The selector has to out-specify CORE, which says the opposite.
 *
 * wp-block-library ships, inline in the head:
 *
 *   @media (min-width: 782px) {
 *     .wp-block-columns:not(.is-not-stacked-on-mobile)
 *       > .wp-block-column[style*="flex-basis"] { flex-grow: 0; }
 *   }
 *
 * — (0,4,0), and deliberately so: a column given an explicit basis is not
 * supposed to grow. That is right in general and wrong in the one case here,
 * where the sibling sharing the row has been removed entirely.
 *
 * A plain `.wp-block-columns > .wp-block-column:has(…)` is only (0,3,0) —
 * `:has()` contributes its most specific ARGUMENT, a single class — so core
 * won and the rule did nothing while appearing to match. Mirroring core's own
 * shape and adding the `:has()` on top makes it (0,5,0), which wins on
 * specificity rather than on source order or `!important`. */
.wp-block-columns:not(.is-not-stacked-on-mobile)
	> .wp-block-column[style*="flex-basis"]:has(.tsp-hero-wrap, .tsp-eb-wrap, .tsp-sidebar-wrap) {
	flex-grow: 1;
}

/* ==========================================================================
   v1.10.568 — the page shell for a template that renders blocks on its own.

   WHY THIS EXISTS. Blocks like these normally sit inside the theme's
   `.ct-container`, which is what gives them their width: measured on the
   homepage at 1440, `.tsp-eb` renders 1200px wide starting at x=120. When
   `/sections/` got its own template in v1.10.567 — to stop Blocksy printing a
   second <h1> — that container went with the entry-header, and the page went
   full bleed: every column flush to the viewport edge at x=0, 1440px wide.

   The numbers here are the homepage's, so a page rendering these blocks through
   the platform's own template lands exactly where the same blocks land through
   the theme's. It is stated in the plugin rather than borrowed from
   `.ct-container`, so a template that opts out of the theme's page markup does
   not quietly depend on the theme's page markup.

   Nothing else uses this class, so it cannot affect a page that did not ask. */
.tsp-page-shell {
	max-width: 1200px;
	margin-inline: auto;
	/* v1.10.569: the gutter, which the first version left out. Constraining the
	   WIDTH alone looked right at 1440 and was wrong everywhere below 1200: with
	   no container left to supply padding, the breadcrumb, the title, the intro
	   and every headline sat flush against the left edge of a 390px phone.

	   The theme's container supplied both, and only the max-width was replaced.
	   With the padding back, this page measures 1160px at x=140 on desktop —
	   which is the category and corporate shell exactly, and the right family for
	   a page that opens with a breadcrumb and a title rather than a full-bleed
	   hero. */
	padding-inline: var(--tsp-gutter, 20px);
	box-sizing: border-box;
}

/* ==========================================================================
   v1.10.673 — the hero needs the ticker's space back when there is no ticker.

   The News Ticker renders NOTHING when no story qualifies as breaking — not an
   empty bar, not a wrapper, nothing. That is the right behaviour and stays.
   But the ticker also carries `margin-bottom: 24px`, which is the theme's own
   block gap (--wp--style--block-gap: 1.5em), and that margin is what holds the
   hero clear of the masthead's red rule. With the ticker gone the margin goes
   with it, and the first block lands 3px under the rule instead of 24px.

   Measured on staging at 1440: with a ticker the hero starts at y=254, a clean
   24px below it. With no ticker the hero starts at y=183 against a masthead
   ending at y=180.

   So the space is restored as the ticker's own 24px rather than a new invented
   number. See the note on the declaration for why that is spelled 1.5rem, and
   for a rationale that was corrected after it was first written.

   :has() is load-bearing and deliberate. The rule must fire ONLY when the hero
   is the first thing on the page; a plain :first-child would also match the
   ticker when it IS present and push the whole ticker down, changing a layout
   that is already signed off. Where :has() is unsupported the rule is dropped
   whole and the page renders exactly as it does today - no worse, never broken.
   ========================================================================== */
.entry-content > :first-child:has(.tsp-hero-wrap),
.entry-content > .tsp-hero-wrap:first-child{
	/* 1.5rem = the ticker's own 24px. The theme token --wp--style--block-gap
	   is `1.5em` and resolves to the same 24px here, measured: this columns
	   block computes at 16px, as does the root. rem is used only because it
	   cannot be knocked off by a later font-size change on an ancestor.
	   The rendered gap reads 27px, which is this 24px plus a 3px offset that
	   already sits between the masthead and the content area - the ticker
	   gets that same 3px when it renders. */
	margin-top: 1.5rem;
}
