/* Key card: one frame on every desk, the card as its own full-height section, the contract column beside it.
   These rules take the desk layout over from the older card compositions when the key card is active, at the
   specificity the older rules use. Per-desk accent colours the Read report button. */
.zw-page[data-news-keycard]{--zk-surface:#10151c;--zk-rule:#ffffff1a;--zk-muted:#ffffff;--zk-accent:#6fb3ff;--zk-frame:#0b1016;--zk-land:#1d2733;--zk-bar:#34414f}
.zw-page[data-news-keycard][data-channel=econ]{--zk-accent:#6fb3ff}
.zw-page[data-news-keycard][data-channel=crypto]{--zk-accent:#f2c57c}
.zw-page[data-news-keycard][data-channel=sport]{--zk-accent:#ef8a8a}
.zw-page[data-news-keycard][data-channel=pol]{--zk-accent:#4a8fdf}
.zw-page[data-news-keycard][data-channel=culture]{--zk-accent:#d9a5e8}
.zw-page[data-news-keycard][data-channel=world]{--zk-accent:#8fd3c7}
/* G6 (round 4): colour carries meaning, so the action never wears a party's colour beside a graphic keyed by party. On
   Politics the desk's blue is the Democratic key, and any card whose graphic keys colour by party (a map, a tally, seat
   bars, wherever the card is listed) draws Read report in the neutral ink no party key uses (the ink the seat-count key
   is drawn in, which belongs to neither party). */
.zw-page[data-news-keycard][data-channel=pol],.zk-card:has([data-party],[data-seat]){--zk-action:#eef1f5}

/* The desk header stays short; the card is the section. The category bar stays reachable while reading. */
.zw-page[data-news-keycard] .zw-heading h1{font-size:22px}
.zw-page[data-news-keycard] .zw-edition-tools{padding:4px 0 8px}
/* The subcategory row pins under the category bar: category and subcategory stay in reach while the card is the
   section in view. Its gutters are the page's own, measured by home-news.js fitWorkspace. */
/* The story controls live in the subcategory row on every News page, on one line at every width. */
html[data-news-view] .zw-page>.zw-edition-tools>.zw-desk-actions{display:flex;align-items:center;gap:6px;flex:none;margin-left:auto}
html[data-news-view] .zw-page>.zw-edition-tools>.zw-edition-source{margin-left:0;flex:none}
html[data-news-view] .zw-page>.zw-edition-tools{flex-wrap:nowrap}
html[data-news-view] .zw-page>.zw-edition-tools>.zw-filters{flex:1 1 auto;flex-basis:auto;order:0;min-width:0;width:auto}
html[data-news-view] #bfBoard:has(.zw-page[data-news-keycard]){scroll-padding-top:calc(var(--zc-bar-height,0px) + var(--zw-tools-height,0px) + 8px)}
html[data-news-view] .zw-page[data-news-keycard]>.zw-edition-tools{position:sticky;top:var(--zc-bar-height,0px);z-index:5;background:var(--bg,#0b0d10);margin-inline:calc(-1 * var(--zw-page-pad-l,12px)) calc(-1 * var(--zw-page-pad-r,12px));padding-inline:var(--zw-page-pad-l,12px) var(--zw-page-pad-r,12px)}

/* Workspace: card | contract column, both the full section height. */
html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]{height:var(--zw-card-height,auto)!important;min-height:0!important;max-height:none!important;align-items:stretch!important;grid-template-columns:minmax(0,1.6fr) minmax(330px,.8fr)!important;gap:24px!important;padding:14px 0 10px;border-bottom:0!important;overflow:hidden}
html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-focus{display:flex!important;flex-direction:column;flex:1 1 auto!important;align-self:stretch!important;height:auto!important;min-height:0!important;max-height:none!important;padding:24px 28px 20px!important;box-sizing:border-box;background:var(--zk-surface);border-radius:12px;overflow:hidden}
.zk-col-label{display:block;flex:none;margin:0 0 14px;font:500 var(--zt-label,11px)/1.4 var(--sans,Arial);color:var(--zk-muted)}
html[data-news-view] .zw-page[data-news-keycard] .zw-focus>.zw-story-header{flex:none;display:block}
.zw-page[data-news-keycard] .zw-story-header h2{font:500 clamp(24px,2.1vw,32px)/1.15 var(--sans,Arial);letter-spacing:-.02em;margin:0}
.zw-page[data-news-keycard] .zw-story-header h2 button{all:unset;cursor:pointer;color:inherit;font:inherit;text-wrap:pretty}
.zw-page[data-news-keycard] .zw-story-copy>p{margin-top:8px;font-size:13px;color:var(--zk-muted)}
/* The publisher's name and the time are each one unbroken phrase ("11:10 PM" never splits); the line wraps between
   them. A name longer than the whole line still wraps inside itself rather than running off the screen (L5). */
.zw-page[data-news-keycard] .zw-story-byline>span{display:inline-block;max-width:100%}
.zw-page[data-news-keycard] .zw-story-byline>span+span{white-space:nowrap}
/* On a phone an agency is named by the short form it uses itself ("SEC / Nov 4, 11:28 AM"), so the publisher line stays
   one line and the graphic keeps the room (L5 allows a short form on a phone; L6). The full name is kept for wider
   screens; the short one carries the hidden attribute until a phone shows it. */
@media (max-width:600px){.zw-story-byline .zw-byline-full{display:none}.zw-story-byline .zw-byline-short[hidden]{display:inline}}
html[data-news-view] .zw-page[data-news-keycard] .zw-focus>.zs-story-body{display:flex!important;flex-direction:column;flex:1 1 auto!important;min-height:0!important;margin-top:10px}
html[data-news-view] .zw-page[data-news-keycard] .zs-story-body>.zs-report-card{display:flex!important;flex-direction:column;flex:1 1 auto!important;align-self:stretch!important;min-height:0!important;height:auto!important;max-height:none!important;background:transparent!important;border-radius:0;overflow:visible}
.zw-page[data-news-keycard] .zs-report-card>.zs-card-impact,.zw-page[data-news-keycard] .zs-story-actions{display:none!important}
html[data-news-view] .zw-page[data-news-keycard] .zs-report-card>.zk-card{display:flex!important;flex-direction:column;flex:1 1 auto!important;min-height:0!important;height:auto!important;max-height:none!important;padding:0!important;background:transparent!important;aspect-ratio:auto!important;overflow:visible}

/* The story's own sentence, once, under the headline. */
.zk-sub{flex:none;margin:0 0 4px;max-width:72ch;font:400 16px/1.5 var(--sans,Arial);color:#fff;text-wrap:pretty}

/* Stage: the graphic as large as the card allows, its detail column beside it with the actions at its foot. */
.zk-stage{display:grid;grid-template-columns:minmax(0,1.85fr) minmax(220px,.8fr);gap:12px 32px;align-items:stretch;flex:1 1 auto;min-height:0;padding:14px 0 0}
.zk-stage[data-zk-form=map]{grid-template-columns:minmax(0,2.3fr) minmax(210px,.75fr)}
.zk-stage-wide{grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr) auto}
html[data-news-view] .zw-page[data-news-keycard] .zk-stage>.zk-graphic{display:flex!important;flex-direction:column;justify-content:center;min-width:0;min-height:0;height:100%;margin:0;color:#fff}
html[data-news-view] .zw-page[data-news-keycard] .zk-graphic>*:first-child{flex:1 1 auto!important;min-height:0!important}
html[data-news-view] .zw-page[data-news-keycard] .zk-graphic svg{width:100%;height:100%;min-height:0}
.zk-graphic>figcaption{display:none}
.zk-graphic>figcaption.zk-caption{display:block;flex:none;margin-top:8px;font:400 12px/1.4 var(--sans,Arial);color:var(--zk-muted)}
.zk-side{display:flex;flex-direction:column;justify-content:space-between;gap:14px;min-width:0;min-height:0;overflow:hidden}
.zk-side-body{display:flex;flex-direction:column;justify-content:center;gap:14px;flex:1 1 auto;min-height:0;overflow:hidden}
.zk-facts{display:grid;gap:8px;margin:0;padding:12px 0 0;border-top:1px solid var(--zk-rule)}
.zk-facts>div{display:flex;justify-content:space-between;gap:12px;min-width:0}
.zk-facts dt{font:400 13px/1.4 var(--sans,Arial);color:var(--zk-muted)}
/* A figure is never split inside its number (L5): the value breaks only between words ("+$52.7" / "billion"), so its
   column is at least its longest word wide and the label beside it takes the wrapping. */
.zk-facts dd{margin:0;font:500 14px/1.4 var(--sans,Arial);color:#fff;text-align:right;overflow-wrap:break-word}
/* L5 (round 2): in a detail column too narrow for a label and its value side by side (under 260px: the 1440 and the
   tablet card), each label sits over its value, so a figure keeps its unit on its line ("$135.9 billion") and a label is
   never crushed to a word a line. */
.zk-side-body{container:zk-detail/inline-size}
@container zk-detail (max-width:259px){
  .zk-facts>div{flex-direction:column;justify-content:flex-start;gap:2px}
  .zk-facts dd{text-align:left}
  .zg-row.zg-row-text{grid-template-columns:minmax(0,1fr);gap:2px}
  .zg-row.zg-row-text>b{text-align:left}
}
.zk-read{padding-top:12px;border-top:1px solid var(--zk-rule)}
.zk-read>span{display:block;font:500 var(--zt-text,11px)/1.4 var(--sans,Arial);color:var(--zk-muted);margin-bottom:6px}
.zk-read>p{margin:0 0 4px;font:400 14px/1.5 var(--sans,Arial);color:#fff}

/* Actions, at the foot of the detail column: Read report in the desk's colour, the source under it. */
.zk-actions{flex:none;display:flex;flex-direction:column;align-items:stretch;gap:8px;padding:0;border:0}
.zk-actions>a.zs-report-source{align-self:center;color:var(--zk-muted);font:400 13px/1.4 var(--sans,Arial);text-decoration:none}
.zk-actions>a.zs-report-source:hover{color:#fff}
.zk-actions>.zk-read-report{display:flex;align-items:center;justify-content:center;gap:10px;min-height:44px;padding:0 20px;border:0;border-radius:7px;background:var(--zk-action,var(--zk-accent));color:#0b0d10!important;font:500 15px/1 var(--sans,Arial);cursor:pointer;text-decoration:none}
.zk-actions>.zk-read-report:hover{filter:brightness(1.08)}
.zk-actions>.zk-read-report:focus-visible{outline:2px solid #fff;outline-offset:3px}

/* Detail block (the focused race, the game line, the leading outcome). */
.zg-focus{display:flex;flex-direction:column;gap:6px;min-width:0;font-family:var(--sans,Arial)}
.zg-focus-state{display:block;font:500 clamp(22px,1.9vw,28px)/1.15 var(--sans,Arial);letter-spacing:-.02em;color:#fff}
.zg-focus-office{display:block;font:400 13px/1.4 var(--sans,Arial);color:var(--zk-muted,#fff);margin-bottom:6px}
.zg-row{display:grid;grid-template-columns:12px minmax(0,1fr) auto auto;gap:10px;align-items:center;font:400 15px/1.35 var(--sans,Arial);color:#fff}
.zg-row-wide{grid-template-columns:minmax(0,1fr) auto}
.zg-row>i,.zg-legend i{display:inline-block;width:10px;height:10px;border-radius:50%;background:#9aa3ad;flex:none}
.zg-row>i[data-party=D],.zg-legend i[data-party=D]{background:#4a8fdf}.zg-row>i[data-party=R],.zg-legend i[data-party=R]{background:#df555c}.zg-row>i[data-party=none],.zg-legend i[data-party=none]{background:#1b232d;border:1px solid #ffffff33}
.zg-row>b{font:500 22px/1.1 var(--sans,Arial);letter-spacing:-.02em;text-align:right}
.zg-row>small{color:var(--zk-muted,#fff);font-size:12px}
.zg-focus-note{display:block;margin-top:4px;font:400 12px/1.45 var(--sans,Arial);color:var(--zk-muted,#fff)}
.zg-legend{display:flex;flex-wrap:wrap;gap:6px 16px;margin-top:10px;font:400 12px/1.4 var(--sans,Arial);color:var(--zk-muted,#fff)}
.zg-legend>span{display:inline-flex;align-items:center;gap:7px}

/* Graphics */
.zg-map-wrap{display:flex;flex-direction:column;min-height:0;height:100%}
.zg-map{width:100%;height:100%;min-height:0;flex:1 1 auto}
.zg-map path{fill:#1b232d;stroke:#10151c;stroke-width:1.2px;vector-effect:non-scaling-stroke}
.zg-map path[data-party=D]{fill:#4a8fdf}.zg-map path[data-party=R]{fill:#df555c}.zg-map path[data-party=O]{fill:#9aa3ad}.zg-map path[data-party=neutral]{fill:#3a4553}
.zg-map path[data-named=true]{stroke:#fff;stroke-width:1.6px}
.zg-map path[data-focus=true]{stroke:#fff;stroke-width:2.6px}

.zg-scoreline{display:flex;flex-direction:column;justify-content:center;height:100%;gap:14px;font-family:var(--sans,Arial)}
.zg-status{font:500 12px/1.4 var(--sans,Arial);color:var(--zk-muted,#fff)}
.zg-sides,.zg-matchup{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:16px;height:100%}
.zg-side{display:flex;flex-direction:column;align-items:center;text-align:center;gap:8px;min-width:0}
.zg-side>img{width:min(96px,22cqw,14vh);height:auto;aspect-ratio:1;object-fit:contain}
.zg-matchup .zg-side>img{width:clamp(96px,11vw,160px);max-height:22vh}
.zg-side>strong{font:500 clamp(17px,1.5vw,24px)/1.15 var(--sans,Arial);letter-spacing:-.02em}
.zg-side>small{font-size:13px;color:var(--zk-muted,#fff)}
.zg-score{font:500 clamp(40px,4.4vw,64px)/1 var(--sans,Arial);letter-spacing:-.03em}
.zg-vs{font:400 14px/1 var(--sans,Arial);color:var(--zk-muted,#fff)}
.zg-detail{font:400 13px/1.4 var(--sans,Arial);color:var(--zk-muted,#fff)}

.zg-rings{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px 20px;align-items:center;justify-items:center;height:100%}
.zg-rings[data-count="3"]{grid-template-columns:repeat(3,minmax(0,1fr))}
.zg-ring{display:flex;flex-direction:column;align-items:center;gap:6px;min-width:0;font-family:var(--sans,Arial)}
.zg-ring>svg{width:min(100%,150px,22vh);height:auto}
.zg-ring-track{fill:none;stroke:#ffffff22;stroke-width:7}
.zg-ring-arc{fill:none;stroke:#fff;stroke-width:7;stroke-linecap:round}
.zg-ring[data-index="1"] .zg-ring-arc{stroke:#9bc4ff}.zg-ring[data-index="2"] .zg-ring-arc{stroke:#f2c57c}.zg-ring[data-index="3"] .zg-ring-arc{stroke:#ef8a8a}
.zg-ring-abbr{fill:#fff;font:500 22px var(--sans,Arial)}
.zg-ring>b{font:500 26px/1 var(--sans,Arial);letter-spacing:-.02em}
.zg-ring>span{font-size:13px;color:var(--zk-muted,#fff)}
/* Open item 3: the ring's key names what its arc measures (the playoff chance, or the wins of the games played), in
   the label ink, under the record. */
.zg-ring-key{font:400 13px/1.3 var(--sans,Arial);color:var(--zk-muted,#fff);white-space:nowrap;font-variant-numeric:tabular-nums}
/* Record rings at the graphic's size (S5 Games, League, and the Players fallback): each ring fills its cell, and one
   club alone fills the graphic with its crest inside, never a small logo in an empty frame (S7). */
.zg-rings{grid-auto-rows:minmax(0,1fr);min-height:0}
.zg-rings[data-count="1"]{grid-template-columns:minmax(0,1fr)}
.zg-rings[data-count="4"]{grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}
.zg-ring{height:100%;width:100%;min-height:0;justify-content:center}
html[data-news-view] .zw-page[data-news-keycard] .zk-graphic .zg-ring>svg{flex:1 1 0;width:100%;height:auto;min-height:0;max-height:260px}
html[data-news-view] .zw-page[data-news-keycard] .zk-graphic .zg-rings[data-count="1"] .zg-ring>svg{max-height:340px}
.zg-rings[data-count="1"] .zg-ring>b{font-size:clamp(28px,2.6vw,40px)}
.zg-rings[data-count="1"] .zg-ring>span{font:500 clamp(16px,1.4vw,20px)/1.2 var(--sans,Arial);color:#fff;text-align:center}
.zg-crest-tile{flex:1 1 auto;min-height:0;max-height:300px;aspect-ratio:1;display:grid;place-items:center;padding:clamp(14px,2vw,28px);border-radius:24px;background:#fff;box-sizing:border-box}
.zg-crest-tile>img{width:100%;height:100%;object-fit:contain}
/* The detail block's rows: a club's dot is its ring's colour; the club's record ring is drawn small beside its record;
   dates are their own element so the count-up never runs over them. */
.zg-row>i[data-ring="0"]{background:#fff}.zg-row>i[data-ring="1"]{background:#9bc4ff}.zg-row>i[data-ring="2"]{background:#f2c57c}.zg-row>i[data-ring="3"]{background:#ef8a8a}
.zg-row>time{font:500 17px/1.25 var(--sans,Arial);color:#fff;text-align:right}
.zg-row-when{grid-template-columns:auto minmax(0,1fr);align-items:baseline}
/* A player's rows are words (Full practice, Wide receiver), set a step smaller than a count so four rows fit the column. */
.zg-focus-player .zg-row>b{font-size:18px;line-height:1.25}
/* A row the report does not supply ("Not stated in the report") keeps the row's own type and wraps beside its label, so
   every Players card shows the same four rows in one hand at every width (S1, L5). */
.zg-focus-player .zg-row-none{grid-template-columns:auto minmax(0,1fr);align-items:baseline}
.zg-focus-player .zg-row-none>b{overflow-wrap:break-word}
/* A Games block's named player and the status the report gives: words, set like a Players row. */
.zg-row-player{align-items:baseline}.zg-row-player>b{font-size:18px;line-height:1.25}
/* The scorebug's two rows share the graphic's height up to a cap, so the score is the card's main event at every frame
   (L6) and never a strip in an empty slot. */
.zg-scoreline>.zg-scorebug{flex:1 1 auto;min-height:0;max-height:300px}.zg-scorebug>.zg-score-row{flex:1 1 0}
/* When the club's own ring fills the photograph's slot, the block does not print the same record again (G6). */
.zk-stage:has(.zg-portrait-frame[data-zk-filled=reserve]) .zg-focus-player .zg-row-ring{display:none}
.zg-row-ring{grid-template-columns:minmax(0,1fr) auto auto}
.zg-mini-ring{width:26px;height:26px;flex:none}
.zg-mini-ring .zg-ring-track,.zg-mini-ring .zg-ring-arc{stroke-width:5}

.zg-series{display:flex;flex-direction:column;height:100%;min-height:0;font-family:var(--sans,Arial)}
.zg-series-head{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin-bottom:8px}
.zg-series-head>span{font:400 13px/1.4 var(--sans,Arial);color:var(--zk-muted,#fff);flex:1 1 auto;min-width:0}
.zg-series-head>b{font:500 26px/1 var(--sans,Arial);letter-spacing:-.02em}
.zg-series-head>small{font-size:13px;color:var(--zk-muted,#fff)}
/* The line takes what the frame's graphic track leaves (L2); it never holds a height of its own that the frame would clip. */
.zg-series>svg{flex:1 1 auto;width:100%;min-height:0}
.zg-grid{stroke:#ffffff14;stroke-width:1}
.zg-line{fill:none;stroke:#fff;stroke-width:2;vector-effect:non-scaling-stroke}
.zg-mark{stroke:#9bc4ff;stroke-width:1.5;stroke-dasharray:4 4;vector-effect:non-scaling-stroke}
.zg-mark-dot{fill:#9bc4ff}
.zg-last{fill:#fff}
.zg-axis{display:flex;justify-content:space-between;font:400 12px/1.4 var(--sans,Arial);color:var(--zk-muted,#fff);margin-top:6px}
.zg-axis-mark{color:#fff}
.zg-source{display:block;margin-top:6px;font:400 12px/1.4 var(--sans,Arial);color:var(--zk-muted,#fff)}

.zg-ladder,.zg-odds{display:flex;flex-direction:column;justify-content:center;gap:10px;height:100%;font-family:var(--sans,Arial)}
.zg-ladder-title{font:400 13px/1.4 var(--sans,Arial);color:var(--zk-muted,#fff);margin-bottom:4px}
.zg-rung{display:grid;grid-template-columns:minmax(110px,.9fr) minmax(0,1.6fr) auto auto;align-items:center;gap:12px;font:400 14px/1.3 var(--sans,Arial)}
/* A rung's name carries meaning, so it wraps under itself, never ends in an ellipsis (L5). */
.zg-rung>span{min-width:0;overflow-wrap:break-word}
.zg-rung>i{display:block;height:12px;border-radius:3px;background:#ffffff1f;position:relative;overflow:hidden}
.zg-rung>i::after{content:'';position:absolute;inset:0;width:var(--w,0%);background:#fff;border-radius:3px;transform-origin:left center}
.zg-rung>b{font:500 17px/1 var(--sans,Arial);min-width:48px;text-align:right}
.zg-rung>small{font-size:12px;color:var(--zk-muted,#fff);min-width:68px;text-align:right}

.zg-figure{display:flex;flex-direction:column;justify-content:center;gap:4px;height:100%;font-family:var(--sans,Arial)}
.zg-figure-label{font:400 14px/1.4 var(--sans,Arial);color:var(--zk-muted,#fff)}
.zg-figure-value{font:500 clamp(48px,6vw,88px)/1 var(--sans,Arial);letter-spacing:-.04em}
.zg-figure>small{font-size:13px;color:var(--zk-muted,#fff)}
.zg-direction{display:inline-block;margin-top:6px;font:500 13px/1.4 var(--sans,Arial);color:#fff}
.zg-figure>dl{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:8px 18px;margin:16px 0 0;padding-top:12px;border-top:1px solid var(--zk-rule,#ffffff1a)}
.zg-figure dt{font-size:12px;color:var(--zk-muted,#fff)}.zg-figure dd{margin:2px 0 0;font:500 17px/1.3 var(--sans,Arial)}

/* The timeline (W5): its words are HTML in one ink, so they never shrink with a drawing; the track keeps each date at
   its place, "Now" is anchored over its mark without leaving the frame, and the dates are listed under the track. */
.zg-timeline{display:flex;flex-direction:column;justify-content:center;gap:8px;height:100%;min-width:0}
.zg-tl-track{display:block;flex:none;width:100%;height:28px;overflow:visible}
html[data-news-view] .zw-page[data-news-keycard] .zk-graphic .zg-timeline>svg.zg-tl-track{height:28px}
.zg-timeline .zg-line{stroke:#ffffff55}
.zg-point{fill:#fff}
.zg-tl-now{align-self:flex-start;position:relative;left:calc(var(--x) * 1%);transform:translateX(calc(var(--x) * -1%));font:500 13px/1.3 var(--sans,Arial);color:#fff}
.zg-tl-labels{display:grid;grid-template-columns:repeat(var(--n),minmax(0,1fr));gap:12px;margin:0;padding:0;list-style:none}
.zg-tl-labels>li{display:flex;flex-direction:column;gap:2px;min-width:0;text-align:center;overflow-wrap:anywhere}
.zg-tl-labels>li:first-child{text-align:left}.zg-tl-labels>li:last-child:not(:first-child){text-align:right}
.zg-tl-label{font:400 13px/1.35 var(--sans,Arial);color:#fff}
.zg-tl-date{font:500 13px/1.35 var(--sans,Arial);color:#fff}

.zg-photo{margin:0;display:flex;flex-direction:column;height:100%;min-height:0}
.zg-photo>img{flex:1 1 auto;min-height:0;width:100%;object-fit:cover;border-radius:8px}
.zg-photo>figcaption{margin-top:8px;font:400 12px/1.4 var(--sans,Arial);color:var(--zk-muted,#fff)}
.zg-photo a{color:inherit}
.zg-text{display:flex;flex-direction:column;justify-content:center;height:100%;gap:10px;font-family:var(--sans,Arial)}
.zg-text>span{font:400 12px/1.4 var(--sans,Arial);color:var(--zk-muted,#fff)}
.zg-text>p{margin:0;font:500 clamp(20px,2vw,30px)/1.25 var(--sans,Arial);letter-spacing:-.02em;max-width:34ch}
.zg-text>small{font:400 13px/1.4 var(--sans,Arial);color:var(--zk-muted,#fff)}
.zg-text>img{flex:1 1 auto;min-height:0;width:100%;object-fit:cover;border-radius:8px}

/* Motion on a new card: arcs and lines draw, bars grow. Nothing fades. */
@keyframes zk-draw{to{stroke-dashoffset:0}}
@keyframes zk-grow{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes zk-trace{0%{stroke-width:1.2}60%{stroke-width:3.4}100%{stroke-width:2.6}}
.zk-enter .zg-ring-arc{stroke-dasharray:330;stroke-dashoffset:330;animation:zk-draw .9s cubic-bezier(.2,.7,.2,1) forwards}
.zk-enter .zg-line{stroke-dasharray:2600;stroke-dashoffset:2600;animation:zk-draw 1.1s cubic-bezier(.2,.7,.2,1) forwards}
.zk-enter .zg-rung>i::after{animation:zk-grow .7s cubic-bezier(.2,.7,.2,1) both}
.zk-enter .zg-map path[data-focus=true]{animation:zk-trace .8s ease-out both}
@media(prefers-reduced-motion:reduce){.zk-enter .zg-ring-arc,.zk-enter .zg-line,.zk-enter .zg-rung>i::after,.zk-enter .zg-map path[data-focus=true]{animation:none;stroke-dashoffset:0;transform:none}}

/* Contract column: only what belongs to the story (C12), the market card first. C13: it never scrolls. It is the card's
   frame height and clips (never a scroll container, so focus cannot scroll it either); home-news.js fitColumn leaves
   out whole blocks (data-zw-col-out) until the rest fit above its foot, and its bottom padding is the room the floating
   Ask Zena button takes over it (--zw-col-reserve, C14). The clip margin keeps a focus ring at its edges whole. */
html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-markets{display:flex!important;flex-direction:column;gap:14px!important;height:auto!important;min-height:0!important;overflow:clip!important;overflow-clip-margin:6px;align-self:stretch!important;box-sizing:border-box;padding:0 0 var(--zw-col-reserve,0px)!important}
/* The blocks fitColumn leaves out, named on the column (data-zw-col-out), never marked inside the blocks. */
html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-markets[data-zw-col-out~=research]>.zk-rail,
html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-markets[data-zw-col-out~=inner2]>.zs-news-rail>:nth-child(2),html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-markets[data-zw-col-out~=inner3]>.zs-news-rail>:nth-child(3),
html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-markets[data-zw-col-out~=inner4]>.zs-news-rail>:nth-child(4),html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-markets[data-zw-col-out~=inner5]>.zs-news-rail>:nth-child(5),
html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-markets[data-zw-col-out~=inner6]>.zs-news-rail>:nth-child(6),
html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-markets[data-zw-col-out~=carry-report] .zw-carry-block[data-zw-carry-part=report],html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-markets[data-zw-col-out~=carry-detail] .zw-carry-block[data-zw-carry-part=detail],
html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-markets[data-zw-col-out~=carry-rows] .zw-carry-block[data-zw-carry-part=rows],html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-markets[data-zw-col-out~=carry-release] .zw-carry-block[data-zw-carry-part=release],
html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-markets[data-zw-col-out~=carry-map] .zw-carry-block[data-zw-carry-part=map],html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-markets[data-zw-col-out~=carry-range] .zw-carry-block[data-zw-carry-part=range],
html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-markets[data-zw-col-out~=carry-read] .zw-carry-block[data-zw-carry-part=read]{display:none!important}
/* C13: a chart height fitColumn sets (data-zw-col-curve, --znews-curve-height) holds every chart in the column to it,
   the contract's line included (news-workspace.css otherwise gives that line a 125px or 145px floor). */
html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-markets[data-zw-col-curve] .zs-history-plot{flex:none!important;height:var(--znews-curve-height)!important;min-height:0!important;max-height:var(--znews-curve-height)!important}
html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-markets[data-zw-col-curve] .zs-history-plot>svg{height:100%!important;min-height:0!important;max-height:none!important}
html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-markets>*{flex:0 0 auto!important;min-height:0!important;height:auto!important}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets>.zk-col-label{margin:24px 0 0}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets>.zs-news-rail{display:flex!important;flex-direction:column;min-height:0!important;gap:8px}
html[data-news-view] .zw-page[data-news-keycard] .zs-news-rail>h3{display:none}
html[data-news-view] .zw-page[data-news-keycard] .zs-news-rail>h3.zs-rail-note{display:block!important;margin:0;font:400 12px/1.4 var(--sans,Arial);letter-spacing:0;text-transform:none;color:var(--zk-muted,#fff)}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zs-news-rail>[data-zw-contract-preview],html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zs-compact-snapshot,html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zs-snapshot-open,html[data-news-view] .zw-page[data-news-keycard] .zw-markets [data-zs-snapshot-row],html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zs-price-history{display:flex!important;flex-direction:column;flex:1 1 auto!important;min-height:0!important}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zs-history-plot{flex:0 0 auto!important;height:118px!important;min-height:118px!important;max-height:118px!important}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zs-history-plot>svg{height:100%!important;min-height:0!important}
/* Open item 11: a chart band whose line is still being read already has the drawn chart's size (historyHTML draws the
   same plot, dates and range lines, empty), so the line lands in place. Its status sits over the empty plot, never in
   the flow under it. */
.zs-price-history[data-zs-history-pending] .zs-history-plot{position:relative}
.zs-price-history[data-zs-history-pending] .zs-history-plot>.zs-history-status{position:absolute!important;inset:0!important;display:flex!important;align-items:center;min-height:0!important;height:auto!important;margin:0!important;padding:0!important}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zs-compact-snapshot{padding:16px 18px!important}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zs-compact-snapshot>header{margin-bottom:10px!important}
/* Explore more markets: one quiet line, never a second box, on every card at the column's bottom right (open item 2):
   fitColumn never leaves it out, and the free space above it pushes it to the foot. */
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zw-election-more{background:transparent!important;border-radius:0}
html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-markets>.zw-election-more{margin-top:auto!important;align-self:flex-end!important;width:auto!important;order:9}
html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-markets[data-zw-col-side]{position:relative}
html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-markets[data-zw-col-side]>.zw-election-more{position:absolute!important;bottom:0;right:var(--zw-col-side);box-sizing:border-box;height:var(--zv-dock-h,44px)!important}
html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-markets[data-zw-col-side]>.zw-election-more>:is(button,a){height:100%;min-height:0!important;padding-top:0!important;padding-bottom:0!important}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zw-election-more>:is(button,a){min-height:34px!important;padding:4px 0!important;background:none!important;font:400 13px/1.4 var(--sans,Arial)!important;color:var(--zk-muted,#fff)!important;border-radius:0!important}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zw-election-more>:is(button,a):hover{color:#fff!important}
/* Item 18 (Palash, 2026-11-06 night): recommended markets fill the column's white space under the lead, down to its foot
   (the floating Ask Zena's room is the column's bottom padding, C14). The list is the column's one stretching block; every
   tile is one fixed height on the 8px grid, so it holds its size before its line arrives (item 11), and home-news.js
   fitColumn shows as many as fit whole (data-zw-recs, C13: nothing cut, never a scroll). A tile: the venue's mark, the
   question in at most two lines, the price large over its sparkline; one ground, one hairline (C8); white words, colour
   only on the line (up green, down red). Motion on first paint only, by position and growth (no alpha): each tile rises
   8px, 40ms after the one before, and its line draws from its start. */
html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-markets>.zw-recs{flex:1 1 0!important;min-height:0!important;display:flex;flex-direction:column;gap:8px;overflow:hidden;margin:0;padding:0;border:0;background:none}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets[data-zw-recs="0"]>.zw-recs{display:none!important}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets[data-zw-recs="1"]>.zw-recs>.zw-rec:nth-of-type(n+2),html[data-news-view] .zw-page[data-news-keycard] .zw-markets[data-zw-recs="2"]>.zw-recs>.zw-rec:nth-of-type(n+3),html[data-news-view] .zw-page[data-news-keycard] .zw-markets[data-zw-recs="3"]>.zw-recs>.zw-rec:nth-of-type(n+4),html[data-news-view] .zw-page[data-news-keycard] .zw-markets[data-zw-recs="4"]>.zw-recs>.zw-rec:nth-of-type(n+5),html[data-news-view] .zw-page[data-news-keycard] .zw-markets[data-zw-recs="5"]>.zw-recs>.zw-rec:nth-of-type(n+6),html[data-news-view] .zw-page[data-news-keycard] .zw-markets[data-zw-recs="6"]>.zw-recs>.zw-rec:nth-of-type(n+7),html[data-news-view] .zw-page[data-news-keycard] .zw-markets[data-zw-recs="7"]>.zw-recs>.zw-rec:nth-of-type(n+8){display:none!important}
.zw-page[data-news-keycard] .zw-recs>h3{flex:none;margin:0;font:500 14px/1.4 var(--sans,Arial,sans-serif);letter-spacing:0;text-transform:none;color:#fff}
.zw-page[data-news-keycard] .zw-recs>.zw-rec{flex:none;display:grid;grid-template-columns:20px minmax(0,1fr) 72px;align-items:center;column-gap:12px;width:100%;height:64px;box-sizing:border-box;margin:0;padding:0 14px;border:1px solid var(--zw-hairline,#ffffff24);border-radius:var(--zw-block-radius,8px);background:var(--zw-ground,#080b10);color:#fff;font:inherit;text-align:left;cursor:pointer;transition:border-color .15s ease,transform .15s ease;animation:zw-rec-rise .32s cubic-bezier(.2,.7,.2,1) backwards}
.zw-page[data-news-keycard] .zw-recs>.zw-rec:hover{border-color:#ffffff66;transform:translateY(-1px)}
.zw-page[data-news-keycard] .zw-recs>.zw-rec:focus-visible{outline:2px solid #c6afff;outline-offset:2px}
.zw-page[data-news-keycard] .zw-recs>.zw-rec:nth-of-type(2){animation-delay:40ms}.zw-page[data-news-keycard] .zw-recs>.zw-rec:nth-of-type(3){animation-delay:80ms}.zw-page[data-news-keycard] .zw-recs>.zw-rec:nth-of-type(4){animation-delay:120ms}.zw-page[data-news-keycard] .zw-recs>.zw-rec:nth-of-type(5){animation-delay:160ms}.zw-page[data-news-keycard] .zw-recs>.zw-rec:nth-of-type(6){animation-delay:200ms}.zw-page[data-news-keycard] .zw-recs>.zw-rec:nth-of-type(n+7){animation-delay:240ms}
.zw-page[data-news-keycard] .zw-rec-mark{display:flex;align-items:center;justify-content:center;width:20px;height:20px;box-sizing:border-box;padding:3px;border-radius:5px;background:#fff}
.zw-page[data-news-keycard] .zw-rec-mark:empty{background:none}
.zw-page[data-news-keycard] .zw-rec-mark>img{display:block;width:14px;height:14px;object-fit:contain}
.zw-page[data-news-keycard] .zw-rec-q{display:block;font:400 13px/1.35 var(--sans,Arial,sans-serif);color:#fff;overflow-wrap:break-word}
.zw-page[data-news-keycard] .zw-rec-quote{display:flex;flex-direction:column;align-items:flex-end;justify-content:center;gap:4px;min-width:0}
.zw-page[data-news-keycard] .zw-rec-quote>b{font:500 20px/1 var(--sans,Arial,sans-serif);font-variant-numeric:tabular-nums;color:#fff;white-space:nowrap}
.zw-page[data-news-keycard] .zw-rec-spark{display:block;width:64px;height:20px}
.zw-page[data-news-keycard] .zw-rec-spark>svg{display:block;width:64px;height:20px;overflow:visible}
.zw-page[data-news-keycard] .zw-rec-spark path{fill:none;stroke:#ffffffb3;stroke-width:1.5;stroke-linejoin:round;stroke-linecap:round;vector-effect:non-scaling-stroke;stroke-dasharray:1;stroke-dashoffset:0;animation:zw-rec-draw .6s cubic-bezier(.2,.7,.2,1) backwards}
.zw-page[data-news-keycard] .zw-rec-spark svg[data-zw-trend=up] path{stroke:#3ecf8e}
.zw-page[data-news-keycard] .zw-rec-spark svg[data-zw-trend=down] path{stroke:#ff6b6b}
@keyframes zw-rec-rise{from{transform:translateY(8px)}to{transform:none}}
@keyframes zw-rec-draw{from{stroke-dashoffset:1}to{stroke-dashoffset:0}}
@media(prefers-reduced-motion:reduce){.zw-page[data-news-keycard] .zw-recs>.zw-rec,.zw-page[data-news-keycard] .zw-rec-spark path{animation:none;transition:none}}
/* Explore more markets is the link at the foot of the list (item 18), never a lone button over white space. */
html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-markets>.zw-election-more{border:0!important;border-radius:0!important;background:none!important;padding:0!important}
html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-markets>.zw-election-more>:is(button,a){justify-content:flex-end;gap:8px;min-height:36px!important;padding:4px 2px!important;border:0!important;background:none!important;font:500 14px/1.4 var(--sans,Arial,sans-serif)!important;color:#fff!important}
html[data-news-view] #bfBoard .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-markets>.zw-election-more>:is(button,a):hover{text-decoration:underline;text-underline-offset:4px}
@media(max-width:900px){html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-markets>.zw-recs{flex:none!important;overflow:visible}.zw-page[data-news-keycard] .zw-recs>.zw-rec:nth-of-type(n+5){display:none}}
.zk-rail{flex:none;border-radius:10px;background:#10151c;padding:16px 18px;color:#fff;font-family:var(--sans,Arial)}
.zk-rail-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:12px}
.zk-rail-head>span{font:500 var(--zt-text,11px)/1.4 var(--sans,Arial);color:var(--zk-muted,#fff)}
.zk-rail-head>button,.zk-rail-head>a{border:0;background:none;color:#fff;font:400 13px/1.4 var(--sans,Arial);text-decoration:none;cursor:pointer;padding:4px 0}
.zk-live-list{display:flex;flex-direction:column;margin:0;padding:0;list-style:none}
.zk-live-item{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:4px 12px;align-items:center;padding:10px 0;border-top:1px solid var(--zk-rule,#ffffff1a)}
.zk-live-item:first-child{border-top:0;padding-top:0}
.zk-live-item>span{font:400 12px/1.3 var(--sans,Arial);color:var(--zk-muted,#fff);grid-column:1 / -1}
.zk-live-item>strong{font:500 14px/1.35 var(--sans,Arial);min-width:0;overflow-wrap:anywhere}
.zk-live-item>strong a{color:inherit;text-decoration:none}
.zk-live-item>b{font:500 16px/1.2 var(--sans,Arial);white-space:nowrap}
.zk-live-item[data-phase=live] b::before{content:'';display:inline-block;width:6px;height:6px;border-radius:50%;background:#ff5b4f;margin-right:7px;vertical-align:middle}
.zk-live-empty{font:400 13px/1.5 var(--sans,Arial);color:var(--zk-muted,#fff);margin:0}
.zk-saved .zc-saved-section{display:block;background:transparent;padding:0;border:0;margin:0}
.zk-saved .zc-saved-section>header{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 0 10px}
.zk-saved .zc-saved-section h2{font:500 var(--zt-text,11px)/1.4 var(--sans,Arial);color:var(--zk-muted,#fff)}
.zk-saved .zc-saved-section>header>button{font:400 13px/1.4 var(--sans,Arial);color:#fff;padding:4px 0}
.zk-saved .zc-saved-empty{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 14px;padding:0;background:none;border:0;border-radius:0;font:400 13px/1.5 var(--sans,Arial)}
.zk-saved .zc-saved-empty>strong{font-weight:400;color:var(--zk-muted,#fff)}
.zk-saved .zc-saved-empty>p{display:none}
.zk-saved .zc-saved-empty>button{font:400 13px/1.4 var(--sans,Arial);color:#fff;padding:0}
.zk-saved .zc-saved-list{grid-template-columns:1fr;gap:6px}
.zk-saved .zc-saved-list>article{background:transparent;border-color:var(--zk-rule,#ffffff1a)}

/* Ribbon: Live now sits on the right beside the watchlist, as its own view. */
/* Live now sits right before the watchlist, both plain bar items (the bar's own rules style the watchlist). */
.zc-category-bar>.zc-live-now{display:inline-flex;align-items:center;gap:7px;flex:none;margin-left:auto;border:0;border-bottom:2px solid transparent;border-radius:0;background:none;color:inherit;font:inherit;font-size:inherit;padding:12px 11px;min-height:46px;cursor:pointer;white-space:nowrap}
.zc-category-bar>.zc-live-now:hover{background:var(--panel2)}
.zc-category-bar>.zc-live-now>i{width:7px;height:7px;border-radius:50%;background:#ff5b4f}
.zc-category-bar>.zc-live-now[aria-pressed=true]{border-bottom-color:var(--text)}
.zc-category-bar>.zc-live-now+.zc-watchlist{margin-left:0!important}
/* Phones: the bar is a grid (product-ui.css); Live now and the watchlist share its first row's right side. */
@media(max-width:600px){
  .zc-board-header .zc-category-bar{grid-template-columns:minmax(0,1fr) auto auto}
  .zc-category-bar>.zc-live-now{grid-column:2;grid-row:1;margin-left:0;padding:10px 8px;min-height:44px}
  .zc-category-bar>.zc-live-now+.zc-watchlist{grid-column:3}
}
/* L2 (round 2): on a narrow or a short phone the News desk's category bar is one row, so the frame keeps the room a
   second row took: the reading modes, the topics, Live now and the watchlist are one strip that scrolls sideways, like
   the subcategory row under it, and the topic the reader chose is kept in view (home-news.js keepTopicInView). */
@media (max-width:360px),(max-width:600px) and (max-height:700px){
  html[data-zw-away]:has(#dash .zw-page[data-news-keycard]) #pnlBoard>.zc-board-header .zc-category-bar{display:flex;flex-wrap:nowrap;align-items:stretch;gap:0;min-height:0;overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;scrollbar-width:none}
  html[data-zw-away]:has(#dash .zw-page[data-news-keycard]) #pnlBoard>.zc-board-header .zc-category-bar::-webkit-scrollbar{display:none}
  html[data-zw-away]:has(#dash .zw-page[data-news-keycard]) #pnlBoard>.zc-board-header .zc-category-bar>*{flex:none;margin-left:0}
  html[data-zw-away]:has(#dash .zw-page[data-news-keycard]) #pnlBoard>.zc-board-header .zc-category-bar>:is(.zc-mode-switch,.zc-topics){overflow:visible;width:auto;border-top:0;mask-image:none}
  html[data-zw-away]:has(#dash .zw-page[data-news-keycard]) #pnlBoard>.zc-board-header .zc-category-bar>.zc-topics>button:first-child{padding-left:12px}
  html[data-zw-away]:has(#dash .zw-page[data-news-keycard]) #pnlBoard>.zc-board-header .zc-category-bar>.zc-watchlist{padding-right:2px}
}
.zn-ticker-quote .zn-ticker-move{margin-left:6px;font:500 var(--zt-text,11px)/1 var(--sans,Arial);color:#fff}

/* Continue reading tiles without drawn glyphs: the copy owns the tile when there is no photograph or mark. */
.znd-preview .znd-object:empty,.znd-preview .znd-object:has(> .znd-object-kind:only-child){display:none!important}
.znd-preview:has(.znd-object:empty),.znd-preview:has(.znd-object > .znd-object-kind:only-child){grid-template-columns:minmax(0,1fr)!important;display:flex!important;flex-direction:column;justify-content:flex-end}
.znd-preview:has(.znd-object:empty) .znd-copy,.znd-preview:has(.znd-object > .znd-object-kind:only-child) .znd-copy{padding:14px!important}
/* A story-browser queue tile has its own inset, so its copy takes no second one: the kicker, the subject and the detail
   then fit inside the tile at the type floor (W5); with both insets the copy overflowed and the kicker was cut. */
.zw-queue-art .znd-preview:has(.znd-object:empty) .znd-copy,.zw-queue-art .znd-preview:has(.znd-object > .znd-object-kind:only-child) .znd-copy{padding:0!important}

/* Narrow screens: one column, natural height, the graphic first. */
@media(max-width:900px){
  html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]{grid-template-columns:minmax(0,1fr)!important;height:auto!important;min-height:0!important;overflow:visible}
  html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-focus{padding:18px 16px 16px!important}
  html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-markets{overflow:visible!important}
  .zk-stage{grid-template-columns:minmax(0,1fr);padding:14px 0 8px}
  .zk-side{align-self:stretch}
  .zk-actions{flex-wrap:wrap}.zk-actions>.zk-read-report{flex:1 1 160px;justify-content:center}
  html[data-news-view] .zw-page[data-news-keycard] .zw-markets>.zs-news-rail{min-height:0!important}
}
/* With a detail block beside it, the series keeps its line and axis; the numbers live in the block. */
.zk-stage:not(.zk-stage-wide) .zg-series-head{display:none}
@media(max-width:900px){.zk-meta{flex-wrap:wrap;gap:4px 12px}.zk-meta>span:last-child{white-space:normal;text-align:left}}
/* Compact frame: the card's measured height is under 600px (a 720px laptop). Same composition, tighter type and
   spacing, so the whole card still sits in one screen. Set by home-news.js fitWorkspace. */
html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design][data-zw-density=compact]>.zw-focus{padding:16px 22px 14px!important}
.zw-workspace[data-zw-density=compact] .zw-story-header h2{font-size:clamp(20px,1.7vw,24px)}
html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-zw-density=compact]>.zw-focus>.zs-story-body{margin-top:6px}
.zw-workspace[data-zw-density=compact] .zk-head{gap:6px;padding-bottom:10px}
.zw-workspace[data-zw-density=compact] .zk-sub{font-size:14px;line-height:1.45}
.zw-workspace[data-zw-density=compact] .zk-meta{font-size:12px}
.zw-workspace[data-zw-density=compact] .zk-stage{padding:10px 0 8px;gap:8px 24px}
.zw-workspace[data-zw-density=compact] .zk-side{gap:8px}
.zw-workspace[data-zw-density=compact] .zk-facts{padding-top:8px;gap:5px}
.zw-workspace[data-zw-density=compact] .zk-facts dt,.zw-workspace[data-zw-density=compact] .zk-facts dd,.zw-workspace[data-zw-density=compact] .zk-read>p{font-size:13px}
.zw-workspace[data-zw-density=compact] .zk-read{padding-top:8px}
.zw-workspace[data-zw-density=compact] .zk-actions{padding-top:10px}
.zw-workspace[data-zw-density=compact] .zk-actions>.zk-read-report{min-height:40px;padding:0 20px;font-size:14px}
.zw-workspace[data-zw-density=compact] .zg-focus-state{font-size:clamp(19px,1.6vw,22px)}
.zw-workspace[data-zw-density=compact] .zg-focus-office{margin-bottom:2px}
.zw-workspace[data-zw-density=compact] .zg-focus{gap:4px}
.zw-workspace[data-zw-density=compact] .zg-row{font-size:14px}
.zw-workspace[data-zw-density=compact] .zg-row>b{font-size:19px}
.zw-workspace[data-zw-density=compact] .zg-legend{margin-top:6px}
.zw-workspace[data-zw-density=compact] .zg-text>p{font-size:clamp(18px,1.6vw,24px)}
.zw-workspace[data-zw-density=compact] .zg-series-head>b{font-size:22px}
/* Headline-only slot: the report's publisher and time, replaced by the article image when it arrives. */
.zg-text-source{justify-content:center;align-items:flex-start;gap:6px;padding:0 8%}
.zg-text-source>span{font:500 13px/1.4 var(--sans,Arial);letter-spacing:.02em;text-transform:none;color:#fff}
.zg-text-source>p{font:400 clamp(18px,1.6vw,22px)/1.3 var(--sans,Arial);letter-spacing:-.01em;color:var(--zk-muted,#fff);max-width:none}
.zg-text-source>small{color:var(--zk-muted,#fff)}
.zg-text-source>img{flex:1 1 auto;min-height:0;width:100%;object-fit:cover;border-radius:8px}
/* Phones: the pinned row keeps every control, each at icon size, so the subcategories keep their room. */
@media(max-width:700px){
  html[data-news-view] .zw-page>.zw-edition-tools{gap:8px}
  html[data-news-view] .zw-page>.zw-edition-tools>.zw-filters{min-width:84px}
  html[data-news-view] .zw-page>.zw-edition-tools>.zw-desk-actions{gap:4px}
}
/* L2 (round 1): on a phone the subcategory row is one line; the subcategories scroll sideways in their own strip, like
   the topics, and the story controls keep their place at its end. */
@media(max-width:600px){
  html[data-news-view] .zw-page>.zw-edition-tools{flex-wrap:nowrap;row-gap:0}
  html[data-news-view] .zw-page>.zw-edition-tools>.zw-filters{flex:1 1 auto;min-width:0;overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:none}
  html[data-news-view] .zw-page>.zw-edition-tools>.zw-filters>button{flex:none}
  html[data-news-view] .zw-page>.zw-edition-tools>.zw-desk-actions{margin-left:0;flex:none}
  html[data-news-view] .zw-page>.zw-edition-tools>.zw-edition-source{margin-left:auto}
  html[data-news-view] .zw-page>.zw-edition-tools .zw-election-toggle{font-size:0;min-width:44px;min-height:40px;padding:0;display:grid;place-items:center;border-radius:3px}
  html[data-news-view] .zw-page>.zw-edition-tools .zw-election-toggle::after{content:'Map';font:500 13px/1 var(--sans,Arial)}
  html[data-news-view] .zw-page>.zw-edition-tools .zw-story-steps{gap:4px}
  html[data-news-view] .zw-page>.zw-edition-tools .zw-story-steps>button{width:36px;min-height:40px}
  html[data-news-view] .zw-page>.zw-edition-tools .zw-wire-jump{min-width:36px;height:40px}
}
/* Under a full-width photograph: the facts and Zena's read on the left, Read report on the right. */
.zk-under{display:flex;flex-wrap:wrap;align-items:center;gap:10px 28px;padding-top:12px}
.zk-under .zk-facts{display:flex;flex-wrap:wrap;gap:6px 24px;margin:0;padding:0;border:0}
.zk-under .zk-facts>div{gap:8px}
.zk-under .zk-read{flex:1 1 320px;padding:0;border:0}
.zk-under .zk-actions{flex-direction:row-reverse;align-items:center;gap:18px;margin-left:auto}
.zk-under .zk-actions>.zk-read-report{min-width:170px}

/* The photograph slot once filled: the image takes the stage, its credit under it. */
.zg-text[data-zk-filled=photo]{justify-content:flex-start;gap:8px;padding:0}
.zg-text[data-zk-filled=photo]>img{flex:1 1 auto;min-height:0;width:100%;height:100%;object-fit:cover;border-radius:10px;background:#0b0f14}
.zg-text[data-zk-filled=photo]>small{flex:none;font:400 12px/1.4 var(--sans,Arial);color:var(--zk-muted);text-transform:none;letter-spacing:0}
.zg-text[data-zk-filled=reserve]{display:flex;flex-direction:column;justify-content:center;gap:0;padding:0}
.zg-text[data-zk-filled=reserve]>*{flex:1 1 auto;min-height:0}
/* Until one arrives the slot is a calm frame naming the report. */
.zg-text-source:not([data-zk-filled]){border-radius:10px;background:#0d1218;padding:0 6%}

/* One club, large, with its name. */
.zg-crest{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;height:100%}
.zg-crest>img{width:clamp(110px,14vw,180px);height:auto;max-height:70%;object-fit:contain}
.zg-crest>strong{font:500 clamp(20px,1.8vw,26px)/1.2 var(--sans,Arial);color:#fff}

/* Muted text in the card and rail is a colour, never a faded opacity (washed text fails contrast). */
.zw-page[data-news-keycard] .zw-markets :is(.zs-history-dates,.zs-history-status,.zs-snapshot-footer>small,.zs-market-snapshot header>span,.zs-history-high,.zs-history-low,.zs-snapshot-axis,.zs-watch-label,.zs-source-credit),.zw-page[data-news-keycard] .zd-visual>footer{opacity:1!important;color:var(--zk-muted)!important}
/* A filing in the key card frame: the source document fills the section, nothing cut, the actions at its foot. */
html[data-news-view] .zw-page[data-news-keycard] .zs-story-body>.zs-report-card:has(>.zf-card){position:relative}
html[data-news-view] .zw-page[data-news-keycard] .zs-report-card>.zf-card{display:flex!important;flex-direction:column;flex:1 1 auto!important;min-height:0!important;border-radius:10px;overflow:hidden}
html[data-news-view] .zw-page[data-news-keycard] .zf-card>.zf-stage{flex:1 1 auto;min-height:0!important;padding-bottom:64px!important;align-items:stretch}
html[data-news-view] .zw-page[data-news-keycard] .zf-company{min-height:0!important;padding:22px 24px;justify-content:space-between}
html[data-news-view] .zw-page[data-news-keycard] .zf-interval{flex:0 1 auto}
html[data-news-view] .zw-page[data-news-keycard] .zf-interval>strong{font-size:clamp(46px,6cqw,78px)}
html[data-news-view] .zw-page[data-news-keycard] .zf-document{padding:20px 22px!important;gap:14px;overflow:auto}
/* L5 (round 2): a document taller than its box starts at its top, so it overflows downward only, where the frame sees it
   and leaves its optional blocks out whole (fitCard); centred, it spilled above the box too, cut at both ends unseen. */
html[data-news-view] .zw-page[data-news-keycard] .zf-card :is(.zf-document,.zf-company){justify-content:safe center}
/* The document is as tall as its row and no taller, its content centred inside it: a document taller than the row
   overflows its own box, where the frame sees it, never the stage above and below (news-card-shell.css centres the box at an id's weight, hence important). */
html[data-news-view] .zw-page[data-news-keycard] .zf-card>.zf-stage>.zf-document{align-self:stretch!important;min-height:0}
/* S1, Filings: a filing's Read report is the key card's own button at the foot of its document column, where every other
   template has it at the foot of its side block (news-studio.js reportCard puts it there). No actions bar is drawn under
   the card, so the stage keeps the room that bar took. The document's own lines stay centred above the button. */
html[data-news-view] .zw-page[data-news-keycard] .zf-card:has(>.zf-stage>.zf-document>.zk-actions)>.zf-stage{padding-bottom:0!important}
html[data-news-view] .zw-page[data-news-keycard] .zf-document>.zk-actions{margin-top:auto}
html[data-news-view] .zw-page[data-news-keycard] .zf-document:has(>.zk-actions)>:first-child{margin-top:auto}
/* On a phone the document sits under the filer's block at its own height: the form line and Read report share one row
   when nothing else of the document is shown, so the filer's block, the flexible track, keeps the room (L2, L6). */
@media(max-width:600px){
  html[data-news-view] .zw-page[data-news-keycard] .zf-document:has(>.zk-actions){flex-direction:row;flex-wrap:wrap;align-items:center;column-gap:14px}
  html[data-news-view] .zw-page[data-news-keycard] .zf-document:has(>.zk-actions)>:not(.zf-document-identity,.zk-actions){flex:1 1 100%}
  html[data-news-view] .zw-page[data-news-keycard] .zf-document:has(>.zk-actions)>:first-child{margin-top:0}
  html[data-news-view] .zw-page[data-news-keycard] .zf-document>.zk-actions{margin:0 0 0 auto}
}
html[data-news-view] .zw-page[data-news-keycard] .zf-dates>time{font-size:clamp(22px,2.6cqw,30px)}
.zw-workspace[data-zw-density=compact] .zf-interval>strong{font-size:clamp(40px,5cqw,60px)}
.zw-workspace[data-zw-density=compact] .zf-issuer{padding-top:10px}
.zw-workspace[data-zw-density=compact] .zf-document{gap:10px}
/* The detail column centres its content but never clips the top of it. */
.zk-side-body{justify-content:safe center}
/* Asset context in the rail is a card of its own rows, never loose links in white space. */
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zw-contract-assets{display:flex!important;flex-direction:column!important;align-items:stretch!important;justify-content:flex-start!important;gap:8px!important;margin:0!important;padding:14px 18px!important;border:0!important;border-radius:10px!important;background:#10151c!important}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zw-contract-assets>.zw-companion-actions{flex-direction:column!important;align-items:stretch!important;justify-content:flex-start!important;gap:0!important}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zw-contract-assets .zw-companion-actions>button{justify-content:space-between!important;min-height:40px!important;padding:8px 0!important;font-size:14px!important}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zw-contract-assets>.zw-section-label{align-self:flex-start!important;color:var(--zk-muted)!important;font-size:var(--zt-label,11px)!important}
/* The discovery card's label never runs under its corner arrow. */
html[data-news-view] .zw-page[data-news-keycard] .zw-market-browse .zw-discovery-label{display:inline-block;max-width:calc(100% - 52px)}
/* A research card's question grows to its own lines; it never runs into the price under it. */
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zr-card h4{height:auto!important;min-height:0!important;margin:12px 0!important;font-size:clamp(18px,1.5vw,21px)!important;line-height:1.25!important}
/* L5 (round 4): the research card's price type (the side, then "Book midpoint" or "Last trade" under it) sits wholly in
   the reading row above the chart, never in the plot's band where the line runs at its high: the row grows to hold both
   lines and the chart starts under it. The high, the low and the change each stay one phrase and wrap onto a line of their
   own when the column is narrow, under the dates, and the plot gives up the height they take, so nothing sits over the
   dates or runs under the card's foot. */
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zr-reading{height:auto!important}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zr-chart:has(>.zr-chart-range){display:flex;flex-direction:column}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zr-chart:has(>.zr-chart-range)>.zr-plot{flex:1 1 auto;height:auto;min-height:0}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zr-chart:has(>.zr-chart-range)>:is(.zr-chart-dates,.zr-chart-range){flex:none}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zr-chart-range{height:auto;flex-wrap:wrap;align-items:baseline;row-gap:2px;margin-top:4px;line-height:1.3}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zr-chart-range>span{white-space:nowrap}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zw-contract-assets>.zw-section-label{font:500 var(--zt-label,11px)/1.4 var(--sans,Arial);color:var(--zk-muted)}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zw-contract-assets>.zw-companion-actions{display:flex;flex-direction:column;gap:0}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zw-contract-assets button{display:flex;justify-content:space-between;align-items:center;width:100%;min-height:40px;padding:8px 0!important;border:0!important;border-top:1px solid var(--zk-rule)!important;border-radius:0!important;background:none!important;color:#fff!important;font:400 14px/1.4 var(--sans,Arial)!important;text-align:left;cursor:pointer}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zw-contract-assets button:first-child{border-top:0!important}
/* Explore more markets: a full row on its own surface, like every other rail card. */
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zw-election-more{background:#10151c!important;border-radius:10px!important}
html[data-news-view] .zw-page[data-news-keycard] .zw-markets .zw-election-more>:is(button,a){min-height:48px!important;padding:12px 18px!important;color:#fff!important;font:400 14px/1.4 var(--sans,Arial)!important}
/* The detail column never overflows into its actions: a block that does not fit is left out whole by the frame's drop
   order (data-zk-fit, below), never cut to an ellipsis (L5). */
.zw-workspace[data-zw-density=compact] .zg-focus-office{font-size:12px;margin-bottom:2px}
.zw-workspace[data-zw-density=compact] .zg-focus .zg-row{font-size:13px}
.zw-workspace[data-zw-density=compact] .zg-focus .zg-row>b{font-size:17px}
/* Phones (600px and under): one column whatever the graphic, the graphic first at full width as the frame's one
   flexible track, the detail block and the actions under it at their own height (L2). Tablets keep the desktop
   composition (the round 1 layout block at the end of this file). */
@media(max-width:600px){
  .zk-stage,.zk-stage[data-zk-form]{grid-template-columns:minmax(0,1fr)!important;grid-template-rows:minmax(0,1fr) auto!important}
  .zk-side{justify-content:flex-start;gap:12px}
  .zk-side-body{flex:none;overflow:visible}
  .zk-actions>.zk-read-report{flex:none}
}
/* A subject's mark (a company, club, coin or flag) shown whole on a light tile, its name under it. */
.zg-text[data-zk-filled=mark]{align-items:center;justify-content:center;gap:14px;padding:0;border-radius:10px;background:#0d1218}
.zg-text[data-zk-filled=mark]>.zk-mark-tile{display:grid;place-items:center;width:clamp(110px,14vw,170px);aspect-ratio:1;border-radius:22px;background:#fff;padding:18px;box-sizing:border-box}
.zg-text[data-zk-filled=mark]>.zk-mark-tile>img{max-width:100%;max-height:100%;object-fit:contain}
.zg-text[data-zk-filled=mark]>strong{font:500 clamp(20px,1.8vw,26px)/1.2 var(--sans,Arial);color:#fff}
.zg-text[data-zk-filled=mark]>small{font:400 12px/1.4 var(--sans,Arial);color:var(--zk-muted);text-transform:none;letter-spacing:0}
/* The matchup sizes to its marks and names and sits centred; it never runs into the caption under it. */
.zg-matchup{height:auto!important;align-self:center;min-height:0}
.zg-matchup .zg-side>img{width:clamp(84px,10vw,150px)!important;max-height:min(22vh,150px)!important}
.zw-workspace[data-zw-density=compact] .zg-matchup .zg-side>img{max-height:min(17vh,120px)!important}
.zg-scoreline .zg-side>img{width:clamp(64px,7vw,104px);max-height:min(15vh,104px)}
/* Scorebug: a row per club, centred in the stage. */
.zg-scoreline{justify-content:center;gap:12px;max-width:620px;width:100%;margin:0 auto}
.zg-scorebug{display:flex;flex-direction:column;gap:10px}
.zg-score-row{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:18px;padding:12px 18px;border-radius:12px;background:#0d1218;color:var(--zk-muted)}
.zg-score-row[data-lead=true]{color:#fff;background:#141b24}
.zg-score-row>img{width:clamp(44px,4.6vw,60px);height:auto;aspect-ratio:1;object-fit:contain}
.zg-score-row>i{width:clamp(44px,4.6vw,60px);aspect-ratio:1}
.zg-score-row>div{display:flex;flex-direction:column;gap:2px;min-width:0}
.zg-score-row strong{font:500 clamp(17px,1.6vw,22px)/1.2 var(--sans,Arial);color:inherit}
.zg-score-row small{font:400 13px/1.3 var(--sans,Arial);color:var(--zk-muted)}
.zg-score-row>.zg-score{font:500 clamp(34px,3.4vw,48px)/1 var(--sans,Arial);letter-spacing:-.03em;color:inherit}
.zw-workspace[data-zw-density=compact] .zg-score-row{padding:6px 14px;gap:14px}
.zw-workspace[data-zw-density=compact] .zg-score-row>img,.zw-workspace[data-zw-density=compact] .zg-score-row>i{width:38px}
.zw-workspace[data-zw-density=compact] .zg-score-row strong{font-size:17px}
.zw-workspace[data-zw-density=compact] .zg-score-row>.zg-score{font-size:32px}
.zw-workspace[data-zw-density=compact] .zg-scorebug{gap:6px}
.zw-workspace[data-zw-density=compact] .zg-scoreline{gap:6px}
/* A graphic taller than its space starts at its top; it never centres itself up under the subtitle. */
html[data-news-view] .zw-page[data-news-keycard] .zk-stage>.zk-graphic{justify-content:safe center!important;overflow:hidden}
.zg-scoreline{justify-content:safe center}

/* ---------- Round 1 of the template rules (docs/news-key-card-rules.md) ---------- */
/* W2: words are one ink. No grey text, no tracked capitals as labels; hierarchy is size and weight. The key card's own
   labels are written that way at source above; these two are also styled by the desk's older sheets (a quiet colour),
   so the key card keeps them white here. */
.zw-page[data-news-keycard] :is(.zk-card,.zw-markets) :is(.zc-saved-section h2,.zw-section-label){text-transform:none!important;letter-spacing:0!important;color:#fff!important}
.zw-page[data-news-keycard] .zk-col-label{display:none!important}
.zg-status{display:flex;gap:14px;font:500 13px/1.4 var(--sans,Arial);color:#fff}
/* G3: a photograph is shown whole inside its frame, never cropped to fill. The frame is a flat panel; the
   picture sits centred in it at its own shape. */
.zg-photo>img,.zg-text>img,.zg-text-source>img,.zg-text[data-zk-filled=photo]>img{object-fit:contain!important;object-position:50% 50%!important;background:var(--zk-frame)}
.zg-text[data-zk-filled=photo]{border-radius:12px;background:var(--zk-frame);padding:12px!important;box-sizing:border-box}
.zg-text[data-zk-filled=photo]>img{border-radius:6px!important;background:transparent}
/* Round 4 (G3, L6; 00975e3a): the story's own photograph (the S7 last resort, Climate's and World's included) sits in its
   frame the way the culture cards' photographs do (the portrait frame below). On a desktop, once its shape is read
   (data-zk-art-shape, --zk-art-aspect), the picture is as large as the graphic allows whole and the frame hugs it, the
   credit under it (12px padding, an 8px gap and one 17px line: 49px), centred in the graphic; never a full-track panel
   with dark bars beside a letterboxed picture. The graphic is read as its own box (container units). On a tablet and a
   phone the frame is the graphic: the picture whole at the frame's full width, centred, the credit at its foot. */
@media (min-width:901px){
  html[data-news-view] .zw-page[data-news-keycard] .zk-graphic:has(>.zg-text[data-zk-filled=photo][data-zk-art-shape]){container-type:size}
  html[data-news-view] .zw-page[data-news-keycard] .zk-graphic>.zg-text[data-zk-filled=photo][data-zk-art-shape]{flex:0 1 auto!important;align-self:center;width:fit-content;max-width:100%;height:auto;max-height:100%}
  html[data-news-view] .zw-page[data-news-keycard] .zk-graphic>.zg-text[data-zk-filled=photo][data-zk-art-shape]>img{flex:none;height:auto;width:min(calc(100cqw - 24px),calc((100cqh - 49px) * var(--zk-art-aspect,1.5)));aspect-ratio:var(--zk-art-aspect,auto);max-width:100%}
  html[data-news-view] .zw-page[data-news-keycard] .zk-graphic>.zg-text[data-zk-filled=photo][data-zk-art-shape]>small{align-self:stretch;contain:inline-size}
}
@media (max-width:900px){
  html[data-news-view] .zw-page[data-news-keycard] .zk-graphic>.zg-text[data-zk-filled=photo][data-zk-art-shape]{padding:0 0 10px!important}
  html[data-news-view] .zw-page[data-news-keycard] .zk-graphic>.zg-text[data-zk-filled=photo][data-zk-art-shape]>img{border-radius:12px 12px 6px 6px!important}
  html[data-news-view] .zw-page[data-news-keycard] .zk-graphic>.zg-text[data-zk-filled=photo][data-zk-art-shape]>small{padding:0 12px}
}
/* Portrait frame: a person, a film or a mission, whole, with the subject's name until the picture arrives. */
.zg-portrait{display:flex;flex-direction:column;gap:12px;height:100%;min-height:0}
.zg-portrait-frame{position:relative;flex:1 1 auto;min-height:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:12px;border-radius:12px;background:var(--zk-frame);box-sizing:border-box;overflow:hidden}
.zg-portrait-frame>img{flex:1 1 auto;min-height:0;width:100%;height:100%;object-fit:contain;border-radius:6px}
.zg-portrait-frame>small{flex:none;align-self:flex-start;font:400 12px/1.4 var(--sans,Arial);color:#fff}
.zg-portrait-name{font:500 clamp(24px,2.4vw,36px)/1.15 var(--sans,Arial);letter-spacing:-.02em;color:#fff;text-align:center;max-width:16ch}
.zg-portrait-frame[data-zk-filled=reserve]{padding:0;background:none}
.zg-portrait-frame[data-zk-filled=reserve]>*{width:100%;flex:1 1 auto;min-height:0}
/* Round 3 (S7 Science reserve, L6): a count drawn in the photograph's place is the graphic, its number as tall as the
   frame allows (and no wider than it), its label over it and who reported it and when under it. */
.zg-portrait-frame[data-zk-filled=reserve]>.zg-figure{container-type:size;justify-content:center}
.zg-portrait-frame[data-zk-filled=reserve]>.zg-figure>.zg-figure-value{font-size:clamp(48px,min(66cqh,calc(150cqw / var(--zg-chars,4))),360px)}
.zg-portrait-frame[data-zk-filled=mark]>.zk-mark-tile{display:grid;place-items:center;width:clamp(120px,14vw,180px);aspect-ratio:1;border-radius:22px;background:#fff;padding:18px;box-sizing:border-box}
.zg-portrait-frame[data-zk-filled=mark]>.zk-mark-tile>img{max-width:100%;max-height:100%;object-fit:contain}
.zg-portrait-frame[data-zk-filled=mark]>strong{font:500 22px/1.2 var(--sans,Arial);color:#fff}
/* A mark's credit sits centred under its tile and name, one group, never alone at the frame's edge (round 2). */
.zg-portrait-frame[data-zk-filled=mark]>small{align-self:center;text-align:center}
/* A player's club crest on the photograph, in its top corner on a white tile (S5 Players). When the slot shows the
   club's own crest or ring instead of a photograph, the corner crest is not drawn twice. */
.zg-portrait{position:relative}
.zg-portrait-crest{position:absolute;top:10px;left:10px;z-index:1;display:grid;place-items:center;width:52px;height:52px;padding:6px;border-radius:12px;background:#fff;box-sizing:border-box}
.zg-portrait-crest>img{width:100%;height:100%;object-fit:contain}
.zg-portrait-frame:is([data-zk-filled=reserve],[data-zk-filled=mark])+.zg-portrait-crest{display:none}
@media (max-width:600px){.zg-portrait-crest{top:8px;left:8px;width:40px;height:40px;padding:5px;border-radius:10px}}
/* Company: its logo on a white tile beside its name, then its share line or the figures it reported. */
.zg-company{display:flex;flex-direction:column;gap:16px;height:100%;min-height:0}
.zg-company-head{flex:none;display:flex;align-items:center;gap:16px}
.zg-company-head>strong{font:500 clamp(22px,2vw,30px)/1.15 var(--sans,Arial);letter-spacing:-.02em;color:#fff}
.zg-company-logo,.zg-status-logo{flex:none;width:64px;height:64px;border-radius:14px;background:#fff;display:grid;place-items:center;padding:8px;box-sizing:border-box;overflow:hidden}
.zg-company-logo:not([data-zk-filled=mark]),.zg-status-logo:not([data-zk-filled=mark]){display:none}
:is(.zg-company-logo,.zg-status-logo)>.zk-mark-tile{display:grid;place-items:center;width:100%;height:100%}
/* A logo sits whole inside its tile (L5): the tile's one cell is the tile's own size, so the picture's max-height holds
   instead of growing the cell past the tile's edge. */
:is(.zg-company-logo,.zg-status-logo),:is(.zg-company-logo,.zg-status-logo)>.zk-mark-tile{grid-template:minmax(0,1fr)/minmax(0,1fr)}
:is(.zg-company-logo,.zg-status-logo) img{max-width:100%;max-height:100%;object-fit:contain}
:is(.zg-company-logo,.zg-status-logo)>:is(strong,small,template){display:none}
.zg-company>.zg-series{flex:1 1 auto;min-height:0}
.zg-company-figures{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin:0}
.zg-company-figures>div{padding:16px;border-radius:12px;background:var(--zk-frame)}
.zg-company-figures dt{font:400 13px/1.4 var(--sans,Arial);color:#fff}
.zg-company-figures dd{margin:6px 0 0;font:500 clamp(24px,2.4vw,34px)/1.1 var(--sans,Arial);letter-spacing:-.02em;color:#fff}
.zg-company-figures small{display:block;margin-top:4px;font:400 12px/1.4 var(--sans,Arial);color:#fff}
/* Release history: one bar per release, the latest in the desk's colour. */
.zg-releases svg{flex:1 1 auto;min-height:0}
.zg-bar{fill:var(--zk-bar)}
.zg-bar-now{fill:var(--zk-accent)}
/* A rule or bill's stage: four segments, filled up to where the report puts it. */
.zg-status-track,.zg-incident{display:flex;flex-direction:column;justify-content:center;gap:22px;height:100%;min-height:0}
.zg-status-head{display:flex;align-items:center;gap:16px}
.zg-status-head>strong{font:500 clamp(22px,2vw,30px)/1.15 var(--sans,Arial);letter-spacing:-.02em;color:#fff}
.zg-status-track>ol{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;margin:0;padding:0;list-style:none}
.zg-status-track li{display:flex;flex-direction:column;gap:10px}
.zg-status-track li>i{display:block;height:10px;border-radius:2px;background:var(--zk-bar)}
.zg-status-track li[data-done]>i,.zg-status-track li[data-now]>i{background:var(--zk-accent)}
.zg-status-track li>span{font:400 14px/1.3 var(--sans,Arial);color:#fff}
.zg-status-track li[data-now]>span{font-weight:600}
.zg-incident>.zg-figure-value{font:500 clamp(44px,5vw,72px)/1 var(--sans,Arial);letter-spacing:-.03em;color:#fff}
.zg-incident-chain{font:400 15px/1.4 var(--sans,Arial);color:#fff}
/* World region: the named countries lit in the desk's colour on the land around them. */
.zg-worldmap{width:100%;height:100%}
.zg-country{fill:var(--zk-land);stroke:var(--zk-surface);stroke-width:.6}
.zg-country-named{fill:var(--zk-accent)}
.zg-country-label{font:500 13px/1 var(--sans,Arial);fill:#fff;paint-order:stroke;stroke:#0b1016;stroke-width:3px}
.zg-company-mark>.zg-portrait-frame{height:100%}
.zg-company-figures{flex:1 1 auto;align-content:center}
/* G6: a line's colour says which way it went; a bar's says whose it is. */
.zg-line[data-dir=up]{stroke:#3ecf8e}
.zg-line[data-dir=down]{stroke:#ff6b6b}
/* The track stays faint and the fill carries the value (a 1% outcome is a sliver, never a full bar); the fill is the
   outcome's party when it has one, a split hatched in both, and one neutral ink otherwise, never the desk's colour, which
   on Politics is the Democratic blue. */
.zg-rung>i::after{background:#e6ebf0}
.zg-rung[data-party=D]>i::after{background:#4a8fdf}
.zg-rung[data-party=R]>i::after{background:#df555c}
.zg-rung[data-party=split]>i::after{background:repeating-linear-gradient(135deg,#4a8fdf 0 6px,#df555c 6px 12px)}
/* The stage track drawn large (rules S5 Crypto Policy, Security, round 1): four blocks across the frame, only the stage
   the report states lit in the desk's colour, each stage named inside its block on one line. */
.zg-status-track>ol{gap:10px}
.zg-status-track li{display:flex;align-items:flex-end;min-height:clamp(64px,20vh,200px);padding:14px;border-radius:8px;background:var(--zk-bar);box-sizing:border-box}
.zg-status-track li>span{font:500 clamp(14px,1.2vw,17px)/1.25 var(--sans,Arial);color:#fff}
.zg-status-track li[data-now]{background:var(--zk-accent)}
.zg-status-track li[data-now]>span{color:#0b0d10}
.zg-status-track li[data-now]>span{font-weight:700}
.zg-range{display:flex;gap:18px;margin-top:4px;font:400 12px/1.4 var(--sans,Arial);color:#fff}
.zg-text-source:not([data-zk-filled]){align-items:center;justify-content:center;background:var(--zk-frame)}
.zg-status-track li{flex-direction:column;justify-content:flex-end;align-items:flex-start;min-width:0}
/* A stage word never breaks inside itself (L5): it stays on one line ("Advancing", never "Advancin / g"), and the track
   never wraps into a 2x2 grid that loses its order (S1, S3). Round 4: the four stages are one row at every size (below). */
.zg-status-track li>span{white-space:nowrap;overflow-wrap:normal;word-break:keep-all;hyphens:none}
@media (max-width:600px){
  .zg-company-logo,.zg-status-logo{width:48px;height:48px;border-radius:12px}
}
/* ---------- Culture, World and Politics templates, round 1 (docs/news-key-card-rules.md) ---------- */
/* A security incident: its amount large with what the report calls it, over the enforcement track. */
.zg-incident-amount{display:flex;flex-direction:column;gap:4px}
.zg-incident-amount>.zg-figure-value{font:500 clamp(40px,4.4vw,64px)/1 var(--sans,Arial);letter-spacing:-.03em;color:#fff}
.zg-incident-amount>.zg-figure-label{font:400 14px/1.4 var(--sans,Arial);color:#fff}
/* A detail row whose value is words: the label, then the value beside it, both whole; a long value wraps under itself. */
.zg-row.zg-row-text{grid-template-columns:minmax(0,max-content) minmax(0,1fr);gap:2px 12px;align-items:baseline}
.zg-row.zg-row-text>span{font:400 13px/1.4 var(--sans,Arial);color:#fff}
.zg-row.zg-row-text>b{font:500 16px/1.3 var(--sans,Arial);letter-spacing:-.01em;text-align:right;overflow-wrap:break-word}
.zg-row>span>small{font:400 12px/1.3 var(--sans,Arial);color:#fff}
/* Film & TV, Music, Awards, Science: on a desktop the photograph fills the graphic's height and its frame is as wide
   as the photograph, the detail block beside it, as on a phone. The stage is sized by the card, so the photograph's
   height is read from the stage itself (container units); a reserve graphic keeps the ordinary columns. */
@media (min-width:901px){
  /* Round 2 (L6): the photograph's column is as wide as the picture at the stage's height, up to all but the detail
     block's own width, and only while a picture is in the frame: a name tile or the asking frame keeps the stage's own
     wide column, never a sliver (S3: the same structure at every size). */
  /* Round 3 (known: frame collapse): only a photograph in the frame (its own img, or a JPEG filed as a mark) fits the
     column to the picture; a logo on its tile keeps the stage's wide column. */
  .zk-stage[data-zk-form=portrait]:has(.zg-portrait:not([data-kind=player])):has(.zg-portrait-frame>img,.zg-portrait-frame[data-zk-filled=mark] img[src*=".jpg" i],.zg-portrait-frame[data-zk-filled=mark] img[src*=".jpeg" i]):not(:has([data-zk-filled=reserve])){container-type:size;grid-template-columns:fit-content(calc(100% - 280px)) minmax(240px,1fr)}
  /* The picture keeps its own shape and fills the graphic's height (round 3, S1 and L6: a thumbnail smaller than the
     stage is drawn at the stage's height, never at its own few hundred pixels); its width follows its shape, up to all
     but the detail block's room, and a picture wider than that is drawn whole inside its box (G3). */
  .zk-stage[data-zk-form=portrait] .zg-portrait:not([data-kind=player]) .zg-portrait-frame>img{flex:none;width:auto;max-width:max(120px,calc(100cqw - 304px));height:calc(100cqh - 52px);max-height:calc(100cqh - 52px);min-height:0;object-fit:contain}
  /* A wide picture (data-zk-art-shape, read when it loads) is bound by the column's width, so its box keeps its own
     shape and the credit sits directly under it, never under an empty band (G3). */
  .zk-stage[data-zk-form=portrait] .zg-portrait:not([data-kind=player]) .zg-portrait-frame[data-zk-art-shape=wide]>img{height:auto;aspect-ratio:var(--zk-art-aspect,auto)}
  /* The credit under the photograph wraps to the photograph's width; it never widens the frame. */
  .zk-stage[data-zk-form=portrait] .zg-portrait:not([data-kind=player]) .zg-portrait-frame>small{align-self:stretch;contain:inline-size}
  .zk-stage[data-zk-form=portrait] .zg-portrait:not([data-kind=player]) .zg-portrait-frame[data-zk-filled=mark]:has(img[src*=".jpg" i],img[src*=".jpeg" i])>.zk-mark-tile>img{height:calc(100cqh - 52px);width:auto;max-width:100%}
}
/* On a phone the photograph keeps to part of the screen, so the detail block and the actions fit under it (L2). */
@media (max-width:900px){.zg-portrait:not([data-kind=player]) .zg-portrait-frame>img{max-height:36vh}}
/* Round 3 (G3): on a tablet and a phone the frame is as wide as its photograph and centred, so the credit sits under
   the picture it names, wrapped to its width, never at the panel's far edge. */
@media (max-width:900px){
  .zg-portrait:not([data-kind=player]) .zg-portrait-frame:has(>img){align-self:center;width:fit-content;max-width:100%}
  .zg-portrait:not([data-kind=player]) .zg-portrait-frame:has(>img)>small{align-self:stretch;contain:inline-size}
}
/* A Wikipedia photograph of a group or a person filed as an organisation is a JPEG, never a logo: it is drawn as the
   photograph it is, whole in the frame, not shrunk onto the white logo tile (G3). Logos are SVG or PNG. */
.zg-portrait:not([data-kind=player]) .zg-portrait-frame[data-zk-filled=mark]:has(img[src*=".jpg" i],img[src*=".jpeg" i])>.zk-mark-tile{display:flex;justify-content:center;flex:1 1 auto;width:100%;min-height:0;aspect-ratio:auto;padding:0;border-radius:6px;background:none}
.zg-portrait:not([data-kind=player]) .zg-portrait-frame[data-zk-filled=mark]:has(img[src*=".jpg" i],img[src*=".jpeg" i])>.zk-mark-tile>img{max-height:100%;object-fit:contain;border-radius:6px}
.zg-portrait:not([data-kind=player]) .zg-portrait-frame[data-zk-filled=mark]:has(img[src*=".jpg" i],img[src*=".jpeg" i])>strong{display:none}
@media (max-width:900px){.zg-portrait:not([data-kind=player]) .zg-portrait-frame[data-zk-filled=mark]:has(img[src*=".jpg" i],img[src*=".jpeg" i])>.zk-mark-tile>img{max-height:36vh}}
/* Region map: every country the report names lit in one colour, the desk's, so the caption ("Countries the report
   names") keys it and each is named by its label (round 2: two colours had no key); its border drawn so neighbours read
   apart; labels draw at 13px (12px on a phone) whatever size the map is shown (--zg-unit, set from the drawn width). */
.zg-country-named{fill:var(--zk-accent);stroke:#0b1016;stroke-width:.8}
.zg-country-label{font:500 calc(13px * var(--zg-unit,1.4))/1 var(--sans,Arial);stroke-width:calc(3px * var(--zg-unit,1.4))}
@media (max-width:600px){.zg-country-label{font-size:calc(12px * var(--zg-unit,2.4))}}
/* Election map (rules G6, G7, T1): every fill drawn has its swatch, in the tally's words. A race on the ballot with no
   count or odds yet is its own fill; a candidate whose party no source supplies is an open ring, never Other; on the
   national map an official count is outlined. */
.zg-map path[data-party=none]{fill:#161d25}
.zg-map path[data-party=ballot]{fill:#2a3441;stroke:#ffffff8c;stroke-dasharray:3 2}
.zg-map path[data-basis=official]:not([data-focus]){stroke:#fff;stroke-width:2px}
:is(.zg-row,.zg-legend) i[data-party=neutral]{background:#3a4553}
:is(.zg-row,.zg-legend) i[data-party=ballot]{background:#2a3441;border:1px dashed #ffffffb3;box-sizing:border-box}
:is(.zg-row,.zg-legend) i[data-party=none]{background:#161d25;border:1px solid #ffffff4d;box-sizing:border-box}
:is(.zg-row,.zg-legend) i[data-party=unknown]{background:none;border:1.5px solid #fff;box-sizing:border-box}
.zg-legend i[data-basis=official]{display:inline-block;width:12px;height:10px;border:2px solid #fff;border-radius:2px;background:none;box-sizing:border-box}
/* ---------- Culture, World, Politics and Crypto templates, round 2 (docs/news-key-card-rules.md) ---------- */
/* The national map keys itself under the map: the office and its count of races, each fill with its count, and one line
   on what the colours rest on (official counts or odds, the venues, as of when). It belongs to the graphic, so the frame
   never drops it (L2) and the map is never a colour without a key (G6). */
.zg-map-key>.zg-legend-head{flex:1 0 100%;font:500 13px/1.4 var(--sans,Arial);color:#fff}
.zg-map-key b{font-weight:600}
.zg-map-key>.zg-map-note{flex:1 0 100%;font:400 12px/1.45 var(--sans,Arial);color:#fff}
/* The map and its key share one box: the map takes what the key leaves, and a short box sets the key tighter. Round 4
   (G6, L2): the key is never cut into pieces. Its head ("Senate races, 35 on the 2026 ballot") says the counts are races,
   not the tally's seats, so a short box runs it inline in front of the swatches instead of dropping it, and every swatch
   stays; on a phone whose map is still short the whole key moves to the column (fitCard's seventh step, below). */
.zg-map-card{display:flex;flex-direction:column;width:100%;height:100%;min-height:0;container-type:size}
.zg-map-card>.zg-map-wrap{flex:1 1 auto;min-height:0;height:auto}
.zg-map-card>.zg-legend{flex:none}
@container (max-height:420px){.zg-map-key{gap:2px 12px;margin-top:6px}.zg-map-key>.zg-legend-head{flex:0 1 auto;font-size:12px;line-height:1.3}}
@container (max-height:260px){.zg-map-key{font-size:12px;line-height:1.3}}
/* Step C (C9, C16): the national key is one row of swatches with their counts, and its basis one foot line in short form;
   the outline swatch opens the foot line, beside the official counts it marks. */
.zg-map-key>span{white-space:nowrap}
.zg-map-key>.zg-map-note>i[data-basis=official]{margin-right:7px;vertical-align:-1px}
/* Odds bars fill the graphic (L6): each outcome is an even band of the slot, its bar and its words sized to the screen. */
.zg-odds{justify-content:flex-start;gap:clamp(6px,1.4vh,16px)}
.zg-odds>.zg-rung{flex:1 1 0;min-height:0;max-height:120px;font-size:clamp(14px,1.9vh,19px)}
.zg-odds .zg-rung>i,.zg-odds .zg-rung>i::after{height:clamp(14px,4vh,40px);border-radius:4px}
.zg-odds .zg-rung>b{font-size:clamp(17px,2.6vh,28px)}
.zg-odds>:is(.zg-ladder-title,.zg-source){flex:none}
/* Policy and Security tracks sit under the actor's head at the top of the graphic and their stages stretch to fill it
   (L6), never a small band centred in an empty frame. */
.zg-status-track,.zg-incident{justify-content:flex-start}
.zg-status-track>ol{flex:1 1 auto;min-height:0;grid-auto-rows:minmax(0,1fr)}
.zg-status-track li{min-height:0}
.zg-status-track>:is(.zg-status-head,.zg-source,.zg-incident-amount,.zg-incident-chain){flex:none}
/* The track fits its frame whole at every size (L5): measured against its own box, a short frame sets the blocks and
   the head tighter, and the shortest leaves out the source line under the track. */
.zg-status-track{container-type:size;gap:clamp(8px,2.4vh,22px);width:100%;box-sizing:border-box}
@container (max-height:220px){.zg-status-track>ol{gap:4px}.zg-status-track li{padding:4px 10px}.zg-status-track li>span{font-size:12px;line-height:1.2}.zg-status-head>strong{font-size:18px}.zg-status-head>.zg-status-logo{width:36px;height:36px;padding:4px;border-radius:8px}.zg-incident-amount>.zg-figure-value{font-size:32px}}
@container (max-height:150px){.zg-status-track>.zg-source{display:none}.zg-status-track li{padding:0 10px}.zg-status-track>ol{gap:3px}.zg-status-head>strong{font-size:16px}.zg-status-head>.zg-status-logo{width:28px;height:28px;padding:3px;border-radius:7px}}
/* Round 3 (G1, L6): on a desktop the track is drawn at a set share of the graphic, never the card's whole height, and the
   room it leaves goes to the actor's head: the tile with the body's mark, or its name tile until a mark is found, grows
   with the graphic and the body's full name stands large beside it. The head and the track are one block, centred in the
   graphic, together at least the graphic's floor (L6). Four blank slabs the height of the card said one fact. */
@media (min-width:601px){
  .zg-status-track{justify-content:center}
  .zg-status-track>.zg-status-head{gap:clamp(16px,3cqh,28px)}
  .zg-status-track>.zg-status-head>strong{font-size:clamp(22px,min(3.4vw,9cqh),44px);line-height:1.12}
  .zg-status-track>.zg-status-head>.zg-status-logo{width:clamp(56px,28cqh,152px);height:clamp(56px,28cqh,152px);border-radius:18px;padding:clamp(8px,2.4cqh,18px)}
  .zg-status-track>.zg-status-head>.zg-status-logo:not([data-zk-filled=mark]):has(>.zg-name-tile){width:auto;min-width:clamp(56px,28cqh,152px);padding-inline:clamp(12px,3cqh,24px)}
}
.zg-status-track>.zg-status-head>.zg-status-logo:not([data-zk-filled=mark]):has(>.zg-name-tile){display:grid}
.zg-status-track .zg-status-logo>.zg-name-tile{font:600 clamp(13px,5cqh,30px)/1 var(--sans,Arial);color:#0e1116;letter-spacing:0;white-space:nowrap}
@media (max-width:600px){.zg-status-track>.zg-status-head>.zg-status-logo:not([data-zk-filled=mark]):has(>.zg-name-tile){width:auto;min-width:48px;padding-inline:10px}}
/* Round 4 (S1, L5, G6): one track at every size, the Policy and the Security track alike. The four stages are one row of
   square-cornered blocks, each stage named under its block with a fixed gap (never inside it, where a narrow phone ran
   "Advancing" into "Passed"), and the blocks are only as tall as a step needs, so the desktop never draws four tall empty
   slabs and the head takes the room. The stage the report states is lit in the desk's colour; the stages before it are
   drawn done (the desk's colour mixed into the bar), so the track shows progress; the stages after it keep the bar. */
.zg-status-track>ol{grid-template-columns:repeat(4,minmax(0,1fr));grid-template-rows:auto;grid-auto-rows:auto;gap:4px 8px;flex:none;height:auto;min-height:0}
.zg-status-track li,.zg-status-track li[data-now]{display:flex;flex-direction:column;align-items:stretch;justify-content:flex-start;gap:8px;min-width:0;min-height:0;padding:0;border-radius:0;background:none}
.zg-status-track li::before{content:'';display:block;height:clamp(28px,40cqh,240px);border-radius:4px;background:var(--zk-bar)}
.zg-status-track li[data-done]::before{background:color-mix(in srgb,var(--zk-accent) 38%,var(--zk-bar))}
.zg-status-track li[data-now]::before{background:var(--zk-accent)}
.zg-status-track li>span,.zg-status-track li[data-now]>span{font:500 clamp(14px,1.2vw,17px)/1.2 var(--sans,Arial);color:#fff}
.zg-status-track li[data-now]>span{font-weight:700}
@media (max-width:600px){.zg-status-track li>span,.zg-status-track li[data-now]>span{font-size:12px}}
@media (max-width:360px){.zg-status-track>ol{gap:4px 6px}.zg-status-track li>span,.zg-status-track li[data-now]>span{letter-spacing:-.01em}}
/* Round 4 (L5, S1, 4ae28506): a track too narrow for four names left-aligned side by side (a 320 phone: the lit
   "Advancing", set bold, ran into "Passed" a pixel away) keeps its one row of four (round 2: a two-by-two wrap loses
   the track's order), with each name centred under its own block so a long name shares the room its shorter
   neighbours leave, the gutters a step tighter, and the lit stage named at the others' weight (its block is lit, which
   says it). Measured on the track's own width, so it follows the frame. */
@container (max-width:300px){.zg-status-track>ol{column-gap:4px}.zg-status-track li>span{align-self:center;text-align:center}.zg-status-track li[data-now]>span{font-weight:500}}
/* The region map: land reads apart from the sea, and a lit place still drawn small is ringed in the lit colour. */
.zg-worldmap .zg-country:not(.zg-country-named){fill:#283546}
/* Round 4 (G1, G6): the land a small lit place sits in is shaded a lighter tint of the lit colour, named on its land. */
.zg-worldmap .zg-country.zg-country-host{fill:color-mix(in srgb,var(--zk-accent) 34%,#283546)}
.zg-country-ring{fill:none;stroke:var(--zk-accent);stroke-width:calc(2.5px * var(--zg-unit,1.4));r:calc(14px * var(--zg-unit,1.4))}
/* Round 3 (L5): a ringed place's label stands at the ring's centre and is moved off it by the ring's drawn radius plus a
   gap, in the drawing's own units like the ring itself, so it clears the ring at every size. The country the place sits
   in or beside is named on its land in the regular weight: named, not lit (G1). */
.zg-country-label[data-side=start]{transform:translateX(calc(22px * var(--zg-unit,1.4)))}
.zg-country-label[data-side=end]{transform:translateX(calc(-22px * var(--zg-unit,1.4)))}
.zg-country-label.zg-country-context{font-weight:400}
/* Film & TV, Music, Awards, Science: the frame holds its photograph whole and is no larger than it, the credit directly
   under the picture (G3, L6); the asking frame and the name tile keep the whole graphic. */
.zg-portrait:not([data-kind=player]){justify-content:center}
.zg-portrait:not([data-kind=player]) .zg-portrait-frame:has(>img){flex:0 1 auto}
/* A logo or a flag on its tile shrinks with a short frame rather than spilling out of it (L5). */
.zg-portrait-frame[data-zk-filled=mark]>.zk-mark-tile{flex:0 1 auto;min-height:0;max-height:100%}
@media (max-width:900px){.zg-portrait:not([data-kind=player]) .zg-portrait-frame>img{flex:0 1 auto;min-height:0;width:auto;max-width:100%;height:auto}}
/* A tablet's card is one tall column: the photograph takes its whole width and the detail block sits under it, as on a
   phone. */
@media (min-width:601px) and (max-width:900px){
  .zk-stage[data-zk-form=portrait]:not(.zk-stage-wide):has(.zg-portrait:not([data-kind=player])){grid-template-columns:minmax(0,1fr)!important;grid-template-rows:minmax(0,1fr) auto!important}
}
/* Round 4 (L6; S5 Film & TV, Music, Awards: the photograph fills the graphic). A portrait with no detail block of its own
   (the stage is one column, zk-stage-wide) gives the photograph the card's whole width above Read report on a desktop,
   never a column fitted to the picture beside an empty field holding one button (22aaf471, 3d284c27, 6042d0ce). */
@media (min-width:901px){
  .zk-stage-wide[data-zk-form=portrait]:has(.zg-portrait:not([data-kind=player])){container-type:size;grid-template-columns:minmax(0,1fr)!important}
  .zk-stage-wide[data-zk-form=portrait] .zg-portrait:not([data-kind=player]) .zg-portrait-frame>img{max-width:calc(100cqw - 24px);height:calc(100cqh - 120px);max-height:calc(100cqh - 120px)}
  .zk-stage-wide[data-zk-form=portrait] .zg-portrait:not([data-kind=player]) .zg-portrait-frame[data-zk-art-shape=wide]>img{width:calc(100cqw - 24px);height:auto;max-height:calc(100cqh - 120px)}
}
/* Round 4 (L6; 7cc76250, 32f654e7, 3285fd73): on a tablet and a phone the photograph's designed frame is the graphic. It
   fills the whole track, the picture whole and centred in it at the frame's full width (no inset), the credit at the
   frame's foot, so no empty band floats above or below a framed picture. */
@media (max-width:900px){
  .zg-portrait:not([data-kind=player]) .zg-portrait-frame:has(>img){flex:1 1 auto;align-self:stretch;width:100%;padding:0 0 10px;justify-content:flex-start}
  .zg-portrait:not([data-kind=player]) .zg-portrait-frame:has(>img)>img{margin:auto 0;max-width:100%;border-radius:12px 12px 6px 6px}
  .zg-portrait:not([data-kind=player]) .zg-portrait-frame:has(>img)>small{padding:0 12px}
}
/* Round 4 (L6, S5 Film & TV note): on a desktop a wide photograph beside its detail block is bound by its column's width,
   so a frame no larger than the picture floated in the taller track with empty bands above and below it. The designed
   frame is the graphic at the track's full height there too: the picture whole and centred in it, the credit at its foot. */
@media (min-width:901px){
  .zk-stage[data-zk-form=portrait]:not(.zk-stage-wide) .zg-portrait:not([data-kind=player]) .zg-portrait-frame[data-zk-art-shape=wide]:has(>img){flex:1 1 auto;align-self:stretch;justify-content:flex-start}
  .zk-stage[data-zk-form=portrait]:not(.zk-stage-wide) .zg-portrait:not([data-kind=player]) .zg-portrait-frame[data-zk-art-shape=wide]>img{margin:auto 0}
}
/* The chamber after the election (S5 Policy, Elections national): one bar per chamber, Democrats from the left and
   Republicans from the right, held or called seats solid, leads striped, the seats with no call or lead in the middle,
   and a white line at half the chamber. */
.zg-chamber{width:100%;height:100%;min-height:0;font-family:var(--sans,Arial)}
.zg-chamber-in{display:flex;flex-direction:column;justify-content:center;gap:clamp(14px,3vh,36px);height:100%;min-height:0}
.zg-chamber-block{display:flex;flex-direction:column;gap:10px;min-width:0}
.zg-chamber-head{display:flex;align-items:baseline;justify-content:space-between;flex-wrap:wrap;gap:4px 12px}
.zg-chamber-head>strong{font:500 clamp(20px,2vw,28px)/1.15 var(--sans,Arial);letter-spacing:-.02em;color:#fff}
.zg-chamber-head>span{font:400 13px/1.4 var(--sans,Arial);color:#fff}
.zg-seatbar{position:relative;display:flex;height:clamp(22px,6vh,56px);border-radius:6px;background:#ffffff14}
.zg-seatbar>i{display:block;flex:var(--n) 1 0;min-width:0}
.zg-seatbar>i:first-of-type{border-radius:6px 0 0 6px}
.zg-seatbar>i:last-of-type{border-radius:0 6px 6px 0}
.zg-majority{position:absolute;left:50%;top:-6px;bottom:-6px;width:2px;margin-left:-1px;background:#fff}
.zg-chamber-key{display:flex;flex-wrap:wrap;gap:6px 16px;font:400 13px/1.4 var(--sans,Arial);color:#fff}
.zg-chamber-key>span{display:inline-flex;align-items:center;gap:7px}
.zg-chamber-key b{font-weight:600}
:is(.zg-chamber-key,.zg-legend) i[data-seat]{display:inline-block;width:12px;height:12px;border-radius:2px;flex:none}
:is(.zg-seatbar,.zg-chamber-key,.zg-legend) i[data-seat=D]{background:#4a8fdf}
:is(.zg-seatbar,.zg-chamber-key,.zg-legend) i[data-seat=R]{background:#df555c}
:is(.zg-seatbar,.zg-chamber-key,.zg-legend) i[data-seat=O]{background:#9aa3ad}
:is(.zg-seatbar,.zg-chamber-key,.zg-legend) i[data-seat=open]{background:#2a3441}
:is(.zg-seatbar,.zg-legend) i[data-seat=D][data-basis=lead]{background:repeating-linear-gradient(135deg,#4a8fdf 0 5px,#2b5688 5px 10px)}
:is(.zg-seatbar,.zg-legend) i[data-seat=R][data-basis=lead]{background:repeating-linear-gradient(135deg,#df555c 0 5px,#8a3237 5px 10px)}
/* Round 4 (G6): the solid-and-striped key is about how a seat is counted, for either party, so it is drawn in a neutral
   ink (white solid, white hatch), never in one party's colour as if leads were that party's. */
.zg-legend i[data-seat=key]{display:inline-block;width:12px;height:12px;border-radius:2px;flex:none;background:#eef1f5}
.zg-legend i[data-seat=key][data-basis=lead]{background:repeating-linear-gradient(135deg,#eef1f5 0 5px,#5b6573 5px 10px)}
/* Round 4 (L2): the national tally's note is a row of its block, set as a note. */
.zg-row.zg-tally-note{display:block}
:is(.zg-seatbar,.zg-legend) i[data-seat=O][data-basis=lead]{background:repeating-linear-gradient(135deg,#9aa3ad 0 5px,#5b626a 5px 10px)}
.zg-chamber-in>.zg-legend{margin-top:0}
/* One chamber alone takes the graphic's height in its bar (L6), never a thin band in an empty frame. Round 3: the bar is
   the flexible track (flex), sized by the room its block leaves after its name and key, never by a fixed cap or a
   viewport step (the round 3 chamber rules below). */
.zg-chamber[data-count="1"] .zg-chamber-head>strong{font-size:clamp(24px,2.6vw,36px)}
.zg-chamber-key small{font:400 12px/1.4 var(--sans,Arial);color:#fff}
.zg-chamber-key i[data-seat=line]{width:2px;height:14px;border-radius:0;background:#fff}
/* The bars fit their frame whole at every size (L5): measured against their own box, a short frame sets them tighter,
   then leaves out the solid-or-striped legend (the key already names the leads in words), then the majority words in the
   head (the detail block gives the seats needed). */
.zg-chamber{container-type:size}
@container (max-height:330px){.zg-chamber-in{gap:10px}.zg-chamber-block{gap:6px}.zg-chamber .zg-seatbar,.zg-chamber[data-count="1"] .zg-seatbar{height:18px}.zg-chamber-head>strong,.zg-chamber[data-count="1"] .zg-chamber-head>strong{font-size:18px}.zg-chamber-key{font-size:12px;gap:2px 12px}}
@container (max-height:150px){.zg-chamber-in>.zg-legend{display:none}}
@container (max-height:190px){.zg-chamber-head>span{display:none}.zg-chamber .zg-seatbar,.zg-chamber[data-count="1"] .zg-seatbar{height:12px}.zg-chamber-in{gap:6px}.zg-chamber-block{gap:4px}}
/* The national map's block keeps its bar and counts as one row, so the frame drops it whole or not at all (L2). */
.zg-row.zg-chamber-row{display:flex;flex-direction:column;align-items:stretch;gap:8px}
.zg-chamber-row>.zg-seatbar{height:18px}
/* On a phone the national block is set a step tighter, so the map keeps its share of the frame (L6). */
@media (max-width:600px){.zg-chamber-tally{gap:4px}.zg-chamber-tally>.zg-focus-state{font-size:18px}.zg-chamber-row{gap:6px}.zg-chamber-row>.zg-seatbar{height:14px}.zg-chamber-row .zg-chamber-key{font-size:12px;gap:0 10px}.zg-chamber-row .zg-chamber-key i[data-seat]{width:10px;height:10px}.zg-chamber-row .zg-chamber-key i[data-seat=line]{width:2px;height:12px}}
.zg-chamber-detail>.zg-chamber-name{margin:8px 0 0;font-weight:500}
/* Item 24 (Palash 2026-11-06 night, "the chamber block reads in one glance"): the party counts over the bar are gone (they
   wrapped beside a heading that wrapped, and left the seats not called out of the sum); the white line is labelled under
   the bar, centred on it, and one line per party sits under that (seatLedger). */
.zg-majority-tag{flex:none;align-self:center;font:400 12px/1.3 var(--sans,Arial);color:#fff;white-space:nowrap}
.zg-chamber-row>.zg-majority-tag{margin-top:-2px}
@media (min-width:601px){.zw-page[data-news-keycard] :is(.zk-card,.zw-carry-block) .zg-majority-tag{font-size:var(--zk-body)}}
/* The national block is headed by the chamber's name alone, on one line, at the head size of a block, never display type. */
.zg-chamber-tally>.zg-focus-state{font-size:20px;line-height:1.2;white-space:nowrap}
/* The lines: one per party in the bar's order, then the seats not called and the total, adding to the chamber's seats.
   Each line's colour is its 3px rule (the party's; a neutral line for the seats not called; white for the total), never
   its words (W2, item 15). The name on the left and the seats on the right in tabular figures, what the seats are under
   both in the small size; nothing in a line wraps (C6). One across in a narrow block, two across from 400px: a line's
   longest words ("2 held, caucus with Democrats") need half of that, so at item 15's 300px they ran past the block. */
.zg-ledger-wrap{container-type:inline-size;min-width:0}
.zg-ledger{display:grid;grid-template-columns:minmax(0,1fr);gap:8px 20px}
@container (min-width:400px){.zg-ledger{grid-template-columns:repeat(2,minmax(0,1fr))}}
.zg-ledger-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:baseline;column-gap:10px;min-width:0;padding:1px 0 1px 13px;background:linear-gradient(var(--zg-seat,#eef1f5),var(--zg-seat,#eef1f5)) left top/3px 100% no-repeat;font:400 var(--zk-body,14px)/1.3 var(--sans,Arial);color:#fff}
.zg-ledger-row>span{font-weight:500;white-space:nowrap}
.zg-ledger-row>b{font-weight:600;font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
.zg-ledger-row>small{grid-column:1/-1;font:400 12px/1.3 var(--sans,Arial);color:#fff;white-space:nowrap}
.zg-ledger-row[data-seat=D]{--zg-seat:#4a8fdf}
.zg-ledger-row[data-seat=R]{--zg-seat:#df555c}
.zg-ledger-row[data-seat=O]{--zg-seat:#9aa3ad}
.zg-ledger-row[data-seat=open]{--zg-seat:#3a4552}
.zg-ledger-row[data-seat=total]{--zg-seat:#eef1f5}
/* Motion on first paint only (news-keycard.js animate adds zk-enter; item 15, M2): the lines rise 8px into place 40ms
   apart and the bar's segments grow from their own end; never opacity. Reduced motion paints the end state. */
@keyframes zg-ledger-in{from{transform:translateY(8px)}to{transform:none}}
.zk-enter .zg-ledger-row{animation:zg-ledger-in .28s cubic-bezier(.2,.7,.2,1) both;animation-delay:calc(var(--i,0) * 40ms)}
.zk-enter .zg-seatbar>i{animation:zk-grow .5s cubic-bezier(.2,.7,.2,1) both;transform-origin:left center}
.zk-enter .zg-seatbar>i[data-seat=R]{transform-origin:right center}
@media(prefers-reduced-motion:reduce){.zk-enter :is(.zg-ledger-row,.zg-seatbar>i){animation:none;transform:none}}
/* Item 21 (Palash 2026-11-06 night, "crypto policy draws what moves crypto"): the person's photograph whole in its frame
   (G3) beside what moves crypto: the chamber as the election counts leave it, the measure's stages, and Bitcoin and Ether
   since the story. With no photograph the frame's column closes and the drawing takes the width. */
.zg-cpol{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:16px 28px;width:100%;height:100%;min-height:0;box-sizing:border-box}
.zg-cpol:has(.zg-cpol-photo[data-zk-filled=reserve]){grid-template-columns:minmax(0,1fr)}
.zg-cpol:has(.zg-cpol-photo[data-zk-filled=reserve])>.zg-cpol-person{display:none}
/* The photograph takes the height it needs up to the frame's (minmax(0,max-content)), the name directly under it; a tall
   portrait in a short frame is set smaller, whole (object-fit: contain), never cut. */
.zg-cpol-person{display:grid;grid-template-rows:minmax(0,max-content) auto;align-content:start;gap:8px;min-width:0;min-height:0}
.zg-cpol-photo{position:relative;min-height:0;height:100%;display:flex;flex-direction:column;align-items:flex-start;justify-content:flex-start;gap:6px;overflow:hidden}
.zg-cpol-photo>img{display:block;flex:0 1 auto;min-height:0;max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;object-position:left top;border-radius:8px}
.zg-cpol-photo>small{flex:none;font:400 12px/1.3 var(--sans,Arial);color:#fff}
.zg-cpol-name{flex:none;font:600 var(--zk-body,15px)/1.3 var(--sans,Arial);color:#fff}
.zg-cpol-side{display:flex;flex-direction:column;gap:20px;min-width:0;min-height:0}
.zg-cpol-block{display:flex;flex-direction:column;gap:8px;min-width:0}
.zg-cpol-head{font:500 var(--zk-body,15px)/1.3 var(--sans,Arial);color:#fff}
.zg-cpol-chamber .zg-seatbar{height:16px}
.zg-cpol-chamber .zg-ledger-row>small{display:none}
/* The party lines are a name and a count each, so they run two across at every width the card is drawn at. */
.zg-cpol-chamber .zg-ledger{grid-template-columns:repeat(2,minmax(0,1fr));gap:6px 18px}
/* A short frame (1280x720) sets the drawing a step tighter, so every part stays whole inside it (L5): the lines under the
   coins are lower and the gaps smaller; the shortest drops the majority line's words (the bar still draws the line). */
.zg-cpol{container-type:size}
@container (max-height:380px){.zg-cpol-side{gap:12px}.zg-cpol-block{gap:6px}.zg-cpol-coins{gap:8px;min-height:0}.zg-coin-spark{height:24px;margin-top:2px}}
@container (max-height:300px){.zg-cpol-chamber .zg-majority-tag{display:none}.zg-coin-spark{height:18px}}
/* The measure's four stages, the stated one lit in the desk's accent, the stages before it half lit. */
.zg-cpol-stages{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:0;padding:0;list-style:none}
.zg-cpol-stages li{display:flex;flex-direction:column;gap:6px;min-width:0}
.zg-cpol-stages i{display:block;height:8px;border-radius:2px;background:var(--zk-bar,#34414f)}
.zg-cpol-stages li[data-done]>i{background:color-mix(in srgb,var(--zk-accent,#f2c57c) 45%,var(--zk-bar,#34414f))}
.zg-cpol-stages li[data-now]>i{background:var(--zk-accent,#f2c57c)}
.zg-cpol-stages span{font:400 12px/1.3 var(--sans,Arial);color:#fff;white-space:nowrap}
.zg-cpol-stages li[data-now]>span{font-weight:600}
/* Bitcoin and Ether: the name, the price and the move since the story on one line (one ink), the day's line under them,
   the hours before the story in the neutral ink and the line after it green when it ended higher, red when lower (G6).
   The box keeps its size while the series are asked for, so nothing reshapes when they land (item 11). */
.zg-cpol-coins{flex:1 1 auto;min-height:150px;gap:12px}
.zg-coin-row{display:grid;grid-template-columns:minmax(0,1fr) auto auto;align-items:baseline;column-gap:12px;min-width:0;font:400 var(--zk-body,15px)/1.3 var(--sans,Arial);color:#fff}
.zg-coin-row>.zg-coin-name{font-weight:500;white-space:nowrap}
.zg-coin-row>b{font-weight:600;font-variant-numeric:tabular-nums;white-space:nowrap}
.zg-coin-move{font-variant-numeric:tabular-nums;white-space:nowrap}
.zg-coin-spark{grid-column:1/-1;display:block;width:100%;height:36px;margin-top:4px;overflow:visible}
.zg-coin-spark path{fill:none;stroke-width:2;stroke-linejoin:round;vector-effect:non-scaling-stroke}
.zg-coin-spark .zg-coin-before{stroke:#5b6573}
.zg-coin-spark .zg-coin-after{stroke:#eef1f5}
.zg-coin-spark .zg-coin-after[data-tone=up]{stroke:#3ecf8e}
.zg-coin-spark .zg-coin-after[data-tone=down]{stroke:#ff6b6b}
.zg-coin-mark{stroke:#eef1f5;stroke-width:1;stroke-dasharray:2 3;vector-effect:non-scaling-stroke}
.zg-coin-row[data-zk-mark]{cursor:crosshair}
/* First paint only (zk-enter, item 15, M2): the blocks rise 8px into place a step apart and each coin's line draws from
   its left end; never opacity. */
@keyframes zg-coin-draw{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}
.zk-enter .zg-cpol-side>.zg-cpol-block,.zk-enter .zg-coin-row{animation:zg-ledger-in .28s cubic-bezier(.2,.7,.2,1) both;animation-delay:calc(var(--i,0) * 40ms)}
.zk-enter .zg-coin-spark{animation:zg-coin-draw .7s cubic-bezier(.2,.7,.2,1) both;animation-delay:calc(var(--i,0) * 40ms + 120ms)}
@media(prefers-reduced-motion:reduce){.zk-enter :is(.zg-cpol-side>.zg-cpol-block,.zg-coin-row,.zg-coin-spark){animation:none;transform:none;clip-path:none}}
/* A phone sets the photograph above the drawing. */
@media (max-width:600px){.zg-cpol{grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(140px,38%) auto}.zg-cpol-coins{min-height:120px}}
/* The stripes' key is the table's row (C9): a striped swatch in front of its label, in the neutral ink of round 4. */
.zg-row-key>[role=rowheader]::before{content:"";display:inline-block;width:12px;height:12px;margin-right:8px;vertical-align:-1px;border-radius:2px;background:repeating-linear-gradient(135deg,#eef1f5 0 4px,#5b6573 4px 8px)}
/* Step C (C11): the map and the seat bar are each one keyboard stop (ZenaNewsReadout steps their marks; its focus ring is
   the readout's own), and a state or a segment under the pointer reads (crosshair). */
:is(.zg-map path,.zg-seatbar>i)[data-zk-mark]{cursor:crosshair}
/* The state or the segment the readout reads is edged at once (states and segments touch), never lit by opacity (M2). */
.zg-map path[data-zk-mark]:hover{stroke:#fff;stroke-width:2.6px}
.zg-seatbar>i[data-zk-mark]:hover{outline:2px solid #fff;outline-offset:-2px}
/* A row whose value is a list of parties reads label over value, so a narrow column never stacks a list beside its label. */
.zg-row.zg-row-text.zg-row-stack{grid-template-columns:minmax(0,1fr);gap:2px}
.zg-row.zg-row-text.zg-row-stack>b{text-align:left}
/* The stage row stands in for a track held behind the story's photograph (S7); when no photograph comes and the track
   itself is drawn, the row would print its lit stage twice (G6), so it is left out. */
.zk-stage:has([data-zk-filled=reserve]:is([data-zk-reserve-form=incident],[data-zk-reserve-form=status],[data-zk-reserve-form=figure],[data-zk-reserve-form=timeline])) .zg-row-held{display:none}
/* Round 3: a block whose every row the drawn reserve already prints (a Science count, its dates) is left out whole,
   never an empty block beside the graphic. */
.zk-stage:has([data-zk-filled=reserve]:is([data-zk-reserve-form=incident],[data-zk-reserve-form=status],[data-zk-reserve-form=figure],[data-zk-reserve-form=timeline])) .zg-focus:has(>.zg-row-held):not(:has(>:not(.zg-row-held))){display:none}
/* Round 4 (L6): with that block left out and nothing else beside it, the drawn reserve takes the card's whole width, as a
   card with no block does (zk-stage-wide), never a track in two thirds of the card beside an empty column. */
@media (min-width:601px){.zk-stage:not(.zk-stage-wide):has(>.zk-graphic [data-zk-filled=reserve]:is([data-zk-reserve-form=incident],[data-zk-reserve-form=status],[data-zk-reserve-form=figure],[data-zk-reserve-form=timeline])):not(:has(>.zk-side .zg-focus>:not(.zg-row-held))):not(:has(>.zk-side :is(.zk-facts,.zk-read))){grid-template-columns:minmax(0,1fr)!important;grid-template-rows:minmax(0,1fr) auto!important}
.zk-stage:not(.zk-stage-wide):has(>.zk-graphic [data-zk-filled=reserve]:is([data-zk-reserve-form=incident],[data-zk-reserve-form=status],[data-zk-reserve-form=figure],[data-zk-reserve-form=timeline])):not(:has(>.zk-side .zg-focus>:not(.zg-row-held))):not(:has(>.zk-side :is(.zk-facts,.zk-read)))>.zk-side>.zk-actions{flex-direction:row-reverse;align-self:flex-end;align-items:center;gap:18px}}
/* Round 4 (424cc873, G6): the column's copy of a held row (the lit stage, a Science count) is held too while the reserve
   draws it, and a carried block left with only such rows is not shown: the column never prints the lit stage again. */
.zw-workspace:has(>.zw-focus .zk-stage [data-zk-filled=reserve]:is([data-zk-reserve-form=incident],[data-zk-reserve-form=status],[data-zk-reserve-form=figure],[data-zk-reserve-form=timeline])) .zw-carry-block .zg-row-held{display:none!important}
.zw-workspace:has(>.zw-focus .zk-stage [data-zk-filled=reserve]:is([data-zk-reserve-form=incident],[data-zk-reserve-form=status],[data-zk-reserve-form=figure],[data-zk-reserve-form=timeline])) .zw-carry-block:has(.zg-row-held):not(:has(.zg-row:not(.zg-row-held))){display:none!important}
/* A named bill's stage beside the seats: four thin bars, only the stage the report states lit (S5 Policy). */
.zg-mini-track>ol{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:4px;margin:2px 0 0;padding:0;list-style:none}
.zg-mini-track li{height:6px;border-radius:2px;background:var(--zk-bar)}
.zg-mini-track li[data-now]{background:var(--zk-accent)}
/* G3 on the filing card: the archive photograph is shown whole in a flat frame, its credit on its own line under it,
   then the filer's name; nothing is laid over the picture. */
html[data-news-view] .zw-page[data-news-keycard] .zf-company.zf-company-photo{display:grid!important;grid-template-rows:minmax(0,1fr) auto auto;gap:10px;padding:12px!important;background:var(--zk-frame)!important;border-radius:12px;justify-content:stretch}
html[data-news-view] .zw-page[data-news-keycard] .zf-company.zf-company-photo>img{position:static!important;inset:auto!important;width:100%!important;height:100%!important;min-height:0;object-fit:contain!important;opacity:1!important;border-radius:6px}
html[data-news-view] .zw-page[data-news-keycard] .zf-company.zf-company-photo::after{display:none!important}
html[data-news-view] .zw-page[data-news-keycard] .zf-company.zf-company-photo>figcaption{position:static!important;inset:auto!important;padding:0!important;background:none!important;color:#fff;font:400 12px/1.4 var(--sans,Arial)}
html[data-news-view] .zw-page[data-news-keycard] .zf-company.zf-company-photo>.zf-issuer{padding:0!important}
/* League table: one row per club, its record, and a bar for its share of wins; the story's own club stands out. The
   rows fill the graphic from its top (no empty band above the table). A bar is the club's own colour when the table
   carries one, else one neutral ink (the desk's colour says nothing about a club, G6). A club's name wraps or, on a
   phone, is its short name; it never ends in an ellipsis (L5). */
.zg-standings{display:flex;flex-direction:column;gap:8px;height:100%;min-height:0;justify-content:flex-start}
.zg-standings>ol{display:grid;flex:1 1 auto;min-height:0;grid-auto-rows:minmax(30px,1fr);gap:6px;margin:0;padding:0;list-style:none}
.zg-standings li{display:grid;grid-template-columns:minmax(1.4em,auto) clamp(28px,2.4vw,40px) minmax(0,1fr) auto minmax(60px,30%);align-items:center;gap:12px;min-height:0;padding:4px 12px;border-radius:6px;background:var(--zk-frame)}
.zg-standings-place{font:500 var(--zk-body,15px)/1 var(--sans,Arial);font-style:normal;font-variant-numeric:tabular-nums;color:#fff;text-align:right}
.zg-standings li[data-named]{outline:1px solid #fff;background:#18212b}
.zg-standings li>img{width:100%;height:auto;max-height:100%;aspect-ratio:1;object-fit:contain}
.zg-standings li>span{font:400 clamp(14px,1.2vw,17px)/1.3 var(--sans,Arial);color:#fff;min-width:0;overflow-wrap:anywhere}
.zg-standings li>b{font:600 clamp(14px,1.2vw,17px)/1 var(--sans,Arial);font-variant-numeric:tabular-nums;color:#fff}
.zg-standings-bar{display:block;height:8px;border-radius:2px;background:linear-gradient(90deg,var(--zg-club-ink,#e6ebf0) var(--w),var(--zk-bar) var(--w))}
.zg-club-short{display:none}
@media (max-width:600px){.zg-standings .zg-club-full{display:none}.zg-standings .zg-club-short{display:inline}}
/* The table fits its frame whole at every size (L5): it is measured against its own box, and each shorter frame drops the
   row ranked last (data-rank, set by the renderer outwards from the named club, else from the top), so the rows kept are
   one unbroken run of the table around the named club and no row is ever dropped between two kept rows (G6). */
.zg-standings{container-type:size}
@container (max-height:364px){.zg-standings li[data-rank="8"]{display:none}}
@container (max-height:328px){.zg-standings li[data-rank="7"]{display:none}}
@container (max-height:292px){.zg-standings li[data-rank="6"]{display:none}}
@container (max-height:256px){.zg-standings li[data-rank="5"]{display:none}}
/* Under 220px the rows step down to 24px, so four still fit (four rows and a two-line title and source need about 204px
   at 320 wide); each tier below drops one more. */
@container (max-height:220px){.zg-standings>ol{grid-auto-rows:minmax(24px,1fr);gap:4px}.zg-standings li{padding:2px 10px}}
@container (max-height:204px){.zg-standings li[data-rank="4"]{display:none}}
@container (max-height:176px){.zg-standings li[data-rank="3"]{display:none}}
@container (max-height:150px){.zg-standings li[data-rank="2"]{display:none}}
/* A crest sits on a light tile inside its record ring, so a dark mark (Raiders, Yankees) stays legible on the dark card
   (G3); the arc and its dot take the club's colour when the table carries one. */
.zg-ring-tile{fill:#fff}
.zg-ring[style*="--zg-club-ink"] .zg-ring-arc{stroke:var(--zg-club-ink)}
.zg-row>i[style*="--zg-club-ink"]{background:var(--zg-club-ink)}
/* Round 4 (G6): a player's or a club's small record ring in the detail block takes the club's ink too. */
.zg-mini-ring[style*="--zg-club-ink"] .zg-ring-arc{stroke:var(--zg-club-ink)}
/* Round 4 (S5 Results): the period scores under the scorebug, a column per period, in one ink with tabular figures. The
   terminal's own table rule (#main th, the micro size) is outranked so no cell draws under the type floor (W5). A short
   graphic (a 320 phone) leaves the period scores out whole rather than letting them run into the scorebug (L5). */
.zg-scoreline{container-type:size}
.zg-periods{flex:none;align-self:center;border-collapse:collapse;font:500 14px/1.2 var(--sans,Arial);font-variant-numeric:tabular-nums;color:#fff}
#main .zg-periods :is(th,td),.zg-periods :is(th,td){height:auto;padding:3px 10px;text-align:center;font-size:inherit;line-height:inherit;font-weight:500;color:#fff}
#main .zg-periods thead th,.zg-periods thead th{font-size:13px;border-bottom:1px solid var(--zk-rule,#ffffff1a)}
#main .zg-periods tbody th,.zg-periods tbody th{text-align:left;padding-left:0}
.zw-workspace[data-zw-density=compact] .zg-periods{font-size:13px}#main .zw-workspace[data-zw-density=compact] .zg-periods :is(th,td),.zw-workspace[data-zw-density=compact] .zg-periods :is(th,td){padding:1px 8px}
@media (max-width:600px){.zg-periods{font-size:13px}#main .zg-periods :is(th,td),.zg-periods :is(th,td){padding:2px 7px}}
@container (max-height:250px){.zg-periods{display:none}}
/* Open item 4: one structured scorebug. Each club is one row on the same columns (crest, name, record, score), the two
   rows are one block (one hairline round it, one between them), and the period table sits directly under it on the same
   columns: its club column under the names, its last period under the scores. */
.zg-scoreline{--zg-sb-crest:clamp(40px,3.6vw,52px);--zg-sb-gap:16px;--zg-sb-pad:16px;justify-content:safe center}
.zw-workspace[data-zw-density=compact] .zg-scoreline{--zg-sb-crest:38px;--zg-sb-gap:14px;--zg-sb-pad:14px}
.zg-scoreline>.zg-scorebug{flex:none;max-height:none;gap:0}
.zw-page[data-news-keycard] .zk-card .zg-scoreline>.zg-scorebug{border:1px solid var(--zk-hair,#ffffff1a);border-radius:12px}
.zw-page[data-news-keycard] .zk-card .zg-scorebug>.zg-score-row{flex:none;display:grid;grid-template-columns:var(--zg-sb-crest) minmax(0,1fr) auto minmax(2.4ch,auto);column-gap:var(--zg-sb-gap);align-items:center;padding-inline:var(--zg-sb-pad);border:0;border-radius:0}
.zw-page[data-news-keycard] .zk-card .zg-scorebug>.zg-score-row+.zg-score-row{border-top:1px solid var(--zk-hair,#ffffff1a)}
.zg-scorebug>.zg-score-row>:is(img,i){width:var(--zg-sb-crest)}
.zg-scorebug>.zg-score-row>div{display:contents}
.zg-scorebug>.zg-score-row small{white-space:nowrap;text-align:right;font:400 var(--zk-body,15px)/1.2 var(--sans,Arial);font-variant-numeric:tabular-nums;color:inherit}
.zg-scorebug>.zg-score-row>.zg-score{text-align:right;font-variant-numeric:tabular-nums}
.zg-scoreline>.zg-periods{align-self:flex-start;box-sizing:border-box;margin:0 0 0 calc(var(--zg-sb-pad) + var(--zg-sb-crest) + var(--zg-sb-gap));width:calc(100% - var(--zg-sb-pad)*2 - var(--zg-sb-crest) - var(--zg-sb-gap))}
#main .zg-scoreline>.zg-periods :is(th,td),.zg-scoreline>.zg-periods :is(th,td){text-align:right;padding:3px 0 3px 14px}
#main .zg-scoreline>.zg-periods :is(thead th:first-child,tbody th),.zg-scoreline>.zg-periods :is(thead th:first-child,tbody th){width:100%;text-align:left;padding-left:0}
/* 2026-11-06 (Palash: "use the same circle thing for results"; open items 3, 4 and 11; C16): the scorebug is the pair of
   record rings every sports card draws (news-story-graphics.js renderScoreline), each club's score large beside its ring
   and the clock or Final between the two scores; the period table sits directly under the pair on the pair's own width
   (one grid column as wide as the pair, centred). Every part holds its final size from the first paint: a ring's size
   comes from the frame (cqh of the scoreline), never from its content, a score keeps the width of its final digits while
   it counts up, and the status has a fixed measure, so a live clock never moves the pair. One ink (W2); the leading
   score is the heavier weight (C7). */
.zg-scoreline{display:grid;grid-template-columns:minmax(0,max-content);grid-auto-rows:auto;justify-content:safe center;align-content:safe center;gap:16px;max-width:100%;margin:0;--zg-ring:min(clamp(88px,8.4vw,136px),34cqh)}
.zw-workspace[data-zw-density=compact] .zg-scoreline{gap:8px;--zg-ring:min(clamp(80px,7.2vw,104px),32cqh)}
.zg-score-pair{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);align-items:center;column-gap:clamp(16px,2vw,32px);min-width:0}
.zg-score-side{display:flex;align-items:center;gap:clamp(12px,1.4vw,24px);min-width:0}
.zg-score-side[data-side="0"]{justify-content:flex-end}
.zg-score-ring{display:flex;flex-direction:column;align-items:center;gap:4px;min-width:0;font-family:var(--sans,Arial);color:#fff;text-align:center}
.zg-score-ring>svg{display:block;flex:none;width:var(--zg-ring);height:var(--zg-ring)}
.zg-score-ring[style*="--zg-club-ink"] .zg-ring-arc{stroke:var(--zg-club-ink)}
.zg-score-club{display:flex;align-items:baseline;justify-content:center;gap:6px;white-space:nowrap;font:400 var(--zk-body,15px)/1.3 var(--sans,Arial)}
.zg-score-club>strong{font-weight:600}
.zg-score-club>span{font-variant-numeric:tabular-nums}
.zg-score-ring>.zg-ring-key{font-size:var(--zk-body,15px);color:#fff}
.zg-score-pair .zg-score{display:block;flex:none;min-width:calc(var(--zg-digits,2) * 1ch);font:400 clamp(40px,4.4vw,64px)/1 var(--sans,Arial);letter-spacing:-.02em;font-variant-numeric:tabular-nums;text-align:center;color:#fff}
.zg-score-side[data-lead=true] .zg-score{font-weight:600}
.zw-workspace[data-zw-density=compact] .zg-score-pair .zg-score{font-size:clamp(34px,3.6vw,48px)}
.zg-score-mid{display:flex;flex-direction:column;align-items:center;gap:2px;width:6.5em;font:600 var(--zk-body,15px)/1.3 var(--sans,Arial);color:#fff;text-align:center;font-variant-numeric:tabular-nums}
.zg-score-mid>small{font:400 var(--zk-body,15px)/1.3 var(--sans,Arial);color:#fff}
.zg-scoreline>.zg-periods{justify-self:stretch;align-self:start;margin:0;width:100%}
#main .zg-scoreline>.zg-periods :is(th,td),.zg-scoreline>.zg-periods :is(th,td){text-align:center;padding:3px 8px}
#main .zg-scoreline>.zg-periods :is(thead th:first-child,tbody th),.zg-scoreline>.zg-periods :is(thead th:first-child,tbody th){width:auto;text-align:left;padding-left:0}
@media (max-width:600px){.zg-scoreline{--zg-ring:min(64px,28cqh)}.zg-score-pair{column-gap:8px}.zg-score-side{gap:8px}.zg-score-pair .zg-score{font-size:32px}.zg-score-club{flex-direction:column;align-items:center;gap:0}.zg-score-ring>.zg-ring-key{white-space:normal}.zg-score-mid{width:4.5em}}
/* 2026-11-06 (Palash: the Steelers League card was "a giant ring with a lone logo and empty space"): one club's ring is
   drawn at a sensible size with the club's key numbers composed beside it as one graphic (renderRings): the record at the
   lead size, what the arc measures under it, then its place and streak as label | value rows (C1), set off by space.
   The ring's size comes from the viewport, never from what loads into the frame (open item 11), and its max-height is the
   same length, so the frame's fit (home-news.js fitCard) reads it as held at its own largest size and never moves the
   description away for room the ring would not take. */
.zg-rings[data-count="1"]>.zg-ring{flex-direction:row;align-items:center;justify-content:center;gap:clamp(20px,3vw,40px);width:auto;max-width:100%}
html[data-news-view] .zw-page[data-news-keycard] .zk-graphic .zg-rings[data-count="1"] .zg-ring>svg,.zg-rings[data-count="1"] .zg-ring>svg{flex:none;width:auto;height:clamp(120px,min(18vw,26vh),240px);max-height:clamp(120px,min(18vw,26vh),240px);min-height:0;aspect-ratio:1}
.zg-ring-facts{display:flex;flex-direction:column;align-items:flex-start;gap:4px;min-width:0;font-family:var(--sans,Arial);color:#fff}
.zg-ring-facts>b{font:500 var(--zk-lead,28px)/1.1 var(--sans,Arial);letter-spacing:-.01em;font-variant-numeric:tabular-nums;white-space:nowrap}
.zg-ring-facts>.zg-ring-key{font-size:var(--zk-body,15px);color:#fff}
.zg-ring-facts>dl{display:grid;grid-template-columns:auto auto;column-gap:24px;row-gap:4px;margin:12px 0 0;padding:0;font:400 var(--zk-body,15px)/1.35 var(--sans,Arial)}
.zg-ring-facts>dl>div{display:contents}
.zg-ring-facts dt{margin:0;color:#fff}
.zg-ring-facts dd{margin:0;text-align:right;font-weight:500;font-variant-numeric:tabular-nums;white-space:nowrap;color:#fff}
.zg-ring-facts dd[data-tone=up]{color:#3ecf8e}.zg-ring-facts dd[data-tone=down]{color:#ff6b6b}
/* Under a photograph slot the place and streak the ring draws are held rows of the table, shown only while the
   photograph stands in for the ring (news-story-graphics.js detail). */
.zk-stage:has([data-zk-filled=reserve]:is([data-zk-reserve-form=crest],[data-zk-reserve-form=rings])) .zg-row-held{display:none}
/* The next game of each club after a final: the label over its game, so a date never breaks across lines. */
.zg-result-detail>.zg-row-when{grid-template-columns:minmax(0,1fr);gap:2px}
.zg-result-detail>.zg-row-when>time{text-align:left}
/* A player's line (S5 Results falls back to the score the report states): the club's crest on its tile and the
   player's name, then each number the report states over the name it gives it, at the scorebug's size. */
.zg-statline{display:flex;flex-direction:column;justify-content:center;gap:clamp(12px,2vh,24px);height:100%;min-height:0;width:100%;max-width:640px;margin:0 auto;font-family:var(--sans,Arial)}
.zg-statline-head{display:flex;align-items:center;gap:14px;min-width:0}
.zg-statline-crest{display:grid;place-items:center;flex:none;width:clamp(48px,5vw,64px);aspect-ratio:1;padding:6px;border-radius:12px;background:#fff;box-sizing:border-box}
.zg-statline-crest>img{width:100%;height:100%;object-fit:contain}
.zg-statline-head>strong{font:500 clamp(20px,2vw,28px)/1.2 var(--sans,Arial);letter-spacing:-.01em;color:#fff;min-width:0;overflow-wrap:anywhere}
.zg-statline-cells{display:grid;grid-template-columns:repeat(var(--zg-cells,3),minmax(0,1fr));gap:10px}
.zg-statline-cells[data-count="1"]{--zg-cells:1}.zg-statline-cells[data-count="2"]{--zg-cells:2}.zg-statline-cells[data-count="4"]{--zg-cells:4}
.zg-statline-cells>div{display:flex;flex-direction:column;gap:8px;min-width:0;padding:clamp(12px,2.4vh,24px) 16px;border-radius:12px;background:#141b24}
.zg-statline-cells b{font:500 clamp(40px,4.6vw,72px)/1 var(--sans,Arial);letter-spacing:-.03em;font-variant-numeric:tabular-nums;color:#fff}
.zg-statline-cells span{font:400 14px/1.3 var(--sans,Arial);color:#fff;overflow-wrap:anywhere}
@media (max-width:600px){.zg-statline-cells{gap:8px}.zg-statline-cells>div{padding:10px 12px}.zg-statline-cells b{font-size:clamp(30px,10vw,44px)}.zg-statline-cells span{font-size:13px}}
/* A short frame sets the line tighter rather than cutting it (L5): the numbers and their names stay whole. */
.zg-statline{container-type:size}
@container (max-height:200px){.zg-statline-head{gap:10px}.zg-statline-crest{width:36px;padding:4px;border-radius:8px}.zg-statline-head>strong{font-size:18px}.zg-statline-cells>div{padding:6px 10px;gap:2px}.zg-statline-cells b{font-size:28px}.zg-statline-cells span{font-size:12px}}
@container (max-height:120px){.zg-statline{gap:4px}.zg-statline-crest{width:28px;padding:3px}.zg-statline-head>strong{font-size:16px}.zg-statline-cells>div{padding:4px 8px}.zg-statline-cells b{font-size:22px}}

/* ---------- Open item 22 (Palash 2026-11-06 night): the club card is the season at a glance ---------- */
/* news-story-graphics.js renderSeason: the badge (crest in its ring) beside the race (bars in each club's colour, the
   leader's total marked through every bar), the season's strip of games under them (each tile the opponent's crest and
   the score, its rule green for a win and red for a loss; the next game's tile ringed in the club's colour). One ground
   (C8): tiles and rows sit on the page's black, set off by a hairline. Words are one ink (W2); colour is on rules and bars.
   The card is a size container, so a short frame sets the drawing tighter and keeps the story's own rows (L2, L5). */
.zg-season{display:flex;flex-direction:column;justify-content:safe center;gap:clamp(10px,3cqh,22px);height:100%;min-height:0;width:100%;font-family:var(--sans,Arial);color:#fff;container-type:size}
.zg-season-top{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:clamp(16px,5cqw,40px);flex:0 1 auto;min-height:0}
.zg-season:not([data-race]) .zg-season-top{grid-template-columns:auto;justify-content:center}
.zg-season-badge{display:flex;flex-direction:column;align-items:center;gap:8px;min-width:0}
html[data-news-view] .zw-page[data-news-keycard] .zk-graphic .zg-season-badge>svg,.zg-season-badge>svg{flex:none;width:clamp(76px,min(30cqh,28cqw),156px);height:auto;max-height:none}
.zg-season-badge .zg-ring-arc{stroke:var(--zg-club-ink,#fff)}
.zg-season-rec{display:flex;flex-direction:column;align-items:center;gap:3px}
.zg-season-rec>b{font:500 var(--zk-lead,28px)/1.05 var(--sans,Arial);letter-spacing:-.01em;font-variant-numeric:tabular-nums;white-space:nowrap}
.zg-season-rec>.zg-ring-key{font:400 var(--zt-label,12px)/1.3 var(--sans,Arial);color:#fff;white-space:nowrap}
.zg-season-head{font:500 var(--zt-label,12px)/1.3 var(--sans,Arial);color:#fff;margin:0 0 8px;white-space:nowrap}
.zg-season-race{display:flex;flex-direction:column;min-width:0;min-height:0}
.zg-season-race>ol{display:grid;gap:clamp(4px,1.4cqh,8px);margin:0;padding:0;list-style:none;min-width:0}
.zg-season-race li{display:grid;grid-template-columns:1.3em 22px minmax(min-content,6.5em) minmax(36px,1fr) auto;align-items:center;column-gap:8px;min-width:0;font:400 13px/1.2 var(--sans,Arial)}
.zg-season-race li>em{font-style:normal;font-variant-numeric:tabular-nums;text-align:right}
.zg-race-crest{display:grid;place-items:center;width:22px;height:22px;font:500 var(--zt-label,11px)/1 var(--sans,Arial)}
.zg-race-crest>img{width:22px;height:22px;object-fit:contain}
.zg-race-name{white-space:nowrap}
.zg-season-race li>b{font:500 13px/1 var(--sans,Arial);font-variant-numeric:tabular-nums;white-space:nowrap;text-align:right}
.zg-race-bar{position:relative;display:block;height:8px;border-radius:2px;background:var(--zk-bar,#34414f)}
.zg-race-bar::after{content:"";position:absolute;inset:0 auto 0 0;width:var(--w,0%);border-radius:2px;background:var(--zg-club-ink,#e6ebf0);transform-origin:left center}
/* The leader's total, one line through every bar. */
.zg-race-bar::before{content:"";position:absolute;top:-4px;bottom:-4px;left:var(--zg-lead,100%);width:2px;margin-left:-1px;border-radius:1px;background:#fff;z-index:1}
.zg-season-race li[data-own]{font-weight:600}
.zg-season-race li[data-own]>b{font-weight:600}
.zg-season-race li[data-own] .zg-race-bar{height:12px}
.zg-season-strip{flex:none;min-width:0}
.zg-season-strip[data-pending]{height:clamp(72px,24cqh,112px)}
/* One row: each tile takes its share of the width (--zg-n tiles), its crest sized to the share; a tile hidden on a phone
   takes no column. */
.zg-season-strip>ol{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:6px;margin:0;padding:0;list-style:none}
.zg-season-strip li{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:5px;min-width:0;padding:7px 2px 9px;border:1px solid var(--zk-rule,#ffffff1a);border-radius:6px;box-sizing:border-box}
.zg-season-strip li::after{content:"";position:absolute;left:6px;right:6px;bottom:2px;height:3px;border-radius:2px;background:var(--zk-bar,#34414f)}
.zg-season-strip li[data-result=W]::after{background:#3ecf8e}
.zg-season-strip li[data-result=L]::after{background:#ff6b6b}
.zg-season-strip li[data-result=T]::after{background:#e6ebf0}
.zg-season-strip li[data-next]{border:1px dashed var(--zg-club-ink,#fff)}
.zg-season-strip li[data-next]::after{display:none}
.zg-season-strip{--zg-crest:min(30px,calc((100cqw - (var(--zg-n,9) - 1) * 6px) / var(--zg-n,9) - 12px))}
.zg-tile-crest{display:grid;place-items:center;width:var(--zg-crest);height:var(--zg-crest);font:500 var(--zt-label,11px)/1 var(--sans,Arial)}
.zg-tile-crest>img{width:100%;height:100%;object-fit:contain}
.zg-season-strip li>b{font:500 12px/1 var(--sans,Arial);letter-spacing:-.01em;font-variant-numeric:tabular-nums;white-space:nowrap}
.zg-season-strip li>small{font:400 var(--zt-label,11px)/1 var(--sans,Arial);color:#fff}
/* First paint only (.zk-enter, item 15; M2, never a fade): the bars grow from their base, the tiles lay in one after
   another from the left. */
@keyframes zg-lay-in{from{transform:translateX(-14px) scale(.86)}to{transform:none}}
.zk-enter .zg-season-strip li{animation:zg-lay-in .34s cubic-bezier(.2,.7,.2,1) both;animation-delay:calc(var(--zg-i,0) * 45ms + 140ms)}
.zk-enter .zg-race-bar::after{animation:zk-grow .6s cubic-bezier(.2,.7,.2,1) both;animation-delay:calc(var(--zg-i,0) * 60ms + 80ms)}
@media(prefers-reduced-motion:reduce){.zk-enter .zg-season-strip li,.zk-enter .zg-race-bar::after{animation:none;transform:none}}
/* A tall frame (1440x900 and up) draws the club card larger, so it fills its room rather than floating in it. */
@container (min-height:420px) and (min-width:500px){.zg-season{gap:clamp(18px,5cqh,32px)}html[data-news-view] .zw-page[data-news-keycard] .zk-graphic .zg-season-badge>svg,.zg-season-badge>svg{width:clamp(120px,34cqh,176px)}.zg-season-rec>b{font-size:32px}.zg-season-race>ol{gap:12px}.zg-season-race li{font-size:15px;grid-template-columns:1.3em 26px minmax(min-content,7em) minmax(40px,1fr) auto}.zg-season-race li>b{font-size:15px}.zg-race-crest,.zg-race-crest>img{width:26px;height:26px}.zg-race-bar{height:10px}.zg-season-race li[data-own] .zg-race-bar{height:14px}.zg-season-head{font-size:13px;margin-bottom:12px}.zg-season-strip{--zg-crest:min(36px,calc((100cqw - (var(--zg-n,9) - 1) * 8px) / var(--zg-n,9) - 12px))}.zg-season-strip>ol{gap:8px}.zg-season-strip li{padding:9px 2px 11px;gap:7px}.zg-season-strip li>b{font-size:13px}}
.zg-season[data-race] .zg-season-race>ol:has(>li:nth-child(7)){gap:8px}
/* A short frame (1280x720) sets the rows and tiles tighter and keeps the story's own rows of a long race. */
@container (max-height:380px){.zg-season-race li{font-size:12px;column-gap:6px}.zg-season-race li>b{font-size:12px}.zg-race-crest,.zg-race-crest>img{width:18px;height:18px}.zg-season-race li{grid-template-columns:1.3em 18px minmax(min-content,6.5em) minmax(32px,1fr) auto}.zg-season-head{margin-bottom:6px}.zg-season-strip{--zg-crest:min(24px,calc((100cqw - (var(--zg-n,9) - 1) * 4px) / var(--zg-n,9) - 10px))}.zg-season-strip>ol{gap:4px}.zg-season-strip li{padding:5px 1px 8px;gap:4px}.zg-season-strip li>b{font-size:var(--zt-label,11px)}.zg-season-rec>b{font-size:24px}}
@container (max-height:380px){.zg-season-race li:nth-child(n+7):not([data-own]):not([data-named]){display:none}}
@container (max-height:300px){.zg-season-race li:nth-child(n+5):not([data-own]):not([data-named]){display:none}.zg-season-rec>.zg-ring-key{font-size:var(--zt-label,11px)}}
/* A narrow frame (phones) keeps the six latest games and the next one, and names each club by its crest. */
@container (max-width:440px){.zg-season-top{gap:14px}.zg-season-race li{grid-template-columns:1.2em 18px minmax(28px,1fr) auto}.zg-race-name{display:none}.zg-season-strip{--zg-crest:22px}.zg-season-strip>ol{gap:4px}.zg-season-strip li:not([data-next]):nth-last-child(n+8){display:none}.zg-season-strip li>b{font-size:var(--zt-label,11px)}}

/* ---------- Layout, round 1 (docs/news-key-card-rules.md L2, L5, L6) ---------- */
/* L2: the card is a frame cut from the screen, never from the story. home-news.js fitWorkspace writes the room under the
   pinned rows as --zw-frame-height at every width, so the card is the same height on every desk and story at a size. */
html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-focus{height:var(--zw-frame-height,auto)!important;max-height:var(--zw-frame-height,none)!important}
/* The older story designs' minimum heights (the award design keeps 240px) never hold the key card taller than its frame. */
html[data-news-view] body .zw-page[data-news-keycard] .zw-workspace[data-news-design] .zs-report-card>.zd-visual:is(.zk-card,.zf-card){min-height:0!important}
/* L2, L6: optional blocks are left out whole, in the rule's order, when the frame cannot hold them beside a graphic at its
   share (home-news.js fitCard writes data-zk-fit): 1 the sentence, 2 the facts, 3 detail rows after the first, 4 Zena's
   read. A filing's are its excerpt, its items and its dates after the first. Each one left out moves to the top of the
   contract column (round 2, below). */
.zk-card[data-zk-fit~="1"] .zk-sub,.zk-card[data-zk-fit~="2"] .zk-facts,.zk-card[data-zk-fit~="3"] :is(.zk-side,.zk-under) .zg-focus>.zg-row~:is(.zg-row,.zg-focus-note),.zk-card[data-zk-fit~="4"] .zk-read,.zf-card[data-zk-fit~="1"] .zf-document>blockquote,.zf-card[data-zk-fit~="2"] .zf-items,.zf-card[data-zk-fit~="3"] .zf-dates>div~div{display:none!important}
/* L2, L5 (round 2): when every optional block is out and the graphic still lacks its share, the headline sizes to the
   frame, a step smaller (data-zk-fit 5). On a phone, where the detail block sits under the graphic and the column sits
   directly under the card, a graphic still short of its share takes the room of everything in the detail block after
   its first line (data-zk-fit 6, round 4): the first row is never optional (L2), so it stays in the card, beside Read
   report where its figure fits there whole (its words wrap beside it; the figure never breaks, and the line is measured
   at its own width, not as the detail column's container, which reads as no width at all), else on its own line above
   it (home-news.js fitCard marks it data-zk-first), and the rest moves
   to the column. A block with no first line moves whole at that step, and a first line that still leaves the graphic
   short moves last (data-zk-fit 8). Whatever share is then left is the graphic's, and nothing clips. */
.zw-focus:has(.zk-card[data-zk-fit~="5"],.zf-card[data-zk-fit~="5"])>.zw-story-header h2{font-size:clamp(18px,1.5vw,21px);line-height:1.2}
@media(max-width:600px){
  .zw-focus:has(.zk-card[data-zk-fit~="5"],.zf-card[data-zk-fit~="5"])>.zw-story-header h2{font-size:16px}
  .zk-card[data-zk-fit~="6"] :is(.zk-side-body,.zk-under)>:not(.zk-facts,.zk-read,.zk-actions):not(:has(>[data-zk-first])),.zk-card[data-zk-fit~="6"] :is(.zk-side-body,.zk-under)>.zg-focus>:not([data-zk-first]){display:none!important}
  .zk-card[data-zk-fit~="6"] .zk-side:has(>.zk-side-body>.zg-focus>[data-zk-first]){flex-direction:row;flex-wrap:wrap;align-items:center;gap:8px 12px}
  .zk-card[data-zk-fit~="6"] .zk-side:has(>.zk-side-body>.zg-focus>[data-zk-first])>.zk-side-body{flex:1 1 0;min-width:auto;container-type:normal}
  .zk-card[data-zk-fit~="6"] .zg-focus>.zg-focus-state[data-zk-first]{white-space:nowrap}
  .zk-card[data-zk-fit~="6"] .zk-side:has(>.zk-side-body>.zg-focus>[data-zk-first])>.zk-actions{margin-left:auto}
  .zk-card[data-zk-fit~="6"] .zg-focus:has(>[data-zk-first]){gap:2px}
  .zk-card[data-zk-fit~="6"] .zg-focus>.zg-focus-office[data-zk-first]{margin-bottom:0}
  .zk-card[data-zk-fit~="8"] .zk-side-body,.zk-card[data-zk-fit~="8"] .zk-under>:not(.zk-actions){display:none!important}
}
/* L2 (round 2): the blocks the frame leaves out of the card sit at the top of the contract column (on a phone, directly
   under the card) above the contract, each on its own surface and labelled by what it is, and each shown only while the
   card leaves it out (home-news.js carryCard copies them; fitCard's data-zk-fit says which). */
.zw-carry{display:contents}
.zw-carry-block,.zw-carry-block>[data-zw-carry-rank]{display:none}
.zw-workspace:has(>.zw-focus [data-zk-fit~="1"]) .zw-carry-block>[data-zw-carry-rank="1"],.zw-workspace:has(>.zw-focus [data-zk-fit~="2"]) .zw-carry-block>[data-zw-carry-rank="2"],.zw-workspace:has(>.zw-focus .zk-card[data-zk-fit~="6"]) .zw-carry-block>[data-zw-carry-rank="6"],.zw-workspace:has(>.zw-focus .zk-card[data-zk-fit~="8"]) .zw-carry-block>[data-zw-carry-rank="8"]{display:block}
.zw-workspace:has(>.zw-focus [data-zk-fit~="3"]) .zw-carry-block>[data-zw-carry-rank="3"],.zw-workspace:has(>.zw-focus .zk-card[data-zk-fit~="6"]) .zw-carry-block>.zg-focus[data-zw-carry-rank="6"]{display:flex;flex-direction:column;gap:8px}
/* What follows the first line (rank 6) and the whole detail block (rank 8) each carry the rows after its first, so they
   are not shown a second time; the whole block carries what follows its first line too. */
.zw-workspace:has(>.zw-focus .zk-card:is([data-zk-fit~="6"],[data-zk-fit~="8"])) .zw-carry-block>[data-zw-carry-rank="3"],.zw-workspace:has(>.zw-focus .zk-card[data-zk-fit~="8"]) .zw-carry-block>.zg-focus[data-zw-carry-rank="6"]{display:none}
.zw-workspace:has(>.zw-focus [data-zk-fit~="1"]) .zw-carry-block:has(>[data-zw-carry-rank="1"]),.zw-workspace:has(>.zw-focus [data-zk-fit~="2"]) .zw-carry-block:has(>[data-zw-carry-rank="2"]),.zw-workspace:has(>.zw-focus [data-zk-fit~="3"]) .zw-carry-block:has(>[data-zw-carry-rank="3"]),.zw-workspace:has(>.zw-focus .zk-card[data-zk-fit~="6"]) .zw-carry-block:has(>[data-zw-carry-rank="6"]),.zw-workspace:has(>.zw-focus .zk-card[data-zk-fit~="8"]) .zw-carry-block:has(>[data-zw-carry-rank="8"]),.zw-workspace:has(>.zw-focus [data-zk-fit~="4"]) .zw-carry-block[data-zw-carry-rank="4"]{display:flex}
.zw-carry-block{flex:none;flex-direction:column;gap:12px;border-radius:10px;background:var(--zk-surface,#10151c);padding:16px 18px;color:#fff;font-family:var(--sans,Arial)}
.zw-carry-head{margin:0;font:500 var(--zt-text,11px)/1.4 var(--sans,Arial);letter-spacing:0;text-transform:none;color:var(--zk-muted,#fff)}
.zw-carry-block .zk-sub{margin:0;max-width:none;font-size:15px}
.zw-carry-block :is(.zk-facts,.zk-read){margin:0;padding:0;border:0}
@media(max-width:600px){.zw-carry-block{padding:14px}}
/* L2 (round 3): the rows after the first sit in a block of their own under the detail block's name, so while the whole
   detail block is in the column (rank 8, or rank 6 for a block with no first line) that block is not shown a second
   time. A graphic's own part left out (a release's description and facts, the national map's source line; fitCard's
   data-zk-gone) shows in the column while the card leaves it out. */
.zw-workspace:has(>.zw-focus .zk-card[data-zk-fit~="8"]) .zw-carry-block[data-zw-carry-part=rows],.zw-workspace:has(>.zw-focus .zk-card[data-zk-fit~="6"]) .zw-carry-block[data-zw-carry-part=rows][data-zw-carry-whole="6"]{display:none}
.zw-carry-block>[data-zw-carry-gone]{display:none}
.zw-workspace:has(>.zw-focus .zk-card[data-zk-gone~="zg-doc-what"]) .zw-carry-block>[data-zw-carry-gone="zg-doc-what"],.zw-workspace:has(>.zw-focus .zk-card[data-zk-gone~="zg-doc-facts"]) .zw-carry-block>[data-zw-carry-gone="zg-doc-facts"],.zw-workspace:has(>.zw-focus .zk-card[data-zk-gone~="zg-map-note"]) .zw-carry-block>[data-zw-carry-gone="zg-map-note"]{display:block}
.zw-workspace:has(>.zw-focus .zk-card[data-zk-gone~="zg-doc-what"]) .zw-carry-block:has(>[data-zw-carry-gone="zg-doc-what"]),.zw-workspace:has(>.zw-focus .zk-card[data-zk-gone~="zg-doc-facts"]) .zw-carry-block:has(>[data-zw-carry-gone="zg-doc-facts"]),.zw-workspace:has(>.zw-focus .zk-card[data-zk-gone~="zg-map-note"]) .zw-carry-block:has(>[data-zw-carry-gone="zg-map-note"]){display:flex}
.zw-carry-block .zg-doc-what{font-size:15px}
.zw-carry-block .zg-map-note{display:block;font:400 13px/1.45 var(--sans,Arial);color:#fff}
/* Round 4 (L2, G6): the national key moves whole, its head, every swatch and its source line, laid out as in the card. */
.zw-carry-block .zg-map-note.zg-map-key{display:flex;flex-wrap:wrap;gap:6px 16px;margin:0}
.zw-carry-block .zg-map-key>:is(.zg-legend-head,.zg-map-note){flex:1 0 100%;font-size:13px}
/* frame320 (round 3, L5, L6): on a phone whose map is still short of its share once the detail block has moved, the
   national map's source line moves to the column, under Map sources directly beneath the card, before the map shrinks to
   a stamp (fitCard's seventh step, taken only when the map grows by it). Round 4: its key goes with it, whole. */
@media(max-width:600px){.zk-card[data-zk-fit~="7"] .zg-map-card>.zg-map-key>.zg-map-note{display:none!important}}
@media(max-width:600px){.zk-card[data-zk-fit~="7"] .zg-map-card>.zg-map-key{display:none!important}}
/* Round 4 (L6, ca36a186): a several-coin chart's legend on a narrow phone took the whole track with each coin's high and
   low on a line of its own, and left the lines a few pixels tall. At the same seventh step (taken only when the lines grow
   by it) each coin's high and low move to the column, named by their coin, and the legend keeps one line per coin. */
@media(max-width:600px){.zk-card[data-zk-fit~="7"] .zg-coin-legend .zg-coin-range{display:none!important}}
.zw-workspace:has(>.zw-focus .zk-card[data-zk-gone~="zg-coin-range"]) .zw-carry-block>[data-zw-carry-gone="zg-coin-range"]{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 10px}
.zw-workspace:has(>.zw-focus .zk-card[data-zk-gone~="zg-coin-range"]) .zw-carry-block:has(>[data-zw-carry-gone="zg-coin-range"]){display:flex}
.zw-carry-block>[data-zw-carry-gone="zg-coin-range"]>span{font:500 14px/1.4 var(--sans,Arial);color:#fff}
.zw-carry-block>[data-zw-carry-gone="zg-coin-range"]>small{font:400 13px/1.4 var(--sans,Arial);color:#fff}
/* L2 (round 3): on a narrow phone the publisher line stays one line wherever the words allow, so the frame
   keeps the line a wrap took: the line is set at the phone's text size, its gap one step tighter. */
@media (max-width:360px){.zw-page[data-news-keycard] .zw-story-copy>p{font-size:12px;column-gap:8px}}
/* G6, L2 (round 4): the publisher line's time names its zone, so on every phone the line is set the same way (the
   phone's text size, the tighter gap). C14: the card carries no Ask Zena, so the line is the publisher and the time. */
@media (max-width:600px){.zw-page[data-news-keycard] .zw-story-copy>p{font-size:12px;column-gap:8px}}
/* L2, L6 (round 3): on a phone the company head is one compact row close over its share line (news-filings.css sets the
   32px tile; this sheet loads after it, so the spacing is set here), and on a narrow phone the line's caption sits close
   under it, so the line keeps the height the spacing took. */
@media (max-width:600px){.zg-company{gap:8px}.zg-company-head{gap:10px}}
@media (max-width:360px){.zg-series>.zg-axis{margin-top:4px}.zg-series>.zg-source{margin-top:2px}}
/* frame320 (round 3, L5): on a narrow phone a several-coin chart's legend (each coin's price, move, high and low) is set
   at the phone's label size and spacing, so the legend and its line fit the graphic whole and never run under Read
   report. */
@media (max-width:360px){.zg-coin-legend{gap:2px 12px;margin-bottom:4px}.zg-coin-legend>li{font-size:12px;line-height:1.25;gap:4px}.zg-coin-legend>li>small{font-size:12px}.zg-coins>.zg-series-head{margin-bottom:4px}.zg-coins>.zg-series-head>span{font-size:12px;line-height:1.3}}
/* Phones: the publisher line wraps in its own column (L5; Ask Zena floats, C14); the actions are one row under the
   detail block, the source wrapping in its own column beside Read report. */
@media(max-width:600px){
  /* The head and the detail block are set a step tighter on a phone so the graphic keeps its share of the frame (L6). */
  html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-focus{padding:14px 14px 12px!important}
  html[data-news-view] .zw-page[data-news-keycard] .zw-focus>.zs-story-body{margin-top:6px!important}
  .zw-page[data-news-keycard] .zw-story-header h2{font-size:21px;line-height:1.2}
  .zk-stage,.zk-stage[data-zk-form]{padding:10px 0 0!important;gap:10px!important}
  .zg-focus-state{font-size:20px}.zg-row{font-size:14px}.zg-row>b{font-size:18px}
  .zw-page[data-news-keycard] .zw-story-copy>p{flex-wrap:nowrap;align-items:center}
  .zw-page[data-news-keycard] .zw-story-copy>p>.zw-story-links{flex:none;margin-left:auto}
  .zk-stage .zk-actions{flex-direction:row;flex-wrap:nowrap;align-items:center;gap:14px;margin-left:0}
  .zk-under>.zk-actions{flex:1 1 100%}
  .zk-actions>.zk-read-report{flex:none;order:2;margin-left:auto}
  .zk-actions>a.zs-report-source{order:1;flex:0 1 auto;min-width:0;align-self:center;overflow-wrap:anywhere}
  /* A filing: the filer's block is the flexible track, the document under it at its own height. */
  html[data-news-view] .zw-page[data-news-keycard] .zf-card>.zf-stage{grid-template-rows:minmax(0,1fr) auto}
  /* A short phone frame (the card under 600px, as on a short laptop): the head and the detail block one step tighter. */
  html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design][data-zw-density=compact]>.zw-focus{padding:12px 12px 10px!important}
  .zw-workspace[data-zw-density=compact] .zw-story-header h2{font-size:18px;line-height:1.2}
  .zw-workspace[data-zw-density=compact] .zk-actions{padding-top:0}
  .zw-workspace[data-zw-density=compact] .zk-actions>.zk-read-report{min-height:40px;padding:0 16px}
  .zw-workspace[data-zw-density=compact] .zg-focus-state{font-size:18px}
  .zw-workspace[data-zw-density=compact] .zg-focus .zg-row>b{font-size:16px}
}
/* Tablets (601 to 900px): the card is wide enough for the desktop composition, the graphic with its detail block beside
   it, so it fits its frame like a desktop card; the contract column follows under the card. */
@media(min-width:601px) and (max-width:900px){
  .zk-stage:not(.zk-stage-wide),.zk-stage:not(.zk-stage-wide)[data-zk-form]{grid-template-columns:minmax(0,1.7fr) minmax(200px,.8fr)!important;grid-template-rows:minmax(0,1fr)!important}
  .zk-stage-wide{grid-template-rows:minmax(0,1fr) auto!important}
  .zk-actions>.zk-read-report{flex:none}
}
/* C14: Ask Zena floats. The one Ask Zena on the News desk is the floating button at the screen's bottom right
   (visual-guide.css draws it on the desk's ground and leaves it room); the card carries no Ask Zena of its own. */
/* L2: on a phone the top nav and The desk row scroll away with the page; the category bar and the subcategory row stay
   pinned. The board stays the one scroller: the two rows are lifted out of the flow over its top, a spacer as tall as
   they are starts its content, and its own scroll moves them up, the bar with them, until the bar reaches the top and
   stays (a position tied to the scroll, never a fade). home-news.js fitWorkspace measures the two rows and sets
   data-zw-away. A browser without scroll timelines keeps them pinned, and the frame is cut from the room that leaves. */
@supports (timeline-scope:--zw-board) and (animation-timeline:--zw-board){
  @media(max-width:600px){
    html[data-zw-away]:has(#dash .zw-page[data-news-keycard])>body{timeline-scope:--zw-board}
    html[data-zw-away]:has(#dash .zw-page[data-news-keycard]) #bfBoard{scroll-timeline:--zw-board block}
    html[data-zw-away]:has(#dash .zw-page[data-news-keycard]) #bfBoard::before{content:'';display:block;height:var(--zw-shell-away,0px)}
    html[data-zw-away]:has(#dash .zw-page[data-news-keycard])>body>.nav,html[data-zw-away]:has(#dash .zw-page[data-news-keycard]) #main>.zc-home-tabs{position:absolute;left:0;right:0;animation-name:zw-shell-away;animation-duration:auto;animation-timing-function:linear;animation-fill-mode:both;animation-timeline:--zw-board;animation-range:0 var(--zw-shell-away,0px)}
    html[data-zw-away]:has(#dash .zw-page[data-news-keycard])>body>.nav{top:0}
    html[data-zw-away]:has(#dash .zw-page[data-news-keycard]) #main>.zc-home-tabs{top:var(--zw-nav-height,0px);height:var(--zw-desk-height,auto)!important;min-height:0}
    html[data-zw-away]:has(#dash .zw-page[data-news-keycard]) #pnlBoard>.zc-board-header{position:relative;z-index:6;animation-name:zw-shell-back;animation-duration:auto;animation-timing-function:linear;animation-fill-mode:both;animation-timeline:--zw-board;animation-range:0 var(--zw-shell-away,0px)}
  }
}
@keyframes zw-shell-away{to{translate:0 calc(-1 * var(--zw-shell-away,0px))}}
@keyframes zw-shell-back{from{translate:0 var(--zw-shell-away,0px)}to{translate:0 0}}

/* ---------- Layout, round 2 (docs/news-key-card-rules.md L2, L5) ---------- */
/* L5 beats the share: once the frame has left out everything it may, a graphic still taller than the room it is left
   sets itself tighter against its own box rather than spilling out of it, cut or laid over the actions. Each step keeps
   every number and its label; the last ones leave out only words the report carries (Read report). */
/* A filing's filer block on a phone (where its box is the card's width, so the card-relative sizes inside it read the
   same): the tile and name smaller, the count beside its words, the two dates on one line. */
@media(max-width:600px){
  html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-zw-density=compact] .zf-card .zf-company{padding:12px 14px;gap:10px}
  html[data-news-view] .zw-page[data-news-keycard] .zf-card .zf-company{container:zf-filer/size}
}
@container zf-filer (max-height:300px){
  .zf-issuer{gap:10px}.zf-mark{width:44px;padding:6px;border-radius:10px}.zf-issuer h3{font-size:24px!important}
  .zf-interval{gap:4px}html[data-news-view] .zw-page[data-news-keycard] .zf-interval>strong{font-size:48px}.zf-interval>span{font-size:13px}.zf-date-bridge{margin-top:4px}
}
@container zf-filer (max-height:220px){
  .zf-mark{width:36px;padding:5px;border-radius:8px}.zf-issuer h3{font-size:20px!important}
  .zf-interval{flex-direction:row;flex-wrap:wrap;align-items:center;column-gap:10px;flex:none}html[data-news-view] .zw-page[data-news-keycard] .zf-interval>strong{font-size:36px}.zf-interval>span{flex:1 1 120px;min-width:0}
  .zf-date-bridge{flex:1 1 100%;flex-wrap:nowrap;gap:8px}.zf-date-bridge time{font-size:14px}.zf-date-bridge i{min-width:12px}
}
/* A tile still showing the filer's ticker (no logo yet) widens to the ticker instead of breaking it ("AAPL", never
   "AA" / "PL"). */
@container zf-filer (max-height:300px){.zf-mark:has(>b){width:auto;min-width:36px;aspect-ratio:auto;padding:4px 8px}.zf-mark>b{white-space:nowrap;overflow-wrap:normal;font-size:13px}}
@container zf-filer (max-height:160px){
  .zf-mark{width:30px;padding:4px;border-radius:7px}.zf-issuer h3{font-size:18px!important}.zf-mark:has(>b){width:auto;height:30px;padding:3px 6px}.zf-mark>b{font-size:12px}
  html[data-news-view] .zw-page[data-news-keycard] .zf-interval>strong{font-size:30px}.zf-interval{row-gap:2px}.zf-date-bridge small{line-height:1.25}
}
/* An agency's release (Primary sources): the agency's head, the act, what it does; the shortest leaves out the release's
   own description, which the report carries. */
.zg-doc{container:zg-doc/size}
/* Round 4 (S1, L6): the document is drawn at its panel's own scale at every height, one continuous scale and never a
   breakpoint's set of small type, so the same template reads the same in a short frame (1280x720, 320x568) as in a tall
   one, the seal and the act as large as the panel allows. Each size is a share of the panel's height (container units)
   between the type floor and the tall panel's cap; it replaces the stepped sizes, here and in news-filings.css. */
.zg-doc .zg-status-head{gap:clamp(10px,3cqh,28px)}
.zg-doc .zg-status-logo{width:clamp(32px,22cqh,144px);height:clamp(32px,22cqh,144px);padding:clamp(4px,2.4cqh,18px);border-radius:clamp(8px,3cqh,24px)}
.zg-doc .zg-status-head>strong{font-size:clamp(15px,8cqh,44px);line-height:1.2}
.zg-doc-body{gap:clamp(6px,3cqh,28px)}
.zg-doc-act{font-size:clamp(20px,14cqh,96px)}
.zg-doc-what{font-size:clamp(13px,3.4cqh,24px);line-height:1.35}
.zg-doc-facts dt{font-size:clamp(12px,2.6cqh,16px)}.zg-doc-facts dd{font-size:clamp(13px,4.2cqh,28px)}
.zg-doc-track{gap:clamp(4px,1.6cqh,8px)}.zg-doc-track li{gap:clamp(4px,1.6cqh,8px)}
.zg-doc-track li>i{height:clamp(10px,4cqh,32px)}.zg-doc-track li>span{font-size:clamp(12px,3cqh,20px)}.zg-doc-track li>time{font-size:clamp(12px,2.6cqh,17px)}
@container zg-doc (max-height:180px){.zg-doc-what,.zg-doc-facts{display:none}}
/* Round 3 (L6, S1, S3): the bar is the graphic's flexible track at every size. Each chamber's name sits at the top, its
   bar takes the height its block leaves after the name and the key (never a hairline under an empty band, never a
   viewport-height step), and a key or legend line is left out only when the measured room is really short. */
.zg-chamber-in{justify-content:flex-start}
.zg-chamber-block{flex:1 1 0;min-height:0}
.zg-chamber .zg-seatbar,.zg-chamber[data-count="1"] .zg-seatbar{flex:1 1 0;height:auto;min-height:12px}
.zg-chamber[data-count="1"] .zg-seatbar{min-height:max(14px,min(35cqh,120px))}
@container (max-height:200px){
  .zg-chamber-head>strong,.zg-chamber[data-count="1"] .zg-chamber-head>strong{font-size:16px}
  .zg-chamber-key{font-size:12px;line-height:1.25;gap:0 8px}.zg-chamber-key>span{gap:5px}.zg-chamber-key i[data-seat]{width:9px;height:9px}
  .zg-chamber-key small{font-size:12px}
}
@container (max-height:150px){.zg-chamber-key>span:has(>i[data-seat=line]){display:none}}
/* Two chambers share the room, so their majority words and the legend leave a step earlier (L5: never overlap). */
@container (max-height:250px){.zg-chamber[data-count="2"] .zg-chamber-key>span:has(>i[data-seat=line]),.zg-chamber[data-count="2"] .zg-chamber-in>.zg-legend{display:none}}
@container (max-height:190px){
  .zg-chamber-block{gap:2px}.zg-chamber-head>strong,.zg-chamber[data-count="1"] .zg-chamber-head>strong{font-size:15px;line-height:1.15}
  .zg-chamber-key,.zg-chamber-key small{line-height:1.15}
}
/* A standings table in a narrow box (a phone): the columns closer, the bar narrower, so a club's short name is one word
   on one line and no row grows into the next. */
@container (max-width:320px){
  .zg-standings li{grid-template-columns:minmax(1.2em,auto) 24px minmax(0,1fr) auto minmax(40px,24%);gap:6px;padding:2px 8px}
  .zg-standings li>span{overflow-wrap:break-word}
}
/* A mark on its tile in a short phone frame: the tile stays square and shrinks with the frame, the mark whole inside it,
   the name and the credit under it. */
@media(max-width:600px){.zg-portrait-frame[data-zk-filled=mark]{container:zk-mark/size}}
.zg-portrait-frame[data-zk-filled=mark]>.zk-mark-tile{grid-template:minmax(0,1fr)/minmax(0,1fr)}
@container zk-mark (max-height:260px){.zg-portrait-frame[data-zk-filled=mark]>.zk-mark-tile{width:max(48px,calc(100cqh - 76px));padding:10px;border-radius:16px}.zg-portrait-frame[data-zk-filled=mark]>strong{font-size:18px}}
/* frame320 (round 3, L5): a chamber's block is never shorter than its name, its bar's least height and its key, so a key
   that wraps on a narrow phone pushes what follows down instead of running under the next chamber or the legend; in a
   short box the single bar's least height steps down first, and the bar keeps taking whatever room is left. */
.zg-chamber-block{min-height:auto}
@container (max-height:240px){.zg-chamber[data-count="1"] .zg-seatbar{min-height:24px}}
/* Two chambers in a short narrow box set their names and keys at the tightest step a little earlier, so both keys fit
   whole above the actions (L5: never clipped). */
@container (max-height:220px){.zg-chamber[data-count="2"] .zg-chamber-in{gap:6px}.zg-chamber[data-count="2"] .zg-chamber-block{gap:2px}.zg-chamber[data-count="2"] .zg-chamber-head>strong{font-size:15px;line-height:1.15}.zg-chamber[data-count="2"] .zg-chamber-key{line-height:1.15;gap:0 8px}}

/* ---------- Clean, step A: the key card (docs/news-key-card-rules.md 4b: C1, C2, C6, C7, C8, C9) ---------- */
/* C8: one ground. The card, its graphic panel and every frame inside the graphic are the page's own black (--bg, the
   ground the News page already paints), set off by one hairline and space, never by a lighter fill. --zk-surface and
   --zk-frame are that ground, so every rule that paints with them (a country's border, a photograph's frame, the
   standings rows) paints the ground too. The older story designs paint the report card and its panel #11171c behind an
   id selector, so the panel is cleared at that weight. */
.zw-page[data-news-keycard]{--zk-surface:var(--bg,#080b10);--zk-frame:var(--bg,#080b10);--zk-hair:rgba(255,255,255,.08);--zk-body:15px;--zk-lead:clamp(22px,1.9vw,28px)}
html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-focus{background:var(--bg,#080b10);border:1px solid var(--zk-hair)}
html[data-news-view] .zw-page[data-news-keycard] :is(.zw-workspace,#landingNewsStage) .zs-report-card,html[data-news-view] .zw-page[data-news-keycard] :is(.zw-workspace,#landingNewsStage) .zs-report-card>.zd-visual{background:transparent!important}
.zw-page[data-news-keycard] .zk-card :is(.zg-portrait-frame:not([data-zk-filled=reserve]),.zg-text[data-zk-filled=photo],.zg-text[data-zk-filled=mark],.zg-text-source:not([data-zk-filled]),.zg-company-figures>div,.zg-statline-cells>div,.zg-score-row,.zg-score-row[data-lead=true]){background:transparent;border:1px solid var(--zk-hair);box-sizing:border-box}
/* C8: the named club's white outline drew a second rule around every named row once the fill went (two lines between
   rows). A standings row is a row of the one table (end of this file); a club the story names is marked by weight (C7). */
.zw-page[data-news-keycard] .zk-card .zg-standings li[data-named]>span{font-weight:600}
/* C2: the card's one foot line, source and time, under the detail block (news-keycard.js render). */
.zk-foot{flex:none;margin:0;font:400 var(--zk-body)/1.4 var(--sans,Arial);color:#fff}
.zk-when{white-space:nowrap}
/* The foot is drawn once at each size: beside the graphic under the detail block on wider screens, under the graphic on
   a phone, where the frame keeps only the block's first line beside Read report (news-keycard.js render), so the card
   always says where its numbers come from (G6). */
@media(min-width:601px){.zk-graphic>figcaption.zk-caption.zk-caption-phone{display:none}}
@media(max-width:600px){.zw-page[data-news-keycard] .zk-card .zk-side .zk-foot{display:none}}
/* A block the frame moves from the card to the top of the column (the carried detail, facts or read) keeps the card's
   ground, its hairline and its type (C7, C8). */
.zw-page[data-news-keycard] .zw-carry-block{background:var(--bg,#080b10);border:1px solid var(--zk-hair)}
/* C7: at most three type sizes on the card: the headline (the story header), the lead value (--zk-lead) and the body
   (--zk-body: 15px, 14px in the compact frame); weight carries the rest. C9: no small secondary line: what sits under a
   lead value, a key, an axis, a range, a source line, a note and the foot are body text in the one ink. A drawing's own
   display figures (a score, a reported figure, a filing's interval, a document's act) scale with the drawing. Phones keep
   their fitted sizes until the phone step; only resizing is checked there. */
.zw-page[data-news-keycard] .zw-workspace[data-zw-density=compact]{--zk-body:14px;--zk-lead:clamp(19px,1.6vw,22px)}
@media (max-width:600px){.zw-page[data-news-keycard]{--zk-body:14px}}
@media (min-width:601px){
  .zw-page[data-news-keycard] :is(.zk-card,.zw-carry-block) :is(.zk-sub,.zk-caption,.zg-focus-office,.zg-focus-note,.zg-focus-name,.zg-row,.zg-row>span,.zg-row>small,.zg-legend,.zg-legend-head,.zg-map-note,.zg-axis,.zg-axis-mark,.zg-axis-time,.zg-axis-range,.zg-range,.zg-source,.zg-ladder-title,.zg-rung,.zg-rung>small,.zg-figure-label,.zg-figure>small,.zg-figure dt,.zg-photo>figcaption,.zg-text>span,.zg-text>small,.zg-portrait-frame>small,.zg-status,.zg-side>small,.zg-vs,.zg-detail,.zg-ring>span,.zg-series-head>span,.zg-series-head>small,.zg-score-row small,.zg-periods,.zg-status-track li>span,.zg-chamber-key,.zg-chamber-key small,.zg-incident-chain,.zg-statline-cells span,.zg-standings li,.zk-facts dt,.zk-read>span,.zk-read>p){font-size:var(--zk-body)}
  html[data-news-view] #main .zw-page[data-news-keycard] .zk-card .zg-periods :is(th,td){font-size:var(--zk-body)}
  /* The card's header line (the publisher and the time) is body text too; a map's country names are drawn at the body
     size (--zg-unit undoes the drawing's scale). */
  .zw-page[data-news-keycard] .zw-focus>.zw-story-header .zw-story-copy>p{font-size:var(--zk-body)}
  .zw-page[data-news-keycard] .zk-card .zg-country-label{font-size:calc(var(--zk-body) * var(--zg-unit,1.4))}
  /* A chamber's name is a lead value in a tall frame; a short one keeps its stepped sizes (L5). */
  @container (min-height:331px){.zw-page[data-news-keycard] .zk-card .zg-chamber-head>strong{font-size:var(--zk-lead)}}
  .zw-page[data-news-keycard] :is(.zk-card,.zw-carry-block) :is(.zw-carry-head,.zg-row>b,.zg-row>time,.zg-row.zg-row-text>b,.zg-row.zg-row-move>b,.zk-facts dd,.zg-figure dd){font-size:var(--zk-body);font-weight:500;line-height:1.35;letter-spacing:0;font-variant-numeric:tabular-nums}
  .zw-page[data-news-keycard] .zk-card :is(.zg-focus-state,.zg-ring>b,.zg-rings[data-count="1"] .zg-ring>b,.zg-series-head>b,.zg-side>strong,.zg-score-row strong){font-size:var(--zk-lead);font-variant-numeric:tabular-nums}
}
/* Item 15 (2026-11-06 night, supersedes C15's table form): the description beside the graphic is the fact block
   (news-story-graphics.js sheet). The lead value at the lead size with its move on its line (the one place a word is red
   or green: the staple-AI rule allows colour in the big lead number only), what it is under it, then the facts, drawn at
   the end of this file ("The fact block"). The facts the card adds (zk-facts) continue the same block under it. */
.zw-page[data-news-keycard] :is(.zk-card,.zw-carry-block) .zg-focus[role=table]>.zg-focus-state{margin:0;text-wrap:balance}
.zw-page[data-news-keycard] :is(.zk-card,.zw-carry-block) .zg-focus[role=table]>.zg-focus-office{margin:2px 0 0;font:400 var(--zk-body)/1.35 var(--sans,Arial);color:#fff}
.zw-page[data-news-keycard] :is(.zk-card,.zw-carry-block) .zg-focus[role=table]>.zg-focus-state:last-child{margin-bottom:0}
.zg-unit,.zg-focus-move{white-space:nowrap}
.zw-page[data-news-keycard] .zk-card .zg-focus[role=table]>.zg-focus-state>.zg-focus-move{margin-left:8px;font:500 var(--zk-body)/1 var(--sans,Arial);font-style:normal;letter-spacing:0;font-variant-numeric:tabular-nums}
html body .zg-focus-move[data-tone=up]{color:#3ecf8e}
html body .zg-focus-move[data-tone=down]{color:#ff6b6b}
/* C16: a club's crest, its record ring and its record are one badge, on the photograph's top-left corner (Players) and at
   the head of a player's line (Results): the crest on its light tile inside the ring drawn in the club's ink, the record
   beside it at the lead size, the badge on the page's ground with one hairline (C8). */
.zg-badge{display:flex;align-items:center;gap:10px;box-sizing:border-box}
.zg-portrait-crest.zg-badge,.zg-statline-crest.zg-badge{width:auto;height:auto;aspect-ratio:auto;padding:5px 14px 5px 5px;border-radius:12px;background:var(--bg,#080b10);border:1px solid var(--zk-hair,rgba(255,255,255,.08))}
.zg-badge-mark{position:relative;display:grid;place-items:center;flex:none;width:52px;height:52px}
.zg-badge-ring{position:absolute;inset:0;width:100%;height:100%}
.zg-badge-ring .zg-ring-track,.zg-badge-ring .zg-ring-arc{stroke-width:5}
.zg-badge[style*="--zg-club-ink"] .zg-badge-ring .zg-ring-arc{stroke:var(--zg-club-ink)}
.zg-badge-mark>img{position:relative;width:36px;height:36px;padding:5px;border-radius:50%;background:#fff;object-fit:contain;box-sizing:border-box}
.zg-badge>b{font:500 var(--zk-lead,24px)/1 var(--sans,Arial);letter-spacing:-.01em;color:#fff;font-variant-numeric:tabular-nums;white-space:nowrap}
/* Open item 3: the badge's ring key sits under its record, beside the crest. */
.zg-badge:has(>.zg-ring-key){display:grid;grid-template-columns:auto auto;grid-template-rows:auto auto;column-gap:10px;row-gap:3px;align-items:center}
.zg-badge:has(>.zg-ring-key)>.zg-badge-mark{grid-row:1/span 2}
.zg-badge:has(>.zg-ring-key)>b{align-self:end}
.zg-badge>.zg-ring-key{align-self:start;font-size:12px}
@media (max-width:600px){.zg-badge-mark{width:40px;height:40px}.zg-badge-mark>img{width:28px;height:28px;padding:4px}.zg-badge>b{font-size:18px}.zg-portrait-crest.zg-badge{padding:4px 10px 4px 4px;gap:8px}}

/* C16 (step B fix): the badge sits on the photograph's own corner. The portrait hugs the photo on desktop (the frame
   letterboxed it, so the badge landed in the empty band); the badge then sits inside the photo's top-left corner. */
@media (min-width:901px){
html[data-news-view] .zw-page[data-news-keycard] .zk-graphic:has(>.zg-portrait[data-kind=player]>.zg-portrait-frame[data-zk-filled=photo][data-zk-art-shape]){container-type:size}
html[data-news-view] .zw-page[data-news-keycard] .zk-graphic>.zg-portrait[data-kind=player]:has(>.zg-portrait-frame[data-zk-filled=photo][data-zk-art-shape]){flex:0 1 auto;align-self:center;width:fit-content;max-width:100%;height:auto;max-height:100%}
html[data-news-view] .zw-page[data-news-keycard] .zk-graphic>.zg-portrait[data-kind=player]>.zg-portrait-frame[data-zk-filled=photo][data-zk-art-shape]{flex:none;width:fit-content;max-width:100%}
html[data-news-view] .zw-page[data-news-keycard] .zk-graphic>.zg-portrait[data-kind=player]>.zg-portrait-frame[data-zk-filled=photo][data-zk-art-shape]>img{flex:none;height:auto;width:min(calc(100cqw - 26px),calc((100cqh - 56px) * var(--zk-art-aspect,1.5)));aspect-ratio:var(--zk-art-aspect,auto);max-width:100%}
html[data-news-view] .zw-page[data-news-keycard] .zk-graphic>.zg-portrait[data-kind=player]>.zg-portrait-frame[data-zk-filled=photo][data-zk-art-shape]>small{align-self:stretch;contain:inline-size}
html[data-news-view] .zw-page[data-news-keycard] .zk-graphic>.zg-portrait[data-kind=player]:has(>.zg-portrait-frame[data-zk-filled=photo][data-zk-art-shape])>.zg-portrait-crest{top:20px;left:20px}
}
/* C11 (step C): every mark of a bar, ring, crest, map, track or rung answers the pointer through the shared readout
   (ZenaNewsReadout, kind "marks"). The pointer finds the mark, never a word laid over it: a country's name lets the
   pointer through to its land, and a place drawn smaller than its ring is found anywhere inside the ring. A graphic that
   holds marks shows the keyboard's focus with one hairline in the one ink, never a glow or a fill (C8, W2). */
.zg-worldmap .zg-country-label{pointer-events:none}
.zg-worldmap .zg-country-ring{pointer-events:all}
/* Where marks stand side by side (a run of release bars, countries sharing borders), the one under the pointer is drawn
   lighter or edged at once, so the reader sees which one the readout reads; a change of fill or edge, never of opacity. */
.zg-releases .zg-bar-mark:hover>.zg-bar:not(.zg-bar-now){fill:#8d9aab}
/* A rung prints its quote exactly ("72.5%", "18.25%"), so its price column holds the widest quote in tabular figures and
   every rung's bar track starts and ends at the same place. */
.zg-rung>b{min-width:3.4em;font-variant-numeric:tabular-nums}
.zg-worldmap .zg-country[data-zk-mark]:hover{stroke:#fff;stroke-width:1.2}
[data-zk-read=marks]:focus{outline:none}
[data-zk-read=marks]:focus-visible{outline:1px solid #fff;outline-offset:3px}
/* C11 (step C): the readout (ZenaNewsReadout, news-keycard.js), one for the page, drawn over the graphic it reads. One ink
   on the page's own ground with one hairline (C8); no pill, no glow, no shadow; it never fades (M2): it is placed by
   position and shown or hidden at once, so nothing here transitions. The value is at the card's body size (the graphic's
   --zk-body, carried as --zk-readout-body), what it is and when beside it, the change on a second line. It takes no
   pointer, so the pointer always reads the graphic under it. The marker is a vertical hairline through the graphic and a
   dot on the point; a mark read by key is outlined by one hairline. */
.zk-readout{position:fixed;left:0;top:0;z-index:40;display:flex;flex-direction:column;gap:2px;margin:0;padding:6px 10px;box-sizing:border-box;width:max-content;background:var(--bg,#080b10);border:1px solid rgba(255,255,255,.22);border-radius:6px;color:#fff;font:400 var(--zk-readout-body,15px)/1.35 var(--sans,Arial);letter-spacing:0;font-variant-numeric:tabular-nums;text-align:left;pointer-events:none;transition:none;animation:none}
.zk-readout[hidden],.zk-readout-mark[hidden]{display:none}
.zk-readout-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:0 8px;white-space:nowrap}
.zk-readout-row>b{font-weight:600}
.zk-readout-row>span{white-space:nowrap}
.zk-readout-key{flex:none;align-self:center;width:8px;height:8px;border-radius:50%}
.zk-readout-mark{position:fixed;left:0;top:0;z-index:39;width:0;height:0;pointer-events:none}
.zk-readout-mark>*{position:absolute;left:0;top:0;pointer-events:none;transition:none;animation:none}
.zk-readout-line{width:1px;background:rgba(255,255,255,.6)}
.zk-readout-dot{box-sizing:border-box;width:13px;height:13px;margin:-6.5px 0 0 -6.5px;border-radius:50%;background:#fff;border:2px solid var(--bg,#080b10)}
.zk-readout-ring{box-sizing:border-box;border:1px solid #fff;border-radius:4px}
/* A line is one stop for the keyboard (its arrows step the points): its focus is one hairline in the one ink. */
svg[data-zk-read]:focus{outline:none}
svg[data-zk-read]:focus-visible{outline:1px solid #fff;outline-offset:2px}
svg[data-zk-read][tabindex]{cursor:crosshair}

/* ---------- The table (Palash, 2026-11-06: "the table should be very easy and clear yet animated and cool -> as long as
   its like that it can be standard across everything") ---------- */
/* C15: one table for every description table (news-story-graphics.js sheet), the facts the card adds (zk-facts), a
   league's standings (zg-standings) and a filing's record (zf-table). Each row is a band on the page's own ground (C8): no
   cell border, no divider line and no fill (an alternate fill would be a lighter shade); rows are set apart by one even
   height on the 8px grid (--zt-row: 40px, 32px in the compact frame). The label sits left at the body size in the one
   ink; the value sits right in tabular figures at weight 500 and takes its own width, the label the rest (open item 6).
   A value with a scale (a share, a chance) carries a thin bar under its row (zt-bar), as long as the share and in the
   value's own colour. Motion (M2: position, scale and shape, never opacity) runs only on a new story's first paint
   (news-keycard.js animate adds zk-enter): rows rise into place a step apart, bars grow from zero, numbers count. */
.zw-page[data-news-keycard],.zk-card,.zf-card{--zt-row:40px}
.zw-page[data-news-keycard] .zw-workspace[data-zw-density=compact]{--zt-row:32px}
/* A filing's record (zf-table) keeps the band rows; the description and the card's facts are the fact block (item 15,
   "The fact block" below). */
html body .zf-card .zf-table>div{position:relative;display:grid;grid-template-columns:fit-content(62%) minmax(0,1fr);align-items:center;column-gap:16px;row-gap:0;min-height:var(--zt-row);margin:0;padding:4px 0;box-sizing:border-box;border:0;border-radius:0;outline:0;box-shadow:none;background:none}
html body .zf-card .zf-table dt{min-width:0;margin:0;padding:0;border:0;font:400 var(--zk-body,15px)/1.45 var(--sans,Arial);letter-spacing:0;color:#fff;text-align:left;overflow-wrap:normal}
html body .zf-card .zf-table dd{min-width:0;margin:0;padding:0;border:0;font:500 var(--zk-body,15px)/1.45 var(--sans,Arial);letter-spacing:0;text-align:right;font-variant-numeric:tabular-nums;overflow-wrap:normal;word-break:normal}
html body .zf-card .zf-table{display:flex;flex-direction:column;gap:0;margin:0;padding:0;border:0;border-radius:0;background:none}
.zk-card .zk-read{border-top:0}
.zk-card .zg-figure>dl{border-top:0}
/* The election desk's column draws the chamber tally (home-news.js refreshElectionMarket) as the same table, on the
   page's ground: the lead at the lead size, a party's count in its colour. */
.zw-election-tally{display:flex;flex-direction:column;gap:8px;padding:16px 18px;border:1px solid var(--zk-hair,rgba(255,255,255,.08));border-radius:10px;background:var(--bg,#080b10);color:#fff;font-family:var(--sans,Arial);--zk-body:15px}
.zw-election-tally .zg-focus-state{font:500 22px/1.2 var(--sans,Arial);color:#fff}
.zw-election-tally .zk-foot{margin:0}
/* Standings are the same rows: a band per club, no border, no fill, the same height; the named club by weight. */
.zw-page[data-news-keycard] .zk-card .zg-standings li,.zw-page[data-news-keycard] .zk-card .zg-standings li[data-named]{margin:0;padding:0 4px;border:0;border-radius:0;outline:0;box-shadow:none;background:none}
.zw-page[data-news-keycard] .zk-card .zg-standings li[data-named]>b{font-weight:600}
.zg-standings-bar{position:relative;background:var(--zk-bar,#1c2530);overflow:hidden;color:var(--zg-club-ink,#e6ebf0)}
.zg-standings-bar::after{content:"";position:absolute;inset:0 auto 0 0;width:var(--w);background:currentColor;border-radius:inherit;transform-origin:left center}
/* Motion: rows rise into place 40 ms apart (at most 160 ms), bars grow from zero after them. The facts move in
   news-keycard.js animate (item 15: on the nodes the first paint drew, so a repaint or a live update never replays it). */
@keyframes zt-row-in{from{transform:translateY(8px) scale(.985)}to{transform:none}}
.zk-enter :is(.zf-table>div,.zg-standings li),.zf-card.zk-enter .zf-table>div{animation:zt-row-in .26s cubic-bezier(.2,.7,.2,1) both;animation-delay:calc(var(--zt-i,0) * 40ms)}
.zk-enter .zg-standings-bar::after{animation:zk-grow .5s cubic-bezier(.2,.7,.2,1) both;animation-delay:calc(var(--zt-i,0) * 40ms + 80ms)}
@media(prefers-reduced-motion:reduce){.zk-enter :is(.zf-table>div,.zg-standings li),.zk-enter .zg-standings-bar::after{animation:none;transform:none}}

/* ---------- The fact block (item 15, Palash 2026-11-06 night: "it doesn't have to be a table ... it can be cool and
   animated, but still convey good info in a concise manner ... eye-catching") ---------- */
/* One component everywhere: the description (news-story-graphics.js sheet), the facts the card adds (zk-facts, which
   continue it) and their copies in the column (zw-carry-block). Under the lead the facts are a grid: two across where the
   block is 300px wide or more, one across under it (the flex basis turns into the whole line under 300px). A fact never
   squeezes its value: its least width is its value's own line (the label and the mark ask for none), so a value too wide
   for half the block takes the whole line, and the second unit (zg-fact-sub) moves under the value only when the line is
   full. Nothing is cut and nothing breaks across three lines; only a value wider than the whole block (a long phrase)
   wraps, between its words. The ARIA roles stay (table, row, rowheader, cell). */
html body .zg-focus.zg-focus:is([role=table],[data-zw-carry-rank]){display:flex;flex-flow:row wrap;align-content:flex-start;align-items:stretch;column-gap:16px;row-gap:0;min-width:0}
html body .zg-focus:is([role=table],[data-zw-carry-rank])>:not(.zg-row[role=row]){flex:0 0 100%;max-width:100%;min-width:0}
html body .zg-focus:is([role=table],[data-zw-carry-rank])>.zg-row[role=row]~:not(.zg-row){margin-top:12px}
html body :is(.zw-page[data-news-keycard] .zw-workspace .zk-facts,.zk-facts){display:flex;flex-flow:row wrap;align-content:flex-start;column-gap:16px;row-gap:0;margin:0;padding:0;border:0;border-radius:0;background:none}
/* A fact: its label (one ink, the body size) over its value (one size, tabular figures, one line), its mark under them,
   and a 3px rule on its left edge. Colour sits on the rule and the mark, never on words (the staple-AI rule): the tone
   is up green, down red, the party's colour, the club's own ink, else one neutral line. */
html body :is(.zw-page[data-news-keycard] :is(.zk-card,.zw-carry-block) .zg-focus[role=table]>.zg-row[role=row],.zg-focus>.zg-row[role=row],.zk-facts>div){position:relative;flex-direction:column;justify-content:flex-start;align-items:stretch;gap:2px;flex:1 1 max(calc(50% - 8px),calc((300px - 100%) * 999));max-width:100%;min-width:auto;min-height:0;margin:12px 0 0;padding:1px 0 calc(1px + var(--zf-mark-room,0px)) 14px;box-sizing:border-box;border:0;border-radius:0;outline:0;box-shadow:none;background:none;font:400 var(--zk-body,15px)/1.35 var(--sans,Arial);color:#fff}
/* The rule is drawn, not a border: the report card takes every border inside it away (news-reading.css). */
html body :is(.zg-focus>.zg-row[role=row],.zk-facts>div)::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;border-radius:0;background:var(--zf-rule,#5b6573);pointer-events:none;transform-origin:center top}
/* The fact's display is set apart at a low weight, so a held fact (zg-row-held) and the frame's fit steps still hide it. */
html body :is(.zg-focus>.zg-row[role=row],.zk-facts>div){display:flex}
/* A column copy of the rows (home-news.js carryCard) stacks them one across. */
html body :is(.zw-page[data-news-keycard] .zw-workspace .zw-carry-block .zg-focus:not([role=table])>.zg-row[role=row],.zw-carry-block .zg-focus:not([role=table])>.zg-row[role=row]){flex:none}
html body :is(.zw-page[data-news-keycard] :is(.zk-card,.zw-carry-block) .zg-focus[role=table]>.zg-row[role=row]>[role=rowheader],.zg-focus>.zg-row[role=row]>[role=rowheader],.zk-facts dt){display:block;width:0;min-width:100%;margin:0;padding:0;border:0;font:400 var(--zk-body,15px)/1.35 var(--sans,Arial);letter-spacing:0;color:#fff;text-align:left;white-space:normal;overflow-wrap:normal}
html body :is(.zw-page[data-news-keycard] :is(.zk-card,.zw-carry-block) .zg-focus[role=table]>.zg-row[role=row]>[role=cell],.zg-focus>.zg-row[role=row]>[role=cell],.zk-facts dd){display:block;width:max-content;max-width:100%;min-width:0;margin:0;padding:0;border:0;--zf-value-size:calc(var(--zk-body,15px) + 3px);font:500 var(--zf-value-size)/1.3 var(--sans,Arial);letter-spacing:-.01em;color:#fff;text-align:left;font-variant-numeric:tabular-nums;white-space:normal;overflow-wrap:normal;word-break:normal}
/* A fact in two units: the value, then the second unit at the body size beside it, or under it when the line is full. */
html body :is(.zw-page[data-news-keycard] :is(.zk-card,.zw-carry-block) .zg-focus[role=table]>.zg-row[role=row]>[role=cell],.zg-focus>.zg-row[role=row]>[role=cell]):has(>.zg-fact-sub){display:flex;flex-wrap:wrap;align-items:baseline;column-gap:8px;width:auto}
html body .zg-fact-v{width:max-content;max-width:100%}
html body .zg-fact-sub{font:400 var(--zk-body,15px)/1.35 var(--sans,Arial);letter-spacing:0;white-space:nowrap}
html body .zg-fact-sep{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
/* The tone. A card fact (zk-facts) keeps its sign on its value (data-tone on the dd), so its rule reads it from there. */
html body :is(.zg-focus>.zg-row[role=row],.zk-facts>div)[data-tone=up],html body .zk-facts>div:has(>dd[data-tone=up]){--zf-rule:#3ecf8e;--zf-mark:#3ecf8e}
html body :is(.zg-focus>.zg-row[role=row],.zk-facts>div)[data-tone=down],html body .zk-facts>div:has(>dd[data-tone=down]){--zf-rule:#ff6b6b;--zf-mark:#ff6b6b}
html body .zg-focus>.zg-row[role=row][data-tone=party][data-party=D]{--zf-rule:#4a8fdf;--zf-mark:#4a8fdf}
html body .zg-focus>.zg-row[role=row][data-tone=party][data-party=R]{--zf-rule:#df555c;--zf-mark:#df555c}
html body .zg-focus>.zg-row[role=row][data-tone=club]{--zf-rule:color-mix(in srgb,var(--zg-tone,#fff),#fff 15%);--zf-mark:color-mix(in srgb,var(--zg-tone,#fff),#fff 15%)}
/* The marks, under the value, as wide as the fact, drawn in the fact's tone: a share's bar (0 to 100) on a faint track,
   a series' sparkline (its own direction's colour), a record's win-loss track (a win rises from the middle line, a loss
   hangs from it), a club's crest on its light disc (G3). The mark closes the value's cell (news-story-graphics.js cell)
   and is placed at the fact's foot across its width; the fact keeps the room for it (--zf-mark-room), so the mark gives
   the fact no width of its own and never covers a word. */
html body .zg-fact-mark{position:absolute;left:14px;right:0;bottom:1px;display:block;box-sizing:border-box;width:auto;min-width:0;height:auto;margin:0;padding:0;border:0;border-radius:0;background:none;color:var(--zf-mark,#c9d1da);pointer-events:none}
html body :is(.zg-focus>.zg-row[role=row]):has(>[role=cell]>.zg-fact-mark[data-mark=bar]){--zf-mark-room:10px}
html body :is(.zg-focus>.zg-row[role=row]):has(>[role=cell]>.zg-fact-mark[data-mark=spark]){--zf-mark-room:28px}
html body :is(.zg-focus>.zg-row[role=row]):has(>[role=cell]>.zg-fact-mark[data-mark=track]){--zf-mark-room:24px}
html body :is(.zg-focus>.zg-row[role=row]):has(>[role=cell]>.zg-fact-mark[data-mark=crest]){--zf-mark-room:32px}
html body .zg-fact-mark[data-mark=bar]{height:4px;border-radius:2px;background:rgba(255,255,255,.12);overflow:hidden}
html body .zg-fact-mark[data-mark=bar]>i{position:absolute;inset:0 auto 0 0;display:block;max-width:100%;border-radius:inherit;background:currentColor;transform-origin:left center}
html body .zg-fact-mark[data-mark=spark]{height:22px;overflow:visible}
html body .zg-fact-mark[data-mark=spark]>path{fill:none;stroke:#c9d1da;stroke-width:1.75;stroke-linejoin:round;stroke-linecap:round;stroke-dasharray:1 0}
html body .zg-fact-mark[data-mark=spark][data-dir=up]>path{stroke:#3ecf8e}
html body .zg-fact-mark[data-mark=spark][data-dir=down]>path{stroke:#ff6b6b}
html body .zg-fact-mark[data-mark=track]{display:flex;align-items:center;gap:3px;height:18px;background:linear-gradient(rgba(255,255,255,.18),rgba(255,255,255,.18)) 0 50%/100% 1px no-repeat}
html body .zg-fact-mark[data-mark=track]>i{display:block;flex:0 0 6px;width:6px;height:2px;border-radius:1px;background:#c9d1da}
html body .zg-fact-mark[data-mark=track]>i[data-r=W]{height:8px;background:#3ecf8e;translate:0 -4px;transform-origin:center bottom}
html body .zg-fact-mark[data-mark=track]>i[data-r=L]{height:8px;background:#ff6b6b;translate:0 4px;transform-origin:center top}
html body .zg-fact-mark[data-mark=crest]{right:auto;width:26px;height:26px;padding:3px;border-radius:50%;background:#fff;object-fit:contain}
/* The block is one stop for the keyboard (the readout reads its facts, news-keycard.js ZenaNewsReadout): one hairline in
   the one ink on focus, never a glow or a fill. */
/* The count (news-keycard.js countUp): the number's own text stays in place, exact, and sizes the box; the counting figure
   is drawn over it, right-aligned in the same box, so nothing beside it moves. Only on the card: a copy the column takes
   mid-count shows the true figure. No opacity: the text's fill is clear while the figure counts. */
:is(.zk-card,.zf-card) .zk-count{position:relative;display:inline-block;white-space:pre;-webkit-text-fill-color:transparent}
:is(.zk-card,.zf-card) .zk-count::after{content:attr(data-n);position:absolute;top:0;right:0;white-space:pre;-webkit-text-fill-color:currentColor;pointer-events:none}
html body .zg-focus[role=table][tabindex]:focus{outline:none}
html body .zg-focus[role=table][tabindex]:focus-visible{outline:1px solid #fff;outline-offset:4px}
html body :is(.zw-page[data-news-keycard] .zw-workspace[data-zw-density=compact] .zk-card .zg-focus[role=table]>.zg-row[role=row],.zw-workspace[data-zw-density=compact] :is(.zg-focus>.zg-row[role=row],.zk-facts>div)){margin-top:8px}
@media(max-width:600px){html body :is(.zw-page[data-news-keycard] :is(.zk-card,.zw-carry-block) .zg-focus[role=table]>.zg-row[role=row],.zg-focus>.zg-row[role=row],.zk-facts>div){margin-top:8px}}
/* A fact the reserve visual draws is held: it shows in the table only while a photograph stands in the frame (C3). */
.zw-page[data-news-keycard] .zk-card .zk-stage:has([data-zk-filled=reserve]) :is(.zk-side,.zk-under) .zk-facts>div.zk-held{display:none!important}
/* A signed figure on a number tile is green up and red down; a figure without a sign stays one ink. */
.zk-card .zg-figure :is(.zg-figure-value,dd)[data-tone=up]{color:#3ecf8e}
.zk-card .zg-figure :is(.zg-figure-value,dd)[data-tone=down]{color:#ff6b6b}
/* 2026-11-05 (Palash: "some keycards just have the word 'preview'"): a slot with no photograph and no reserve visual
   (home-news useReserve marks it data-zk-filled="none") is never shown as an empty frame or a word: the graphic gives
   its room to the description table, drawn larger. */
html[data-news-view] .zw-page[data-news-keycard] .zk-stage:has(>.zk-graphic [data-zk-filled=none]){grid-template-columns:minmax(0,1fr)!important;grid-template-rows:minmax(0,1fr) auto!important}
html[data-news-view] .zw-page[data-news-keycard] .zk-stage:has(>.zk-graphic [data-zk-filled=none])>.zk-graphic{display:none!important}
html[data-news-view] .zw-page[data-news-keycard] .zk-stage:has(>.zk-graphic [data-zk-filled=none])>:is(.zk-side,.zk-under){--zk-body:18px;width:100%;max-width:640px;justify-self:start}
/* 2026-11-06: on the key card's map a state leading and not called is hatched in its party's colour, a called state solid
   (news-story-graphics.js renderMap); the key's swatch is the same hatch. */
.zg-map path[data-call=leading][data-party=D]{fill:url(#zg-hatch-D)}.zg-map path[data-call=leading][data-party=R]{fill:url(#zg-hatch-R)}.zg-map path[data-call=leading][data-party=O]{fill:url(#zg-hatch-O)}
.zg-legend i[data-party=lead]{background:repeating-linear-gradient(135deg,#4a8fdf 0 2.5px,#17222f 2.5px 5px);border-radius:2px}
/* 2026-11-06: a world story's facts on its graphic (news-story-graphics.js worldMap callout): the locator map takes the
   left 58% and the annotations sit beside the lit country, joined to it by the country's marker; label one ink at the body
   size, value at the lead size for what happened and the body size for the rest. */
.zg-world-story{display:grid;grid-template-columns:minmax(0,58fr) minmax(0,42fr);align-items:center;gap:24px;width:100%;height:100%;min-height:0}
.zg-world-story>.zg-map-wrap{min-height:0;height:100%}
.zg-world-callout{display:flex;flex-direction:column;gap:12px;margin:0;padding:0 0 0 16px;border-left:2px solid #fff;font-family:var(--sans,Arial);color:#fff}
.zg-world-callout-head{display:flex;align-items:center;gap:8px;font:500 var(--zk-body,15px)/1.3 var(--sans,Arial)}
.zg-world-callout-head>i{width:10px;height:10px;border-radius:50%;background:#fff;margin-left:-22px}
.zg-world-callout>div:not(.zg-world-callout-head){display:flex;flex-direction:column;gap:2px}
.zg-world-callout dt{font:400 var(--zk-body,15px)/1.35 var(--sans,Arial);color:#fff}
.zg-world-callout dd{margin:0;font:500 var(--zk-body,15px)/1.35 var(--sans,Arial);color:#fff;overflow-wrap:break-word}
.zg-world-callout>div:nth-child(2) dd{font-size:var(--zk-lead,26px);line-height:1.15;letter-spacing:-.01em}
@media(max-width:600px){.zg-world-story{grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr) auto;gap:12px}}
/* The facts continue the description's table: no extra space between the two (the side body's 14px gap is taken back). */
.zw-page[data-news-keycard] .zk-card .zk-side .zg-focus[role=table]:has(>.zg-row[role=row])+.zk-facts{margin-top:-14px}

/* ---------- Proportions (Palash, 2026-11-06: "the sizing is still horrible for some markets"; 4b C7, open item 7) ---------- */
/* The laptop and desktop layout first (4b priority), so this holds from 901px up. Every space of the card is on the 8px
   grid: the frame is inset 24px on every side (16px in the compact frame of a 720px laptop), the card's body starts 8px
   under the publisher line, the stage 16px under the sentence (8px compact), the graphic and its side block stand 32px
   apart (24px compact) and the side's blocks 16px apart (8px compact), the facts continuing the table with no space. */
@media (min-width:901px){
  .zw-page[data-news-keycard]{--zk-side-gap:16px}
  .zw-page[data-news-keycard] .zw-workspace[data-zw-density=compact]{--zk-side-gap:8px}
  html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]:not([data-zw-density=compact])>.zw-focus{padding:24px!important}
  html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design][data-zw-density=compact]>.zw-focus{padding:16px!important}
  html[data-news-view] .zw-page[data-news-keycard] .zw-workspace[data-news-design]>.zw-focus>.zs-story-body{margin-top:8px}
  .zw-page[data-news-keycard] .zk-card>.zk-sub{margin-bottom:0}
  .zw-page[data-news-keycard] .zk-stage{padding:16px 0 0;gap:16px 32px}
  .zw-page[data-news-keycard] .zw-workspace[data-zw-density=compact] .zk-stage{padding:8px 0 0;gap:8px 24px}
  .zw-page[data-news-keycard] :is(.zk-side,.zk-side-body){gap:var(--zk-side-gap)}
  .zw-page[data-news-keycard] .zk-card .zk-side .zg-focus[role=table]:has(>.zg-row[role=row])+.zk-facts{margin-top:calc(-1 * var(--zk-side-gap))}
  .zw-page[data-news-keycard] .zw-workspace[data-zw-density=compact] .zk-actions{padding-top:8px}
  /* Balanced with its table: the side block is wide enough for a label and its value on one line at the body size
     (256px at least, about a third of the stage) and the graphic takes the rest. The election map keeps its wider share,
     and a photograph's fitted column its own (above). */
  .zw-page[data-news-keycard] .zk-stage:not(.zk-stage-wide,[data-zk-form=map]){grid-template-columns:minmax(0,1.75fr) minmax(256px,.85fr)}
  /* Top-aligned: the graphic and the side block start on one line. A graphic drawn to its content (a figure, a release's
     bars, a stage track, a timeline, odds by strike, a photograph bound by its width) sits at the top of its track beside
     the table's first row, never centred under it; the side block's table starts at its top and Read report keeps its
     foot, the two on the side's own column edges. The sports graphics keep their placement (their own rules). */
  html[data-news-view] .zw-page[data-news-keycard] .zk-stage>.zk-graphic:not([data-zk-form=scoreline],[data-zk-form=matchup],[data-zk-form=rings],[data-zk-form=crest],[data-zk-form=standings],[data-zk-form=statline]):not(:has(>.zg-portrait[data-kind=player])){justify-content:flex-start!important}
  .zw-page[data-news-keycard] .zk-side-body{justify-content:flex-start}
  .zw-page[data-news-keycard] .zk-graphic :is(.zg-figure,.zg-figbars,.zg-timeline,.zg-ladder,.zg-status-track,.zg-portrait:not([data-kind=player])){justify-content:flex-start}
  .zw-page[data-news-keycard] .zk-graphic .zg-company-figures{align-content:start}
  /* Sized to its track as well as its content: a reported figure's number grows with the graphic's height (a quarter of
     it, 144px at most) and never runs wider than the graphic (--zg-chars, news-story-graphics.js renderFigure), so a short
     number is never a small line in a large frame; a release's bars thicken with the height and their values are lead
     values (C7), the bars 16px apart (8px compact). */
  .zw-page[data-news-keycard] .zk-graphic>:is(.zg-figure,.zg-figbars),.zw-page[data-news-keycard] .zk-graphic>.zg-text>.zg-figure{container-type:size}
  .zw-page[data-news-keycard] .zk-graphic>.zg-figure>.zg-figure-value,.zw-page[data-news-keycard] .zk-graphic>.zg-text>.zg-figure>.zg-figure-value{font-size:clamp(48px,min(24cqh,calc(160cqw / var(--zg-chars,4))),144px)}
  .zw-page[data-news-keycard] .zk-graphic>.zg-figbars{gap:16px}
  .zw-page[data-news-keycard] .zw-workspace[data-zw-density=compact] .zk-graphic>.zg-figbars{gap:8px}
  .zw-page[data-news-keycard] .zk-graphic>.zg-figbars>.zg-figbar>i{height:clamp(12px,6cqh,32px)}
  .zw-page[data-news-keycard] .zk-graphic>.zg-figbars>.zg-figbar>b{font-size:var(--zk-lead)}
  /* An agency's release is a framed document like the filer's panel: the same 24px inset (16px compact), its head at the
     top of the frame. */
  .zw-page[data-news-keycard] .zk-graphic .zg-doc[data-zg-surface=document]{justify-content:flex-start;padding:24px}
  .zw-page[data-news-keycard] .zw-workspace[data-zw-density=compact] .zk-graphic .zg-doc[data-zg-surface=document]{padding:16px}
}
