/* Catholic Information Wire — public teaser and day archives.
   Rendered by functions/_lib/news-teaser.ts. Extracted from that file's
   inline <style> on 2026-07-29: the module had reached 1016 lines against a
   500-line project cap, and the archive pages share this sheet.
   Type floor: no text below 11px. Both colour schemes are declared. */
/* The Marian register: ivory linen and lapis ink by day, a deep lapis night
   with parchment text after dark; antique gold carries every accent. */
:root{color-scheme:light dark;--bg:#faf9f5;--panel:#ffffff;--wash:#f5efdc;--ink:#232a3d;--muted:#46506a;--faint:#5d667f;--rule:#dcdbd2;--lapis:#1b2c55;--accent:#7d6420;--gold:#c0a054;--sans:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,"Helvetica Neue",Arial,sans-serif}
:root[data-theme="dark"]{color-scheme:dark;--bg:#0f1524;--panel:#161d31;--wash:#141b2e;--ink:#e9e6da;--muted:#b6b7c6;--faint:#9a9db1;--rule:#2a3149;--lapis:#e9e6da;--accent:#d3b36a;--gold:#c0a054;--sans:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,"Helvetica Neue",Arial,sans-serif}
:root[data-theme="light"]{color-scheme:light;--bg:#faf9f5;--panel:#ffffff;--wash:#f5efdc;--ink:#232a3d;--muted:#46506a;--faint:#5d667f;--rule:#dcdbd2;--lapis:#1b2c55;--accent:#7d6420;--gold:#c0a054;--sans:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,"Helvetica Neue",Arial,sans-serif}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);font:17px/1.55 "EB Garamond",Georgia,serif}
main{max-width:64rem;margin:0 auto;padding:1.1rem 1.25rem 3rem}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.skip-link{position:fixed;top:.5rem;left:.5rem;z-index:1000;padding:.55rem .85rem;border:2px solid var(--lapis);border-radius:6px;background:var(--panel);color:var(--ink);font:600 .9rem var(--sans);text-decoration:none;transform:translateY(calc(-100% - 1rem))}
.skip-link:focus{transform:translateY(0)}
.story-stream{scroll-margin-top:6rem}
.story-stream:focus-visible{outline:2px solid var(--lapis);outline-offset:5px;border-radius:10px}
/* The masthead lives in assets/masthead.css (functions/_lib/siteMasthead.ts).
   The wire only narrows its column to the story column. */
.ci-mast{--mast-max:64rem}
.dateline{margin:.75rem 0 0;color:var(--faint);font:.8rem/1.4 ui-monospace,Menlo,monospace;text-transform:uppercase;letter-spacing:.065em}
/* Each segment (date, liturgical day, updated-ago) is an unbreakable unit, so
   a narrow screen wraps BETWEEN them, never through "updated / 6m ago". */
.dateline .seg{white-space:nowrap}
/* The language switcher (Español · Italiano) rides the dateline in the same
   register: quiet until wanted. */
.dateline a{color:var(--faint);text-decoration:underline;text-decoration-color:var(--rule);text-underline-offset:3px}
.dateline a:hover{color:var(--accent);text-decoration-color:var(--gold)}
/* THE EDITIONS ARE NAVIGATION, NOT THE RECORD.
   Six of them rode the tail of the dateline in the same uppercase monospace as
   the day, its season and its colour. On a 390px screen that strip ran to five
   lines and 164px -- taller than the masthead above it -- with POLSKI alone on
   the last one, and the first story of the day began at 630px of an 844px
   viewport. They are their own line now, in the sans and quieter than the
   record they sit under, and one swipeable line on a phone. */
.editions{margin:.3rem 0 0;color:var(--faint);font:.78rem/1.45 var(--sans)}
.editions a{color:var(--faint);text-decoration:underline;text-decoration-color:var(--rule);text-underline-offset:3px}
.editions a:hover,.editions a:focus-visible{color:var(--accent);text-decoration-color:var(--gold)}
/* The day must not break mid-phrase; the office after it may, because a strip
   that cannot wrap overflows a 390px screen rather than shrinking. */
.lit{white-space:normal}
.lit-day{white-space:nowrap}
/* The Office, on the end of the liturgical strip. Underlined rather than
   coloured, because the strip already carries one colour and that colour means
   something: it is the colour of the day. */
/* Underlined like every other dateline link. It used to carry a border-bottom,
   and on a phone touch.css makes it a 44px inline-flex box, so the rule drew
   20px under the text and ran the width of the line. */
.lit-hours{color:inherit}
.lit-hours:focus-visible{color:var(--accent);text-decoration-color:var(--gold)}
.lit-dot{display:inline-block;width:.5rem;height:.5rem;border-radius:50%;border:1px solid var(--rule);margin-right:.3rem;vertical-align:-1px}
.lit-green{background:#3a7d44}.lit-violet{background:#5e3a87}.lit-red{background:#a8322d}.lit-rose{background:#cf7f96}.lit-white{background:#f6f2e4}.lit-black{background:#1c1c1c}
h1{margin:.2rem 0 .15rem;font-size:1.85rem;line-height:1.18;font-weight:600}
/* Secondary briefing, after the lead stories. A ruled reading block keeps it
   from competing with the gold-framed Holy See section. */
.tldr{margin:1rem 0 1.25rem;padding:.75rem .15rem;border-block:1px solid var(--rule)}
.tldr-head{display:flex;gap:.6rem;align-items:baseline;margin:0 0 .5rem}
.tldr-head span:first-child{font-family:var(--sans);font-weight:700;font-size:.78rem;letter-spacing:.12em;color:var(--accent)}
.tldr-head span:last-child{color:var(--faint);font-family:var(--sans);font-style:italic;font-size:.8125rem}
.tldr ol{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.2rem 2rem;margin:0;padding:0 0 0 1.4rem}
.tldr li{margin:.2rem 0;padding-right:.4rem;font-size:1rem;line-height:1.45}
.tldr li::marker{color:var(--accent);font-variant-numeric:tabular-nums;font-size:.86rem}
.tldr a{color:var(--ink);text-decoration:none}
.tldr a:hover{color:var(--accent);text-decoration:underline;text-decoration-color:var(--gold)}
.persp{color:var(--faint);font-style:italic}
.day-nav{display:flex;justify-content:space-between;gap:1rem;margin:1.15rem 0 0;font-size:.9rem}
.day-nav a{color:var(--muted);text-decoration:none;border-bottom:1px solid var(--rule)}
.day-nav a:hover{color:var(--accent);border-bottom-color:var(--gold)}
.lede{margin:.35rem 0 0;max-width:44rem;color:var(--muted);font-size:1.02rem;line-height:1.55}
.day{margin-top:1.25rem}
/* The Holy See section: the same wire rows, set apart by a gold frame. It is
   the one section on the page that is not sorted by time — it is sorted by
   authority, because the Church's own record comes first. */
.day.is-holy-see{margin-top:.8rem;padding:.15rem 1rem .6rem;background:var(--wash);border:1px solid var(--gold);border-radius:14px}
.day.is-holy-see .day-head{border-bottom-color:var(--gold)}
.day.is-holy-see .day-head h2{letter-spacing:.1em}
.section-more{margin:.5rem 0 .1rem;font-size:.9rem}
.section-more a{color:var(--accent);text-decoration:none;border-bottom:1px solid var(--rule)}
.section-more a:hover{border-bottom-color:var(--gold)}
.day-head h2 a{color:inherit;text-decoration:none}
.day-head h2 a:hover{color:var(--accent);text-decoration:underline;text-decoration-color:var(--gold)}
.day-head{display:flex;align-items:baseline;gap:.7rem;flex-wrap:wrap;padding-bottom:.45rem;border-bottom:1px solid var(--rule)}
.day-head h2{margin:0;font-family:var(--sans);font-weight:600;font-size:.92rem;letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
.day-count{color:var(--faint);font-family:var(--sans);font-style:normal;font-size:.8125rem}
.rail{display:flex;flex-wrap:wrap;align-items:center;gap:.35rem;margin:.55rem 0 .7rem;padding-bottom:.65rem;border-bottom:1px solid var(--rule);position:relative}
.rail{overflow:hidden}
.rail.is-open{overflow:visible}
.rail .chip-extra{display:none}
.rail.is-open .chip-extra,.rail.is-open .chip-wide-only{display:inline-flex}
.chip-more{font-style:italic}
.rail-label{margin-right:.35rem;font-family:var(--sans);font-weight:700;font-size:.72rem;letter-spacing:.12em;text-transform:uppercase;color:var(--accent)}
/* Entity rail sits AFTER the wire so the fold carries a headline, not two
   pill strips. It keeps the same chip language; the top rule marks it as a
   second pass ("browse by who") rather than another header. */
.rail-entities{margin:1.6rem 0 .7rem;padding-top:.85rem;border-top:1px solid var(--rule)}
/* A subject carried by two or more of the last day's rows, in a rail whose
   window is three days. Colour alone would say nothing to a screen reader, so
   the chip also carries the words; this is the visible half. */
.chip.is-rising{border-color:var(--gold);color:var(--accent)}
.chip.is-rising b{color:var(--accent)}
/* A gold dot marks a chip whose subject has a record in this site. */
.chip.has-record::before{content:"";display:inline-block;width:.34rem;height:.34rem;margin-right:.36rem;border-radius:50%;background:var(--gold);vertical-align:.08em}
/* The Places rail sits directly under the topics, tighter: two rails read
   as one filter bar, not two headers. A chip lit by geo-sense (the reader's
   own continent) borrows the rising mark; the country chip is a link, so it
   carries the underline the other chips do not. */
.rail-places{margin-top:-.2rem}
.chip.is-near{border-color:var(--gold);color:var(--accent)}
.chip.is-near b{color:var(--accent)}
a.chip-near{text-decoration:none}
a.chip-near:hover{border-color:var(--gold)}
.rail-record{margin:0 0 1rem;font-size:.92rem;color:var(--muted)}
.rail-record button{font:inherit;font-size:inherit;background:none;border:0;padding:0;color:var(--accent);cursor:pointer;border-bottom:1px solid var(--rule)}
.rail-record button:hover{border-bottom-color:var(--gold)}
.chip-taste{font-style:italic}
.chip[hidden]{display:none}
.rail-record a{color:var(--accent);text-decoration:none;border-bottom:1px solid var(--rule)}
.rail-record a:hover{border-bottom-color:var(--gold)}

.chip{display:inline-flex;align-items:center;gap:.35rem;padding:.2rem .65rem;border:1px solid var(--rule);border-radius:999px;background:var(--panel);color:var(--muted);cursor:pointer;font:inherit;font-family:var(--sans);font-size:.875rem}
.chip b{color:var(--faint);font-weight:600;font-size:.8125rem;font-variant-numeric:tabular-nums}
.chip:hover{border-color:var(--gold);color:var(--accent)}
.chip[aria-pressed="true"]{border-color:var(--gold);background:var(--wash);color:var(--accent)}
.chip[aria-pressed="true"] b{color:var(--accent)}
.chip b{margin-left:.05rem}
ol.wire{list-style:none;margin:0;padding:0}
ol.wire>li{border-bottom:1px solid var(--rule)}
ol.wire>li[hidden]{display:none}
/* Column 2 is the vote, and it is a FIXED track. Sized to content it grew
   with the number printed inside it: a story upvoted 128 times pushed its own
   headline 2px right of every other headline on the page, so the left edge of
   the wire drifted with the voting. Nothing else in the row depends on the
   count, and nothing else should.

   Column 6 is the picture, and it is RESERVED ON EVERY ROW, including rows
   with no picture. That reverses a deliberate earlier decision, so here is
   the measurement that overturned it. The column used to exist only on rows
   that had a picture, to spare a wire of text rows an empty right-hand
   gutter. But 37% of the stories published in the last seven days carry a
   picture and 63% do not, so every page is a mixture, and the topic and time
   columns landed 100px apart depending on whether a publisher had attached a
   photograph. A reader of a dense wire runs their eye down the times; a
   column that moves 100px between rows is not a column. The empty gutter
   costs almost nothing in exchange, because the reading column is capped at
   32rem by the dek's measure long before it reaches the track's width. */
.story-row{display:grid;grid-template-columns:1.8rem 2.6rem minmax(0,1fr) auto var(--time-col) 5.5rem;align-items:baseline;column-gap:.75rem;row-gap:.1rem;padding:.5rem 0}
/* The publisher's picture. A sixth column that only exists on rows that have
   one, so a wire of text rows keeps its exact measure and does not develop a
   ragged empty gutter. Fixed box, cover fit: publishers ship every aspect
   ratio there is and a wire cannot let them set its rhythm. */
.story-row.has-thumb{grid-template-columns:1.8rem 2.6rem minmax(0,1fr) auto var(--time-col) 5.5rem}
.story-thumb{grid-column:6;grid-row:1 / span 3;align-self:start;display:block;width:5.5rem;height:4.1rem;overflow:hidden;border-radius:3px;border:1px solid var(--rule);background:var(--wash)}
.story-thumb img{width:100%;height:100%;object-fit:cover;display:block;transition:opacity .15s ease}
.story-thumb:hover img{opacity:.85}
/* `a.discuss` is grid-column 4 / -1, and -1 moved when the thumbnail added a
   sixth column: the link slid underneath the picture. Rendered, not caught by
   any test, because every test asserts on markup and the markup was right. */
.story-row.has-thumb a.discuss{grid-column:4 / 6}
/* A picture the publisher has since deleted must leave nothing at all, not a
   broken-image glyph in a frame. The script below removes the frame on error;
   this hides it in the instant before that runs, and permanently without JS. */
.story-thumb img:not([src]),.story-thumb.is-broken{display:none}
/* A picture that 404s must leave a quiet empty frame, never a broken-image
   glyph and never alt text sprawling across the row. */
.story-thumb img[alt='']{color:transparent}
.rank{grid-column:1;grid-row:1}
ol.wire .vote{grid-column:2;grid-row:1 / span 2;align-self:start}
.story-head{grid-column:3;grid-row:1;min-width:0}
/* ---------------------------------------------------------------------
   THE APPARATUS IS SET IN SANS, THE READING IN SERIF.

   Measured on the rendered page 2026-08-04: every text role on a row was
   EB Garamond, and the row's apparatus (topic, time, the sources control,
   discuss) was 13.44px of it. Garamond is a small-x-height face drawn for
   a printed page at 11pt and up; at 13px on a screen it is the right voice
   for a sentence and the wrong one for a label read at a glance. Nothing
   here failed contrast (the lowest ratio on the row was 4.97:1), so this
   is not an accessibility fix. It is a legibility one, and the two are not
   the same complaint.

   So the division is by JOB, which the sheet already made elsewhere: the
   section heads and the "SOURCES" label were always sans. Headline, dek
   and TL;DR stay Garamond and get bigger. The apparatus moves to the sans
   stack, where 13.6px is a comfortable label.
   --------------------------------------------------------------------- */
.col-topic{grid-column:4;grid-row:1;text-align:right;white-space:nowrap;color:var(--faint);font-family:var(--sans);font-size:.875rem}
/* THE TIME CELL IS SIZED TO ITS WORST CONTENT, NOT ITS COMMONEST.
   It was 4.6rem (74px) with white-space:nowrap, and the cell does not hold
   only a clock: "New" and "Updated" ride inside it, deliberately, so that
   neither can move the left edge of the headline the way the old gold pill
   did. "Updated 54m ago" measures 130px in this face at this size. Measured
   on the live page at 1280px on 2026-08-25: 48 of the time cells overflowed
   and 12 of them printed straight into the picture column beside them.
   nowrap does not clip, it spills, so the defect was invisible to any test
   that asked whether the text was present.
   8.25rem holds the widest string the cell can ever carry. It costs the
   headline column 58px on desktop, which is the price of a column that is
   still a column. Below 1000px the cell moves to its own row and the token
   is not used. */
:root{--time-col:8.25rem}
.col-time{grid-column:5;grid-row:1;text-align:right;white-space:nowrap;color:var(--faint);font-family:var(--sans);font-size:.875rem;font-variant-numeric:tabular-nums}
/* The dek is a sentence, so it is bound by MEASURE and not only by size.
   At 42rem it ran 110 characters per line on a 1280px viewport, which is
   about half again the width the eye tracks back from without losing the
   line. 34rem holds it near 75. */
.story-tease{grid-column:3;grid-row:2;margin:.15rem 0 0;max-width:32rem;color:var(--muted);font-size:1.125rem;line-height:1.55}
.story-fold,.story-fold-static{grid-column:3;grid-row:2}
.story-row:has(.story-tease) .story-fold,.story-row:has(.story-tease) .story-fold-static{grid-row:3}
.story-row:has(.story-tease) a.discuss{grid-row:3;align-self:start}
.story-row:has(.story-fold[open]) .story-tease{display:none}
.story-fold summary{display:block;min-height:22px;list-style:none;cursor:pointer}
.story-fold summary::-webkit-details-marker{display:none}
.story-fold summary small,.story-fold-static{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem;color:var(--faint);font-family:var(--sans);font-size:.875rem}
.story-fold summary:hover small{color:var(--accent)}
.story.is-corr .story-title{font-weight:700}
/* Freshness is a property of the clock. The gold pill that used to carry it
   sat inside the headline and was 47px wide at 390px, so a fresh row began
   its headline 55px right of the rest and, at that width, printed straight
   into the first word: "NewSuore dell'Imitazione di Cristo". The timestamp
   already answers "when", so it carries this too, for nothing. */
.col-time.is-fresh{color:var(--accent);font-weight:700}
/* The second step. Under two hours takes the accent; under six keeps the ink
   without it, so the column reads as a gradient rather than as one flag and a
   uniform grey behind it. */
.col-time.is-recent{color:var(--ink)}
/* The word on the clock. "New" broke inside the window; "Updated" is an older
   record that gained reporting, which the timestamp cannot say because it
   prints last_seen_at. Both sit INSIDE the right-aligned time cell, so neither
   can move the headline the way the old pill did. */
.time-new,.time-grew{margin-right:.35rem;font-family:var(--sans);font-weight:700;font-size:.72rem;letter-spacing:.1em;text-transform:uppercase}
.time-new{color:var(--accent)}
.time-grew{color:var(--faint)}
/* Reports behind the outlets, printed only where the two counts differ. */
.reports{color:var(--faint);font-variant-numeric:tabular-nums}
.story-title{color:var(--ink);text-decoration:none;font-weight:600;font-size:1.18rem;line-height:1.32}
.story-title:hover{color:var(--accent)}
a.discuss{grid-column:4 / 6;grid-row:2;justify-self:end;align-self:center;font-family:var(--sans);font-size:.875rem;font-weight:400;color:var(--muted);text-decoration:none;border-bottom:1px solid var(--rule);white-space:nowrap}
a.discuss:hover{color:var(--accent);border-bottom-color:var(--gold)}
/* The caret is the only thing telling a reader the source list opens. --gold is
   a fixed #c0a054 in both themes and tops out at 2.5:1 on the light panel even
   at full opacity, so it can never reach the 3:1 a UI affordance needs; --accent
   is theme-aware and does. Kept aria-hidden: the <summary> already announces
   the disclosure to a screen reader, this is for readers who can see it but
   only just. */
.caret{color:var(--accent);display:inline-block;opacity:.8;transition:transform .15s ease,opacity .15s ease}
.story-fold summary:hover .caret,.story-fold[open] .caret{opacity:1}
.story-fold[open] .caret{transform:rotate(180deg)}
.story-body{margin:.2rem 0 .8rem;padding:.7rem .9rem;background:var(--wash);border-left:2px solid var(--gold);border-radius:0 10px 10px 0}
.story-dek{margin:0;max-width:32rem;font-size:1.125rem;line-height:1.6;color:var(--muted)}
.story-dek+.story-sources{margin-top:.55rem}
.story-sources{display:flex;flex-wrap:wrap;gap:.4rem;align-items:center;margin:0}
.story-sources span{font-family:var(--sans);font-weight:700;font-size:.72rem;letter-spacing:.12em;text-transform:uppercase;color:var(--accent);margin-right:.2rem}
.story-sources a{color:var(--ink);font-family:var(--sans);font-size:.875rem;text-decoration:none;padding:.2rem .65rem;border:1px solid var(--rule);border-radius:999px;background:var(--panel)}
.story-sources a:hover{border-color:var(--gold);color:var(--accent)}
ol.wire .vote{display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:.1rem;width:100%;min-width:0;min-height:38px;padding:.25rem .3rem;border:1px solid var(--rule);border-radius:8px;background:transparent;color:var(--faint);cursor:pointer;font:600 .82rem var(--sans);font-variant-numeric:tabular-nums;line-height:1.1}
ol.wire .vote:hover{border-color:var(--gold);color:var(--accent)}
ol.wire .vote[aria-pressed="true"]{border-color:var(--gold);color:var(--accent);background:var(--wash)}
ol.wire .rank{color:var(--faint);font-family:var(--sans);font-size:.8125rem;font-variant-numeric:tabular-nums}
/* A ranked river that renders every rank identically is not legibly ranked:
   the digits are there, all in the same grey, and the eye reads a list. The
   top three carry the page, so they take the ink and everything below recedes
   to where a number belongs. Two channels, weight and colour, and no vertical
   space at all. */
ol.wire>li:nth-child(-n+3) .rank{color:var(--ink);font-weight:700}
/* No room for columns on a phone: stack, and let topic and time share a line. */
b.corr{color:var(--accent);font-weight:700;font-variant-numeric:tabular-nums}
/* The publisher run on the closed row. Separated by a middot drawn in the
   rule colour rather than by a printed character, so the names read as a set
   and the punctuation does not compete with them. It is a set of names, not a
   sentence, so it may wrap but each name stays whole. */
/* A name too long to stay whole is truncated, not allowed to take the page
   sideways with it. One publisher in the registry is "Chierici Regolari Poveri
   della Madre di Dio delle Scuole Pie", which measures 375px in a 350px column
   on a 390px phone and was the only one of the 92 names on the front page over
   the edge: the wire scrolled horizontally by 5px because of it. The ellipsis
   says the name is cut; the whole of it is one press away inside the fold. */
.story-run{display:inline-flex;flex-wrap:wrap;align-items:baseline;gap:0;max-width:100%}
.story-run span{white-space:nowrap;min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis}
.story-run span+span::before{content:"·";margin:0 .38rem;color:var(--rule)}
.story-run .run-more{margin-left:.4rem;color:var(--faint);font-weight:600;font-variant-numeric:tabular-nums}
.empty-note{margin:1rem 0 0;color:var(--faint);font-style:italic}
.cta{margin:1.8rem 0;padding:1.15rem 1.25rem;border:1.5px solid var(--gold);background:var(--panel);border-radius:14px}
.cta h2{margin:0 0 .3rem;font-family:"EB Garamond",Georgia,serif;font-size:1.15rem;font-weight:600;letter-spacing:0}
.cta p{margin:0 0 .8rem;color:var(--muted);font-size:1.05rem;line-height:1.55}
.cta-actions{display:flex;flex-wrap:wrap;align-items:center;gap:.9rem 1.1rem;margin:0}
.cta a.join{display:inline-flex;align-items:center;min-height:44px;padding:.35rem 1.25rem;border-radius:999px;background:var(--lapis);color:var(--bg);font-family:var(--sans);font-weight:600;font-size:.86rem;letter-spacing:.01em;text-decoration:none;border:1.5px solid var(--lapis)}
.cta a.join:hover{background:color-mix(in srgb,var(--lapis) 86%,var(--gold));color:var(--bg);border-color:var(--gold)}
/* Same reason as .mast-search: gold alone is 2.37:1 on the page behind it. The
   shared ring is offset clear of the lapis fill, so it reads against --bg. */
.cta a.signin{color:var(--accent);font-size:.94rem;text-decoration:none;border-bottom:1px solid var(--rule)}
.cta a.signin:hover{border-bottom-color:var(--gold)}
a:focus-visible,button:focus-visible,summary:focus-visible,input:focus-visible{outline:2px solid var(--lapis);outline-offset:2px;border-radius:2px;box-shadow:0 0 0 4px color-mix(in srgb,var(--gold) 55%,transparent)}
/* --lapis inverts with the scheme (ink by day, parchment by night), so the
   ring keeps 3:1 both ways; gold alone was 2.37:1 on ivory. */
/* The footer shares main's measure. It is a body child, so without its own
   max-width + side padding it ran full-bleed: x=0 on desktop, and on a phone
   the disclosure line touched both screen edges. */
footer{max-width:64rem;margin:2rem auto 0;padding:1rem 1.25rem 1.5rem;border-top:1px solid var(--rule);color:var(--muted);font-family:var(--sans);font-size:.8125rem;line-height:1.6}
footer a{color:var(--muted)}
/* Three lines, in falling order of importance: who this is, where else to go,
   and the standing disclaimer. It was one run-on middot chain that put the
   masthead and an RSS link at the same weight. */
footer p{margin:.35rem 0}
.foot-brand{color:var(--ink)}
.foot-nav{line-height:2.1}
.foot-disclosure{margin-top:.8rem;color:var(--faint)}

/* Public source atlas ---------------------------------------------------
   This is the collection system as a product, not a back-office table. The
   cards keep the wire's compact typographic register while giving provenance,
   coverage and health enough room to be read rather than decoded. */
.source-nav{display:flex;align-items:center;gap:.9rem;margin-left:auto;white-space:nowrap}
.source-nav a{color:var(--muted);font:600 .74rem var(--sans);letter-spacing:.06em;text-transform:uppercase;text-decoration:none}
.source-nav a:hover{color:var(--accent)}
.source-atlas{max-width:72rem}
.source-atlas .dateline a{color:inherit}
.source-atlas h1{font-size:2.25rem;margin-top:.35rem}
.atlas-lede{max-width:55rem;margin:.45rem 0 1.5rem;color:var(--muted);font-size:1.08rem;line-height:1.58}
.atlas-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:.7rem;margin:0 0 2rem}
.atlas-stats article{padding:1rem 1.05rem;border:1px solid var(--rule);border-top:3px solid var(--gold);border-radius:12px;background:var(--panel)}
.atlas-stats strong{display:block;color:var(--lapis);font-size:1.8rem;line-height:1;font-variant-numeric:tabular-nums}
.atlas-stats span{display:block;margin-top:.38rem;color:var(--faint);font:600 .72rem var(--sans);letter-spacing:.07em;text-transform:uppercase}
.eyebrow{margin:0 0 .15rem;color:var(--accent);font:700 .7rem var(--sans);letter-spacing:.13em;text-transform:uppercase}
.atlas-method,.atlas-health{display:grid;grid-template-columns:minmax(12rem,.7fr) minmax(0,1.3fr);gap:2rem;margin:2rem 0;padding:1.35rem 1.45rem;border:1px solid var(--gold);border-radius:14px;background:var(--wash)}
.atlas-method h2,.atlas-health h2,.section-top h2{margin:0;font-size:1.35rem;line-height:1.25;font-weight:600}
.atlas-method ol{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem 1.4rem;counter-reset:method}
.atlas-method li{position:relative;padding-left:2rem;counter-increment:method}
.atlas-method li::before{content:counter(method,decimal-leading-zero);position:absolute;left:0;top:.1rem;color:var(--accent);font:.7rem ui-monospace,Menlo,monospace;letter-spacing:.08em}
.atlas-method b{display:block;font-family:var(--sans);font-size:.76rem;letter-spacing:.08em;text-transform:uppercase;color:var(--lapis)}
.atlas-method span{display:block;margin-top:.18rem;color:var(--muted);font-size:.94rem;line-height:1.45}
.atlas-coverage,.atlas-roster{margin:2.2rem 0}
.section-top{display:flex;align-items:end;justify-content:space-between;gap:1rem;margin:0 0 .8rem;padding-bottom:.55rem;border-bottom:2px solid var(--gold)}
.section-top>p{max-width:34rem;margin:0;color:var(--faint);font-size:.83rem;line-height:1.45;text-align:right}
.region-grid{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:.55rem}
.region-grid article{padding:.8rem .85rem;border:1px solid var(--rule);border-radius:10px;background:var(--panel)}
.region-grid strong{display:block;color:var(--lapis);font-size:.92rem;line-height:1.25}
.region-grid span{display:block;margin-top:.2rem;color:var(--faint);font-size:.82rem}
.atlas-tools{display:flex;align-items:center;gap:.75rem 1rem;margin:0 0 .9rem}
.atlas-tools label{flex:1 1 20rem}
.atlas-tools input{width:100%;min-height:42px;padding:.45rem .9rem;border:1px solid var(--rule);border-radius:10px;background:var(--panel);color:var(--ink);font:inherit;font-size:.95rem}
.atlas-tools input:focus{outline:2px solid var(--lapis);outline-offset:2px}
.atlas-chips{display:flex;align-items:center;gap:.35rem;overflow-x:auto;scrollbar-width:none}
.atlas-chips::-webkit-scrollbar{display:none}
.atlas-chips button{flex:none;min-height:38px;padding:.25rem .65rem;border:1px solid var(--rule);border-radius:999px;background:var(--panel);color:var(--muted);cursor:pointer;font:inherit;font-size:.82rem;white-space:nowrap}
.atlas-chips button:hover,.atlas-chips button[aria-pressed="true"]{border-color:var(--gold);background:var(--wash);color:var(--accent)}
.atlas-chips b{margin-left:.2rem;color:var(--faint);font-size:.76rem}
.source-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.65rem}
.source-card{padding:1rem 1.05rem;border:1px solid var(--rule);border-radius:12px;background:var(--panel)}
.source-card[hidden]{display:none}
.source-card-head{display:flex;align-items:start;justify-content:space-between;gap:.8rem}
.source-card h3{margin:0;font-size:1.05rem;line-height:1.25}
.source-card h3 a{color:var(--ink);text-decoration:none}
.source-card h3 a:hover{color:var(--accent);text-decoration:underline;text-decoration-color:var(--gold);text-underline-offset:3px}
.source-place{margin:.18rem 0 0;color:var(--faint);font-size:.78rem}
.source-state{display:inline-flex;align-items:center;gap:.35rem;flex:none;color:var(--faint);font:600 .68rem var(--sans);letter-spacing:.05em;text-transform:uppercase;white-space:nowrap}
.source-state i{width:.48rem;height:.48rem;border-radius:50%;background:var(--faint)}
.source-state.is-healthy i{background:#438654}
.source-state.is-degraded i{background:#b18128}
.source-state.is-blocked i{background:#ad3d37}
.source-state.is-queued i{background:transparent;border:1px solid var(--faint)}
.source-desc{margin:.65rem 0;color:var(--muted);font-size:.93rem;line-height:1.45}
.source-meta{display:flex;flex-wrap:wrap;gap:.28rem .4rem;margin:.65rem 0 0}
.source-meta span{padding:.12rem .42rem;border-radius:999px;background:var(--wash);color:var(--faint);font-size:.72rem;line-height:1.45}
/* The medium chip leads the row and is the only one that is not grey: whether
   a link opens prose or plays is the first thing a reader wants off a card,
   and it is the one fact on it that a filter chip above is also offering. */
.source-meta .is-medium{background:transparent;border:1px solid var(--rule);color:var(--muted);font-variant-caps:all-small-caps;letter-spacing:.06em}
.atlas-health{align-items:start}
.atlas-health-copy p{margin:0;color:var(--muted);font-size:.96rem;line-height:1.55}
.atlas-health-copy p+p{margin-top:.7rem}
.atlas-health a{color:var(--accent);text-decoration:none;border-bottom:1px solid var(--rule)}
.atlas-health a:hover{border-bottom-color:var(--gold)}

/* The Church throughout the world ------------------------------------
   Five cells, always five, in the Annuario's order, and each one carries up
   to three headlines so a continent reads as having had a day rather than a
   token. Written in the receded chrome: sans labels, hairline rules, no fill,
   no shadow. The band is a rail above the wire, never a second wire.

   THIS BLOCK WAS SILENTLY LOST ONCE. A parallel session's copy of this sheet
   won a rebase and the markup kept rendering with no rules at all: an ordered
   list with visible numbers and default blue links, live on the front page.
   tests/newsTeaserStyles.test.ts now fails if any class the teaser emits has
   no rule here. */
.world{margin-top:1.5rem}
.world-lede{margin:.6rem 0 .9rem;max-width:48rem;color:var(--muted);font-size:.92rem;line-height:1.5}
.world-grid{list-style:none;display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:0;margin:0;padding:0;border-top:1px solid var(--rule)}
.world-cell{display:flex;flex-direction:column;gap:.35rem;padding:.8rem .85rem;border-left:1px solid var(--rule);min-width:0}
.world-cell:first-child{border-left:0}
.world-name{color:var(--accent);font-family:var(--sans);font-weight:600;font-size:.72rem;letter-spacing:.09em;text-transform:uppercase;text-decoration:none}
.world-name:hover{color:var(--ink);text-decoration:underline;text-decoration-color:var(--gold);text-underline-offset:3px}
.world-publishers{color:var(--faint);font-family:var(--sans);font-size:.75rem;line-height:1.4;overflow-wrap:anywhere}
.world-stories{list-style:none;margin:.1rem 0 0;padding:0;display:flex;flex-direction:column;gap:.4rem}
.world-stories li{padding-top:.4rem;border-top:1px solid var(--rule)}
.world-stories li:first-child{padding-top:0;border-top:0}
.world-stories a{color:var(--ink);font-size:1rem;line-height:1.42;text-decoration:none;display:block}
.world-stories a:hover{color:var(--accent)}
.world-cell.is-quiet .world-publishers{font-style:italic}
.world-cell.is-quiet .world-name{color:var(--faint)}

/* ---------------------------------------------------------------------
   RESPONSIVE RULES LAST, AND THEY MUST STAY LAST.
   A media query adds NO specificity. While this sheet was inline in
   news-teaser.ts the @media blocks sat ABOVE the base declarations, so
   `.rail{flex-wrap:nowrap}` inside a breakpoint lost to `.rail{...wrap}`
   further down, and `.chip-extra{display:none}` lost to `.chip{...}`.
   Both needed defensive selectors (nav.rail, .rail .chip-extra) that are
   no longer necessary now the order is right. Do not move this block up.
   --------------------------------------------------------------------- */
@media (prefers-color-scheme:dark){:root{--bg:#0f1524;--panel:#161d31;--wash:#141b2e;--ink:#e9e6da;--muted:#b6b7c6;--faint:#9a9db1;--rule:#2a3149;--lapis:#e9e6da;--accent:#d3b36a;--gold:#c0a054;--sans:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,"Helvetica Neue",Arial,sans-serif}}
@media (max-width:1000px){.world-grid{grid-template-columns:repeat(2,minmax(0,1fr));border-top:0}
  .world-cell{border-left:0;border-top:1px solid var(--rule)}}
@media (max-width:520px){.world-grid{grid-template-columns:minmax(0,1fr)}}
/* Tablet is a two-row masthead and a three-track wire. The old 768px layout
   squeezed search to 90px and each headline between six apparatus columns.
   Wrapping follows DOM order; no `order` declaration is used anywhere. */
/* The verse leaves first. Between 900 and 1000px brand+verse, four actions and
   the search field could not share one row: the mark clipped off the left edge
   and the field ran off the right. */
@media (max-width:900px){
  nav.rail{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch;gap:.35rem;padding-bottom:.55rem;margin-bottom:.7rem;mask-image:linear-gradient(90deg,#000 0%,#000 calc(100% - 1.6rem),transparent);-webkit-mask-image:linear-gradient(90deg,#000 0%,#000 calc(100% - 1.6rem),transparent)}
  nav.rail.is-open{mask-image:none;-webkit-mask-image:none}
  nav.rail::-webkit-scrollbar{display:none}
  nav.rail .rail-label{display:inline-flex;flex:none;position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:nowrap;margin-right:.25rem}
  nav.rail .chip,nav.rail .chip-wide-only,nav.rail .chip-extra{display:inline-flex;flex:none;min-height:44px}
  nav.rail .chip-more{display:none}
  .story-row,.story-row.has-thumb{grid-template-columns:3.2rem minmax(0,1fr) auto;column-gap:.65rem;row-gap:.12rem}
  .rank,.story-thumb{display:none}
  ol.wire .vote{grid-column:1;grid-row:1 / span 3;align-self:start}
  .story-head{grid-column:2 / -1;grid-row:1}
  .col-topic{grid-column:2;grid-row:2;text-align:left}
  .col-time{grid-column:3;grid-row:2;text-align:right}
  .story-tease{grid-column:2 / -1;grid-row:3;max-width:none}
  .story-fold,.story-fold-static{grid-column:2;grid-row:3}
  .story-row:has(.story-tease) .story-fold,.story-row:has(.story-tease) .story-fold-static{grid-row:4}
  a.discuss,.story-row.has-thumb a.discuss{grid-column:3;grid-row:3;justify-self:end;display:inline-flex;align-items:center;min-height:24px}
  .story-row:has(.story-tease) a.discuss{grid-row:4}
  .day-head h2>a{display:inline-flex;align-items:center;min-height:44px}
}
@media (max-width:920px){
  .source-nav{display:none}
  .atlas-stats{grid-template-columns:repeat(2,minmax(0,1fr))}
  .region-grid{grid-template-columns:repeat(3,minmax(0,1fr))}
  .atlas-tools{align-items:stretch;flex-direction:column}
  .atlas-tools label{flex:auto;width:100%}
  .atlas-chips{width:100%}
}
@media (max-width:620px){
  main{padding:.75rem .8rem 2.5rem}
  /* The dateline ran three lines of spaced uppercase monospace (76px) before a
     single headline; the office and the season stay, the "updated 1m" segment
     stands down, and the tracking comes in. Two lines at most. */
  .dateline{margin-top:.5rem;font-size:max(.7rem,11px);line-height:1.4;letter-spacing:.03em}
  .dateline .seg-updated{display:none}
  /* touch.css makes the office link a 44px inline-flex box, which alone put
     the strip on a third line. The hit box stays 44px; the line does not. */
  .dateline a.lit-hours{margin-block:-.7rem}
  .dateline .lit-day{white-space:normal}
  /* One swipeable ribbon rather than three wrapped lines. The links stay in
     the DOM and keyboard focus scrolls them into view; the same treatment the
     dateline itself takes at 360px. */
  .editions{white-space:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;mask-image:linear-gradient(90deg,#000 0%,#000 calc(100% - 1.25rem),transparent);-webkit-mask-image:linear-gradient(90deg,#000 0%,#000 calc(100% - 1.25rem),transparent)}
  .editions::-webkit-scrollbar{display:none}
  .editions{margin-top:.2rem}
  h1{margin:.3rem 0 .1rem;font-size:1.3rem;line-height:1.22}
  /* The two filter rails read as one bar: smaller label, 40px chips, one rule
     between them and one under. They were 54px each with 44px pills and a
     label column, and together cost 130px of the fold. */
  nav.rail{margin:.45rem 0 .35rem;padding-bottom:.4rem;gap:.3rem}
  nav.rail.rail-places{margin-top:-.1rem}
  nav.rail .rail-label{font-size:max(.64rem,11px);margin-right:.15rem}
  nav.rail .chip,nav.rail .chip-wide-only,nav.rail .chip-extra{min-height:40px;padding:.1rem .6rem;font-size:.8125rem;white-space:nowrap}
  nav.rail .chip b{font-size:.75rem}
  .day.is-holy-see{margin-top:.55rem}
  .tldr{padding:.7rem .1rem}
  .tldr ol{grid-template-columns:1fr;gap:.1rem}
  .tldr li:nth-child(n+3){display:none}
  .day-count{display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}
  .source-atlas h1{font-size:1.75rem}
  .atlas-lede{font-size:1rem}
  .atlas-stats{gap:.45rem}
  .atlas-stats article{padding:.8rem}
  .atlas-stats strong{font-size:1.5rem}
  .atlas-method,.atlas-health{grid-template-columns:1fr;gap:1rem;padding:1rem}
  .atlas-method ol{grid-template-columns:1fr}
  .region-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .source-grid{grid-template-columns:1fr}
  .section-top{align-items:start;flex-direction:column}
  .section-top>p{text-align:left}
  .source-card-head{display:block}
  .source-state{margin-top:.45rem}
}
/* A 320px phone. The wordmark breaks to two lines above rather than
   collapsing to "CI" here: measured at 340px (Safari page zoom on a 390px
   phone) the collapse fired and the masthead read as a monogram, a stray
   letter and a filled pill. The dateline wraps rather than scrolls, because a
   ribbon that stops at "ORDINARY TIM" is a cut, not a design. Publisher names
   are already present on every Holy See row, so repeating them in that
   section header is the expendable line. */
@media (max-width:360px){
  .day.is-holy-see .day-count{display:none}
}
@media (pointer: coarse){
.story-fold summary{min-height:44px}

ol.wire .vote{min-width:44px}
ol.wire .vote .n{font-size:max(.74rem,12px)}
.chip{min-height:44px}
a.discuss{display:inline-flex;align-items:center;min-height:44px;padding-inline:.35rem;margin-inline:-.35rem;border-bottom:0;text-decoration:underline;text-decoration-color:var(--rule);text-underline-offset:3px}
.story-sources a{min-height:44px;display:inline-flex;align-items:center}
.cta a.signin{display:inline-flex;align-items:center;min-height:44px;border-bottom:0;text-decoration:underline;text-decoration-color:var(--rule);text-underline-offset:3px}
footer a{display:inline-flex;align-items:center;min-height:44px}

}

/* ---------------------------------------------------------------------
   "discuss" was 13% tappable, and the other 87% did something else.

   At <=700px both `details.story-fold` and `a.discuss` are placed in the
   same grid cell (column 3, same row). The details is a block and fills
   that cell, so its summary painted straight over the anchor: a thumb
   aimed at the middle of "discuss" hit the summary and expanded the story
   instead of opening it. Measured on a 390px viewport, only a 5px band at
   the right edge (x 354-358 of a 47px control) actually reached the link,
   and puppeteer's touchscreen.tap at the control's own centre never
   navigated.

   Capping the fold's width clears the cell that `justify-self:end` puts
   the anchor in. Hit rate goes 13% -> 100% and the tap navigates, with no
   change to row height or document height.

   The negative inline margin came from the 44px touch pass; on the end
   side it pushed every row 5.6px past its own column, which put the one
   live sliver of "discuss" inside the iOS edge-swipe region.
   --------------------------------------------------------------------- */
@media (max-width:700px){
  .story-fold,.story-fold-static{max-width:calc(100% - 5.25rem)}
}
@media (pointer: coarse){
  a.discuss{margin-inline:-.35rem 0}
}

/* ---------------------------------------------------------------------
   Target size on touch (WCAG 2.5.8, 24x24 minimum).

   These are all standalone controls, so the "inline link inside a sentence"
   exception does not cover them. Measured on a 390x844 iPhone before:
   a.story-title 22px, .day-head h2 a 19px, .section-more a 20px,
   nav.day-nav a 23px, and footer RSS/API 22px and 21px WIDE (their height
   was already 44; only the height axis had ever been padded).

   inline-block rather than padding on an inline box, because an inline box
   with vertical padding overlaps its neighbours and hands them its taps.
   That is the same mechanism that made "discuss" unpressable, so it is not
   worth repeating to save six pixels.

   It also fixes a quieter miss: the headline was `display:inline`, so a
   two-line title's bounding box included the empty gutter after the short
   second line, and elementFromPoint at the box's visual centre returned
   div.story-head, not the link. Measured after: title hit rate 60% -> 100%,
   centre of the box now hits the anchor, and the document is 19px shorter,
   not longer.
   --------------------------------------------------------------------- */
@media (pointer: coarse){
  a.story-title{display:inline-block;padding-block:.2rem}
  .day-head h2 a{display:inline-block;padding-block:.25rem}
  .section-more a{display:inline-block;padding-block:.3rem}
  nav.day-nav a{display:inline-flex;align-items:center;min-height:44px}
  footer a,nav.crumbs a{padding-inline:.3rem}
}

/* ---------------------------------------------------------------------
   Motion: the same quiet grammar as the front door. Colors and borders
   ease; nothing moves. Sits after the responsive rules because it adds
   only transition longhands no earlier rule declares.
   --------------------------------------------------------------------- */
.chip,ol.wire .vote,.story-title,a.discuss,.story-sources a,.atlas-chips button,.source-card h3 a,.cta a.join{transition:color .15s ease,border-color .15s ease,background .15s ease}
@media (prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}

/* ---------------------------------------------------------------------
   Phone rows: the headline takes the whole width.

   Measured 2026-08-28 at 340px and 390px: the vote was a 51x44 empty circle
   with a small triangle in it, sitting in a column of its own to the left of
   every headline, so each title began 60px in; "discuss" fell to a line of
   its own above the sources fold on rows with a picture (a has-thumb rule
   from the tablet block outranked this one); and the fold reserved 5.25rem
   for a link that was no longer beside it, so "2 sources · Vatican News"
   wrapped at the middot.

   One grid, three columns, restated for every variant that outranks a bare
   .story-row (has-thumb, :has(.story-tease)) so the cascade cannot pull a
   row back into the tablet template:
     row 1  headline, full width
     row 2  topic | time | vote
     row 3  tease, full width (when present)
     row 4  sources fold | discuss
   The vote is a small pill on the meta line, where a reader who has read the
   headline decides, and it keeps a 40px hit box through a negative block
   margin that does not reach the headline's own padded box. Sits last, after
   the tablet grid, at equal or higher specificity.
   --------------------------------------------------------------------- */
@media (max-width:620px){
  .story-row,.story-row.has-thumb{grid-template-columns:minmax(0,1fr) auto auto;column-gap:.6rem;row-gap:.15rem;padding:.55rem 0 .6rem;align-items:center}
  .rank,.story-thumb{display:none}
  .story-head,.story-row.has-thumb .story-head{grid-column:1 / -1;grid-row:1}
  .col-topic{grid-column:1;grid-row:2;text-align:left;justify-self:start;padding-right:0;min-width:0;overflow:hidden;text-overflow:ellipsis}
  .col-time{grid-column:2;grid-row:2;justify-self:end;text-align:right}
  ol.wire .story-row .vote{grid-column:3;grid-row:2;flex-direction:row;gap:.3rem;width:auto;min-width:2.5rem;min-height:36px;padding:0 .5rem;margin-block:-.4rem;align-self:center;justify-self:end;border-radius:999px;font-size:.8rem}
  ol.wire .story-row .vote .n:empty{display:none}
  .story-tease{grid-column:1 / -1;grid-row:3;max-width:none}
  .story-fold,.story-fold-static,.story-row:has(.story-tease) .story-fold,.story-row:has(.story-tease) .story-fold-static{grid-column:1 / 3;grid-row:4;max-width:none;min-width:0}
  a.discuss,.story-row.has-thumb a.discuss,.story-row:has(.story-tease) a.discuss{grid-column:3;grid-row:4;justify-self:end;align-self:center;margin-inline:0}
  .story-fold summary small,.story-fold-static{row-gap:.1rem}
  /* Three or more publishers beside "discuss" stacked one name per line with
     an orphaned middot leading each. Those rows give the fold the whole width
     and let discuss take the next line; a one-publisher row keeps its line. */
  .story-row:has(.story-run span:nth-of-type(3)) .story-fold,.story-row:has(.story-run span:nth-of-type(3)) .story-fold-static{grid-column:1 / -1}
  .story-row:has(.story-run span:nth-of-type(3)) a.discuss{grid-row:5;margin-top:-.5rem}
  /* The caret is the last flex item after the run; a run that fills its line
     dropped it to a line of its own. Leave it room on the run's last line. */
  .story-fold summary small .story-run{max-width:calc(100% - 1.4rem)}
  .day.is-holy-see{padding:.15rem .65rem .5rem}
}

/* === DENSITY (2026-08-08) ===================================================
   Measured on the live page at 1440x900: FOUR ranked stories above the fold,
   against eleven on the aggregator this wire is most often compared to. The
   cause was not the preamble, which is smaller here, but the row: 126px each,
   of which the closed-row dek was 56px because it wrapped to two lines and
   rides on nearly every corroborated story.

   What is NOT given up to buy the space back. The dek stays, on the same rows
   it was already on. The named publishers stay on the fold line. The topic and
   time columns stay. That is the whole argument for this wire over a denser
   one: a reader gets the sentence and the provenance without opening anything,
   and a 37px row that carries a headline and a ratio is not the same product.
   So the dek is held to ONE line rather than removed, and the rest is rhythm.

   These rules are appended, so they land after the media blocks they tighten
   and win at equal specificity without !important or a rewrite of the grid. */
.story-tease{font-size:1rem;line-height:1.45;margin:.05rem 0 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.story-row{padding:.34rem 0;row-gap:.02rem}
.story-title{font-size:1.09rem;line-height:1.4}
.story-fold summary{padding-block:.05rem}
/* The dek is a single line now, so its column no longer needs to reserve the
   width that a two-line wrap wanted. */
.story-tease{max-width:44rem}
@media (max-width:700px){
  /* The phone stacks the row, where a nowrap dek would be ellipsed after four
     words and tell the reader nothing. Two lines, clamped, is the honest
     version of the same trade on a narrow column. The type sizes belong here,
     after the density declarations: keeping them in the earlier phone block
     let this later section silently shrink them back to the desktop scale. */
  .story-title{font-size:1.2rem;line-height:1.32}
  .story-tease{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;font-size:1.03rem;line-height:1.5}
  .story-row{padding:.45rem 0 .5rem}
}
@media (pointer:coarse){
  /* The section and day headings ("From the Holy See", "Saturday, August 8")
     are anchors inside an h2, 31px tall, and they are how a reader gets from
     the front page into a section or a day: both are `.day-head h2>a`, the Holy See
     section being a `.day` with `is-holy-see`. assets/touch.css raises targets
     by enumerated selector and had never heard of it; the selector lives here
     rather than there because a bare `h2>a` in the shared sheet would reach
     into every template on the site. */
  .day-head h2>a{display:inline-flex;align-items:center;min-height:44px}
}

/* The wire's footer links out to /map/, which answers a stranger with the door.
   Every other link in that row opens. Marked 2026-08-08, in the reader's own
   language, because a footer that mixes the two silently is a footer that
   spends somebody's click. */
.foot-members{padding:.05em .3em;border:1px solid var(--rule);border-radius:2px;font-family:var(--sans);font-size:max(.5rem,11px);font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--faint);vertical-align:.1em}
.foot-gated{white-space:nowrap}

/* === THE SOURCE ATLAS (2026-08-08) =========================================
   /news/sources/ is public, 252KB, and had never been audited: the harness
   knew about /news/ and /news/archive/ and nothing else on this wire. Three
   findings, all of them the shape the rest of this work kept finding, which is
   a standard applied by hand to the pages somebody remembered.

   `.source-state` is the health mark on every one of 284 sources ("Collecting",
   "Needs attention"). 0.68rem is 10.88px, under the floor this sheet's own
   header declares in its second sentence.

   The filter chips stand 38px and the source names 22px on a phone. The names
   are the entire point of the page: it is a directory, and the link is the
   row. The exemption in assets/touch.css section 7 is for `nav.rail` on the
   wire front page, where two 44px pill rows ate the fold before a headline
   arrived; this rail is one row on a page that is nothing but rows. */
.source-state{font-size:max(.68rem,11px)}
@media (pointer:coarse){
  .atlas-chips button{min-height:44px}
  .source-card h3 a{display:inline-flex;align-items:center;min-height:44px}
}
