/* ═══════════════════════════════════════════════════════════════════════════
   seite.css  —  das Seitenformat

   Hiess bis zur Auslagerung css/news_v3.css und gehoerte zu index_v3.html.

   Umsetzung des Design-Exports
   docs/Infinma news Redesign-Mockup/Infinma News Redesign v2.dc.html
   samt zugehörigem README. Werte (Farben, Größen, Abstände) sind von dort
   übernommen, die Fundstelle steht jeweils als Kommentar am Block.

   EIGENSTÄNDIG. Diese Datei trägt das gesamte Seitenformat. Dazu kommen nur
   css/base.css (Reset) und css/modal.css (Dialoge).

   Sie entstand neben einem älteren Navy-Format aus css/news.css,
   css/riat-format.css und css/start.css, das der Export mit seiner eigenen
   Farbwelt (warmer Sandton, Serifenschrift, kantige Flächen, keine Schatten)
   nicht gebrauchen konnte. Die drei Dateien liegen seit der Auslagerung in
   Projekt_Tool_infinma_news_Sicherung_V1_V2.

   Weil das frühere css/riat-format.css hier nie geladen wurde, definiert
   dieser Block auch die sechs Tokens, die css/modal.css erwartet (--bg-card, --bg-page, --border,
   --navy-700, --navy-900, --text-body). Sie zeigen auf die Palette dieser
   Datei, damit
   die vier Modals im Ton der Seite stehen.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ───────────────────────────────────────────────────────────────────────────
   1) Schriften
   Der Export nennt Newsreader (Serif) und Source Sans 3 (Sans) von Google
   Fonts. Hier selbst gehostet aus fonts/, wie Manrope in css/base.css: die
   Seite soll ohne CDN laufen. Fällt eine Datei aus, greifen Georgia bzw. die
   Systemschrift, das Layout bleibt tragfähig.
   ─────────────────────────────────────────────────────────────────────────── */
@font-face { font-family:'Newsreader'; font-style:normal; font-weight:400; font-display:swap; src:url('../fonts/newsreader-400.ttf') format('truetype'); }
@font-face { font-family:'Newsreader'; font-style:normal; font-weight:500; font-display:swap; src:url('../fonts/newsreader-500.ttf') format('truetype'); }
@font-face { font-family:'Newsreader'; font-style:normal; font-weight:600; font-display:swap; src:url('../fonts/newsreader-600.ttf') format('truetype'); }
@font-face { font-family:'Newsreader'; font-style:normal; font-weight:700; font-display:swap; src:url('../fonts/newsreader-700.ttf') format('truetype'); }
@font-face { font-family:'Newsreader'; font-style:italic; font-weight:400; font-display:swap; src:url('../fonts/newsreader-400-italic.ttf') format('truetype'); }
@font-face { font-family:'Source Sans 3'; font-style:normal; font-weight:400; font-display:swap; src:url('../fonts/sourcesans3-400.ttf') format('truetype'); }
@font-face { font-family:'Source Sans 3'; font-style:normal; font-weight:500; font-display:swap; src:url('../fonts/sourcesans3-500.ttf') format('truetype'); }
@font-face { font-family:'Source Sans 3'; font-style:normal; font-weight:600; font-display:swap; src:url('../fonts/sourcesans3-600.ttf') format('truetype'); }
@font-face { font-family:'Source Sans 3'; font-style:normal; font-weight:700; font-display:swap; src:url('../fonts/sourcesans3-700.ttf') format('truetype'); }


/* ───────────────────────────────────────────────────────────────────────────
   2) Tokens
   Quelle: README.md, Abschnitt "Design Tokens".
   ─────────────────────────────────────────────────────────────────────────── */
:root {
  --ns-page:      #eceae4;   /* Seitenhintergrund, warmer Sand */
  --ns-surface:   #ffffff;   /* Header, Artikelflächen, Pills */
  --ns-paper:     #f7f5ef;   /* Kennzahl-Karte */
  --ns-ink:       #11212e;   /* Überschriften, dunkles Band */
  --ns-body:      #26394a;   /* Fließtext Artikel */
  --ns-body-soft: #3d5265;   /* Meldungstext Ebene 1 */
  --ns-body-mid:  #4b5d6c;   /* Meldungstext Ebene 2 */
  --ns-meta:      #5a6d7c;   /* Meta, Zähler */
  --ns-navy:      #12395c;   /* Marke, Ausgabe-Karte, Buttons, Links */
  --ns-navy-dark: #0d2d4a;   /* Hover, CTA-Button */
  --ns-tint-1:    #8fc0e4;   /* Text auf Navy, hell */
  --ns-tint-2:    #c4d9e8;
  --ns-tint-3:    #9fc9ea;
  --ns-rubric:    #6b5c42;   /* Rubrikenlabel, warmes Braun */
  --ns-line:      #dcd8ce;
  --ns-line-2:    #cfcabe;
  --ns-line-3:    #d3cec2;
  --ns-line-4:    #e6e2d9;
  --ns-line-5:    #ddd8ca;
  --ns-accent:    #e8c96a;   /* Sandgold */

  /* Abgedunkeltes und leicht entsaettigtes Sandgold. Traegt die Zitate der
     Randspalte UND alle Kategorie-Marker. Dieselbe Farbfamilie wie
     --ns-accent, nur lesbar gemacht: Sandgold liegt bei HSL 45/66/73,
     dieser Ton bei 45/60/30.

     Warum die Marker nicht das helle --ns-accent tragen, obwohl sie
     dekorativ sind: gemessen kommt #e8c96a als kleines Quadrat auf dem
     Sandgrund der Seite auf 1,34:1 und auf Weiss auf 1,62:1. Ein 6px
     grosser Punkt ist damit praktisch unsichtbar, und genau so wirkte er
     auch. Mit diesem Ton sind es 4,81:1 und 5,78:1.

     Warum nicht dunkler oder heller: gemessen gegen die weisse
     Artikelflaeche und gegen den Sandgrund ergeben sich 5,78:1 und 4,81:1.
     Eine Stufe heller (H45 S75% L34%, #987716) faellt auf 4,21:1 und 3,50:1
     und reisst damit AA fuer 21px. Eine Stufe dunkler waere sicherer, sieht
     aber nicht mehr nach Gold aus, sondern nach Oliv.

     Der Unterschied zum Fliesstext ist bewusst ein FARBTON-Unterschied und
     kein Helligkeitsunterschied: --ns-body #26394a ist kuehles Blaugrau bei
     Hue 209, dieser Ton warmes Gold bei Hue 45. Genau das fehlte vorher,
     das Zitat stand auf #2c4051 und damit praktisch im Ton des Fliesstexts. */
  --ns-gold:      #7a631f;

  /* Spaltenmasse der Themenbeitraege. Der Bereich laeuft ueber die volle
     Containerbreite, die Spalten sind aber gesetzt und nicht elastisch:
     der Fliesstext waechst also nicht von selbst mit.

     Messreihe bei 18px Source Sans 3, gemessen ueber echte Zeilenboxen:
       596px -> 66,5 Zeichen je Zeile (Median)
       620px -> 72,0
       640px -> 73,0
       713px -> 80,6   aktueller Stand
       770px -> 85,0

     ACHTUNG, die Breite ist eine Entscheidung des Auftraggebers und nicht
     aus dem Komfortbereich von 45 bis 75 Zeichen abgeleitet. Sie hat zwei
     Staende hinter sich: erst "vier Zentimeter breiter" von 620 auf 770,
     dann "eineinhalb Zentimeter schmaler" von 770 auf 713 (1,5cm sind bei
     37,8px/cm rund 57px). 80,6 Zeichen liegen weiter ueber 75, aber
     unter dem Wert von index.html, das bei 679px auf 79,1 kommt. Wer die
     Zeilenlaenge wirklich unter 75 bringen will, setzt rund 660px. Der
     Zeilenabstand ist mitgewachsen, siehe .ns-article__body p.

     Die Randspur ist 1fr und nimmt den Rest der Zeile ein, deshalb bleibt
     die Textspalte bei jeder Fensterbreite gleich breit und die Randspalte
     schrumpft zuerst. Der Rest bleibt weisser Raum rechts. Dasselbe Muster
     hatte das fruehere Seitenformat in .news-article-outer, dort
     minmax(0,700px) 200px in einem 1080px breiten Kasten mit 144px Rest.

     Einen Deckel --ns-art-rand am Randinhalt gab es bis zur Verbreiterung.
     Er ist entfallen: bei 770px Text bleiben der Randspur am maximalen
     Container gemessen 382px, der frueher gesetzte Deckel von 440px konnte
     also nie mehr greifen. */
  --ns-art-text:  713px;   /* Fliesstextspalte */
  --ns-art-luft:   36px;   /* Text zur Linie und Linie zum Randinhalt */
  --ns-art-pad:    56px;   /* Innenabstand der Artikelflaeche und des Bandes */

  --ns-serif: 'Newsreader', Georgia, 'Times New Roman', serif;
  --ns-sans:  'Source Sans 3', 'Segoe UI', system-ui, -apple-system, sans-serif;
  --ns-maxw:  1400px;

  /* Brücke zu css/modal.css: dort stehen diese sechs Namen fest. */
  --navy-900:  #11212e;
  --navy-700:  #12395c;
  --text-body: #4b5d6c;
  --bg-page:   #eceae4;
  --bg-card:   #ffffff;
  --border:    #dcd8ce;
}

body {
  font-family: var(--ns-sans);
  color: var(--ns-ink);
  background: var(--ns-page);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;

  /* Ein zu langes Wort bricht um, statt aus seinem Kasten zu laufen.
     Gemessen bei 360px Fensterbreite: in zehn von 38 Ausgaben lief das
     Dokument nach rechts hinaus, bis auf 866px. Verursacher waren immer
     einzelne unteilbare Woerter, einmal ein Link auf bundesregierung.de,
     einmal "Erwerbsunfaehigkeitsversicherung" in einer Ueberschrift.

     Die Regel steht hier und nicht an den einzelnen Textklassen, weil sie
     geerbt wird und damit auch Texte erfasst, die es heute noch nicht
     gibt. Bewusst "break-word" und nicht "anywhere": break-word bricht nur
     dort, wo es sonst ueberlaeuft, und laesst die min-content-Breite
     unberuehrt. "anywhere" senkt sie auf ein Zeichen und verhandelt damit
     die Breite jedes Flex- und Grid-Elements der Seite neu. */
  overflow-wrap: break-word;
}

#app {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--ns-page);
}


/* ───────────────────────────────────────────────────────────────────────────
   3) Kopfzeile (Utility-Header)
   Quelle: README §1.
   ─────────────────────────────────────────────────────────────────────────── */
.ns-topbar {
  background: var(--ns-surface);
  border-bottom: 1px solid #e2ded5;
}

.ns-topbar__inner {
  max-width: var(--ns-maxw);
  margin: 0 auto;
  padding: 0 32px;
  min-height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}

/* Wortmarke nach docs/logos/infinma-news-04b-badge-markenblau.png.
   "news" steht dort als gefuellte Flaeche neben dem infinma-Schriftzug.

   Alle Werte sind AN DER DATEI GEMESSEN und nicht geschaetzt. Die Referenz
   ist 1052x272 gross, der Badge darin 490x192, die Schrift 337x81. Daraus
   die Verhaeltnisse, angewandt auf die 25px hohe Logodatei im Header:

     Badgehoehe / Hoehe infinma        1,2075  ->  25px * 1,2075 = 30px
     Innenpolster links / Badgehoehe   0,4010  ->  30px * 0,4010 = 12px
     Innenpolster rechts / Badgehoehe  0,3958  ->  dieselben 12px
     Abstand infinma-Badge / Badgeh.   0,3385  ->  30px * 0,3385 = 10px
     Fuellung                          #12395c, am Pixel gemessen, also
                                       genau --ns-navy
     Schrift im Badge                  #ffffff, am Pixel gemessen

   Die Schriftgroesse ist ueber die Breite zurueckgerechnet: die Referenz
   braucht bei 30px Badgehoehe 52,66px Schriftbreite, Newsreader 500 liefert
   bei 24px gemessen 52,61px. Vorher standen hier 23px.

   ECKEN: die Referenz hat KEINEN Radius. Alle vier Eckpixel sind gefuellt,
   die Diagonaltiefe bis zur Fuellung betraegt 0px. Das passt auch zur
   Formsprache des Entwurfs, in der ausser Pillen und Tags alles kantig ist.

   Der fruehere Trennstrich .ns-brand__sep ist entfallen, die Referenz hat
   keinen. Der infinma-Schriftzug selbst ist unveraendert. */
.ns-brand { display: flex; align-items: center; gap: 10px; }
.ns-brand__logo { height: 25px; width: auto; }
.ns-brand__word {
  display: inline-flex; align-items: center;
  height: 30px; padding: 0 12px;
  background: var(--ns-navy); color: #ffffff;
  font-family: var(--ns-serif);
  font-size: 24px; font-weight: 500; line-height: 1;
}

.ns-topbar__links {
  display: flex; align-items: center; gap: 28px;
  font-size: 15px; color: #3f5464;
  flex-wrap: wrap;
}

.ns-topbar__link {
  font: inherit; color: #3f5464; background: none; border: 0; padding: 0;
  cursor: pointer; display: inline-flex; align-items: center; gap: 7px;
}
.ns-topbar__link:hover { color: var(--ns-navy-dark); text-decoration: underline; }

/* "Newsletter abonnieren" steht als einziger Punkt der Leiste fuer eine
   Handlung und nicht fuer einen Ort. Er sitzt deshalb ganz rechts, wo das
   Auge die Leiste verlaesst, und traegt mehr Gewicht als Kontakt und
   infinma.com. Bewusst nur Schriftschnitt und Farbe, kein gefuellter Knopf:
   der Header soll dem Hero nicht die Schau stehlen. */
.ns-topbar__link--stark { font-weight: 700; color: var(--ns-navy); }


/* ───────────────────────────────────────────────────────────────────────────
   4) Hero
   Quelle: README §2. Zwei bewusst schwache Scrims über dem Foto, damit das
   Motiv sichtbar bleibt, dazu Text-Shadows am weißen Text.
   ─────────────────────────────────────────────────────────────────────────── */
.ns-hero {
  position: relative;
  background: var(--ns-navy-dark);
  overflow: hidden;
}

/* Das Foto ist 1914x822, die Spitzen der Domtuerme liegen in Zeile 405,
   also bei 49,3 Prozent der Hoehe. Die Hoehe des Heros ergibt sich allein aus
   dem Text, das Foto fuellt sie mit cover aus. Ab etwa 650px Breite ist der
   Hero flacher als das Foto, geschnitten wird dann oben und unten, und 68
   Prozent des Ueberstands fallen oben weg. Schmaler wird seitlich geschnitten.

   Gemessen am 22.09.2026 nach dem Fotowechsel auf hero-koeln-skyline.webp.
   Das Motiv sitzt dort rund 6 Prozentpunkte tiefer als im Vorgaengerfoto
   (Domspitzen 49,3 statt 43,7 Prozent), deshalb 68 statt 72 Prozent: mit 72
   waeren die Spitzen bei 2560px um 10px angeschnitten. Mit 68 bleiben bei
   1920px 88px Luft, bei 2560px 36px. */
.ns-hero__img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 68%;
  display: block;
}

/* Ab 1800px noch etwas hoeher ansetzen. Mit 68 Prozent blieben bei 2560px
   nur 36px Luft ueber den Domspitzen, mit 64 Prozent sind es 59px, bei
   1920px 108px statt 88px. Unterhalb von 1800px bleibt es bei 68 Prozent,
   jeder Prozentpunkt weniger schiebt Rhein und Bruecke weiter unter die
   Meta-Zeile. */
@media (min-width: 1800px) {
  .ns-hero__img { object-position: 50% 64%; }
}

.ns-hero__scrim { position: absolute; inset: 0; }

/* Scrim A. Eine senkrechte Bahn ueber der linken Bildhaelfte, die den
   Text traegt.

   STAND 25.09.2026. Vorher lagen hier drei Ebenen: ein Verlauf mit 100deg
   ueber die volle Breite, ab 1000px durch eine Ellipse ersetzt, und davor
   eine Maske, die die Ellipse links vom Text ausblendete. Alle drei sind
   entfallen. Der Grund war nicht technisch, sondern gestalterisch: die
   Konstruktion legte sich als breite, kalte Flaeche ueber das halbe Foto,
   im Urteil des Auftraggebers wie eine Rauchwolke. Ein Mockup gab die
   Zielrichtung vor, und diese Bahn ist daran nachgebaut.

   Die Werte stammen aus dem Mockup, nicht aus einer Vorliebe:

     Grundton rgb(49,87,117). Die Vorlage liegt an ihrer dichtesten
     Stelle sichtbar bei rgb(105,126,145), diese Bahn trifft dort
     rgb(102,127,146).

     Die Flaeche beginnt bei 9 Prozent, steht ab 14 Prozent, ist bei 20
     Prozent am dichtesten und ist bei 42 Prozent verschwunden. Links
     davon bleibt die Sonne ueber dem Wasser frei, rechts davon das Foto
     unangetastet. Der frueher genutzte Bereich reichte bis 62 Prozent.

     Der Anlauf von 9 auf 14 Prozent ist kurz und ABSICHTLICH nicht
     weicher. Die Vorlage hat dort eine erkennbare Kante. Ueber 7 Prozent
     verteilt verschwimmt sie, bei einem einzigen Stopp wird daraus eine
     gerade Linie durch das ganze Bild.

   KEINE MASKE MEHR. Sie war noetig, solange die Ellipse ueber die linke
   Fensterkante hinauslief. Die Bahn beginnt von sich aus erst bei 9
   Prozent, eine Maske haette nichts mehr zu tun. Getestet wurde es
   trotzdem: mit diesem helleren Ton ist zwischen mit und ohne Maske kein
   Unterschied zu sehen.

   ACHTUNG, hier wurde NICHT auf Kontrast gemessen. Die alte Konstruktion
   war auf AA getrimmt, mit dem Untertitel bei 1024px als Engpass. Diese
   Fassung ist ein freigegebener Sichtentwurf, das Kriterium war allein
   der Abgleich mit dem Mockup. Wer die Lesbarkeit belegen will, misst
   neu. */
/* AM CONTAINER VERANKERT, nicht an Fensterprozenten. Nachgezogen am
   25.09.2026, nachdem die Prozentfassung bei schmalen Fenstern
   auseinanderlief: der Textblock sitzt im zentrierten 1400px-Container,
   die Bahn lag in Prozent des Fensters. Bei 360px ragte der Untertitel
   167px ueber das Ende der Bahn hinaus und stand auf ungetoentem Foto.

   Der Text beginnt an der Containerkante plus Polster und endet rund
   418px dahinter, und zwar bei JEDER Breite, weil der Container immer
   1400px breit ist. Die Bahn steht damit ueberall gleich zum Text.

   Chromium verwirft calc(max(...) * Zahl), siehe die frueheren Notizen
   zur Ellipse. Hier wird ausschliesslich addiert und subtrahiert.

   WARUM 49 STOPPS UND NICHT ZEHN. Ein linear-gradient ist zwischen zwei
   Stopps eine GERADE. An jedem Stopp wechselt die Steigung sprunghaft,
   und das Auge sieht nicht den Helligkeitssprung, sondern genau diesen
   Knick, als senkrechte Linie. Mach-Streifen heisst das.

   Mit zehn Stopps waren bei 1800px zwei solche Linien sichtbar, bei
   x=77 und bei x=206. Die Steigungswechsel dort betrugen 0,00128 und
   0,00141 je Bildpunkt. Der groesste Wechsel der Kurve lag mit 0,00255
   bei x=468 und fiel NICHT auf, weil dort dunklerer Himmel liegt.

   Das ist der zweite Teil der Erklaerung: der sichtbare Unterschied ist
   immer Deckkraft mal (Foto minus Overlayton). Gemessen am ungetoenten
   Foto bei 1800px ist die linke Bildhaelfte im Mittel 205 hell, die
   rechte 180. Dieselbe Deckkraftaenderung schlaegt links deshalb rund
   30 Prozent staerker durch. Links liegt die Sonnenspiegelung, dort
   wird jeder Knick sichtbar, rechts verschwindet derselbe Knick.

   Die Kurve stammt aus zehn Stuetzstellen, geglaettet mit einem
   Hann-Fenster von 220px und danach alle 20px abgetastet. Dadurch
   sinkt der groesste Steigungswechsel von 0,00255 auf 0,00046, also
   unter den kleinsten Wert, der vorher nachweislich unsichtbar blieb.

   DIE DAEMPFUNG LINKS: im Anlauf ist die Deckkraft auf 80 Prozent
   zurueckgenommen und laeuft bis zur Textkante wieder auf 100 Prozent
   hoch. Am Textanfang betraegt der Faktor bereits 0,98, der Textbereich
   bleibt also unberuehrt, gedaempft wird nur der helle Sonnenbereich
   davor. Das gleicht den Helligkeitsunterschied von oben aus.

   WER HIER ETWAS AENDERT, aendert nicht einzelne Zahlen. Die 49 Werte
   sind Abtastpunkte einer geglaetteten Kurve. Eine von Hand verschobene
   Stuetzstelle bringt genau den Knick zurueck, den die Glaettung
   entfernt hat. Erzeugt wurden sie von s3_glatt.py im Scratchpad,
   Aufruf glaetten(B5, 220, daempfung=(52, 0.80)). */
.ns-hero__scrim--a {
  background: linear-gradient(to right,
    rgba(49,87,117,0) calc(max(0px, (100% - 1400px) / 2) - 340px),
    rgba(49,87,117,0.0032) calc(max(0px, (100% - 1400px) / 2) - 320px),
    rgba(49,87,117,0.0066) calc(max(0px, (100% - 1400px) / 2) - 300px),
    rgba(49,87,117,0.0118) calc(max(0px, (100% - 1400px) / 2) - 280px),
    rgba(49,87,117,0.0196) calc(max(0px, (100% - 1400px) / 2) - 260px),
    rgba(49,87,117,0.0304) calc(max(0px, (100% - 1400px) / 2) - 240px),
    rgba(49,87,117,0.0449) calc(max(0px, (100% - 1400px) / 2) - 220px),
    rgba(49,87,117,0.0635) calc(max(0px, (100% - 1400px) / 2) - 200px),
    rgba(49,87,117,0.0868) calc(max(0px, (100% - 1400px) / 2) - 180px),
    rgba(49,87,117,0.1155) calc(max(0px, (100% - 1400px) / 2) - 160px),
    rgba(49,87,117,0.1501) calc(max(0px, (100% - 1400px) / 2) - 140px),
    rgba(49,87,117,0.1908) calc(max(0px, (100% - 1400px) / 2) - 120px),
    rgba(49,87,117,0.2375) calc(max(0px, (100% - 1400px) / 2) - 100px),
    rgba(49,87,117,0.2901) calc(max(0px, (100% - 1400px) / 2) - 80px),
    rgba(49,87,117,0.3474) calc(max(0px, (100% - 1400px) / 2) - 60px),
    rgba(49,87,117,0.4077) calc(max(0px, (100% - 1400px) / 2) - 40px),
    rgba(49,87,117,0.4684) calc(max(0px, (100% - 1400px) / 2) - 20px),
    rgba(49,87,117,0.5264) calc(max(0px, (100% - 1400px) / 2) + 0px),
    rgba(49,87,117,0.5787) calc(max(0px, (100% - 1400px) / 2) + 20px),
    rgba(49,87,117,0.6231) calc(max(0px, (100% - 1400px) / 2) + 40px),
    rgba(49,87,117,0.6586) calc(max(0px, (100% - 1400px) / 2) + 60px),
    rgba(49,87,117,0.6856) calc(max(0px, (100% - 1400px) / 2) + 80px),
    rgba(49,87,117,0.7054) calc(max(0px, (100% - 1400px) / 2) + 100px),
    rgba(49,87,117,0.7193) calc(max(0px, (100% - 1400px) / 2) + 120px),
    rgba(49,87,117,0.7283) calc(max(0px, (100% - 1400px) / 2) + 140px),
    rgba(49,87,117,0.7332) calc(max(0px, (100% - 1400px) / 2) + 160px),
    rgba(49,87,117,0.7342) calc(max(0px, (100% - 1400px) / 2) + 180px),
    rgba(49,87,117,0.7309) calc(max(0px, (100% - 1400px) / 2) + 200px),
    rgba(49,87,117,0.722) calc(max(0px, (100% - 1400px) / 2) + 220px),
    rgba(49,87,117,0.7061) calc(max(0px, (100% - 1400px) / 2) + 240px),
    rgba(49,87,117,0.6817) calc(max(0px, (100% - 1400px) / 2) + 260px),
    rgba(49,87,117,0.6481) calc(max(0px, (100% - 1400px) / 2) + 280px),
    rgba(49,87,117,0.6058) calc(max(0px, (100% - 1400px) / 2) + 300px),
    rgba(49,87,117,0.5565) calc(max(0px, (100% - 1400px) / 2) + 320px),
    rgba(49,87,117,0.5034) calc(max(0px, (100% - 1400px) / 2) + 340px),
    rgba(49,87,117,0.4498) calc(max(0px, (100% - 1400px) / 2) + 360px),
    rgba(49,87,117,0.3979) calc(max(0px, (100% - 1400px) / 2) + 380px),
    rgba(49,87,117,0.3485) calc(max(0px, (100% - 1400px) / 2) + 400px),
    rgba(49,87,117,0.3014) calc(max(0px, (100% - 1400px) / 2) + 420px),
    rgba(49,87,117,0.2561) calc(max(0px, (100% - 1400px) / 2) + 440px),
    rgba(49,87,117,0.2118) calc(max(0px, (100% - 1400px) / 2) + 460px),
    rgba(49,87,117,0.1683) calc(max(0px, (100% - 1400px) / 2) + 480px),
    rgba(49,87,117,0.1265) calc(max(0px, (100% - 1400px) / 2) + 500px),
    rgba(49,87,117,0.0885) calc(max(0px, (100% - 1400px) / 2) + 520px),
    rgba(49,87,117,0.0565) calc(max(0px, (100% - 1400px) / 2) + 540px),
    rgba(49,87,117,0.032) calc(max(0px, (100% - 1400px) / 2) + 560px),
    rgba(49,87,117,0.0154) calc(max(0px, (100% - 1400px) / 2) + 580px),
    rgba(49,87,117,0.0058) calc(max(0px, (100% - 1400px) / 2) + 600px),
    rgba(49,87,117,0) calc(max(0px, (100% - 1400px) / 2) + 620px));
}

.ns-hero__inner {
  position: relative;
  max-width: var(--ns-maxw);
  margin: 0 auto;
  padding: 40px 32px 34px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 30px 56px;
  align-items: start;
}

.ns-hero__kicker {
  display: flex; align-items: center; gap: 12px;
  margin-bottom: 14px;
}
.ns-hero__kickerbar { width: 22px; height: 2px; background: var(--ns-accent); flex: 0 0 auto; }
.ns-hero__kickertext {
  font-size: 12px; letter-spacing: 0.18em; text-transform: uppercase;
  color: #ffffff; font-weight: 600;
  text-shadow: 0 1px 10px rgba(7,26,44,0.55);
}

.ns-hero__title {
  margin: 0;
  font-family: var(--ns-serif);
  font-size: clamp(34px, 3.6vw, 50px);
  line-height: 1.0; font-weight: 600; letter-spacing: -0.03em;
  color: #ffffff;
  text-shadow: 0 2px 20px rgba(7,26,44,0.45);
  max-width: 15ch;
  text-wrap: balance;
}

/* Weiss seit dem 22.09.2026, vorher #dce8f2. Gemessen war der Untertitel an
   jeder Breite der Engpass: mit #dce8f2 lag er bei 1024px bei 5,37:1, weiss
   bei 8,47:1. Dieser Gewinn ist die Gegenrechnung zur leichteren Ellipse.
   Der Unterschied zum Titel traegt weiter die Schrift: 17px gegen 34 bis
   50px, normal gegen 600. */
.ns-hero__sub {
  margin: 16px 0 0;
  font-size: 17px; line-height: 1.5; color: #ffffff;
  max-width: 44ch; text-wrap: pretty;
  text-shadow: 0 1px 12px rgba(7,26,44,0.5);
}

/* Meta-Streifen, noch im Hero-Container. Quelle: README §2.

   Grund am 22.09.2026 von 0,62 auf 0,45 gesenkt und die Linie von 0,18 auf
   0,14 mitgefuehrt, der Streifen wirkte zu schwer. Tiefer nicht: die
   Erscheinungszeile traegt ihre Lesbarkeit allein aus diesem Grund, und die
   engste Breite ist 360px, nicht die breiten. Gemessen dort: 0,62 gibt 7,40:1,
   0,45 noch 5,36:1, 0,42 nur 4,98:1. Bei 0,45 bleiben also 0,86 Reserve, bei
   0,42 nur 0,48, und die Messung schwankt zwischen zwei Laeufen um bis zu 0,3. */
.ns-hero__meta {
  position: relative;
  border-top: 1px solid rgba(255,255,255,0.14);
  background: rgba(49,87,117,0.30);
}
.ns-hero__metainner {
  max-width: var(--ns-maxw);
  margin: 0 auto;
  padding: 8px 32px;
  display: flex; align-items: center; gap: 36px; flex-wrap: wrap;
  min-height: 54px;
}
.ns-hero__metaitem { font-size: 14px; color: #c9dcea; }
.ns-hero__metaitem strong { color: #ffffff; font-weight: 700; }


/* ───────────────────────────────────────────────────────────────────────────
   5) Inhalts-Layout
   Quelle: README §3. Kein max-width und kein sticky an der Sidebar: bricht
   sie unter die Hauptspalte, füllt sie als Modul-Grid die volle Breite.
   .ns-wrap trägt die id news-main, weil alle Aktionen aus js/actions.js in
   dieses Element schreiben.
   ─────────────────────────────────────────────────────────────────────────── */
.ns-wrap {
  max-width: var(--ns-maxw);
  margin: 0 auto;
  width: 100%;
  padding: 0 32px 96px;
  display: flex;
  gap: 56px;
  align-items: flex-start;
  flex-wrap: wrap;
}

.ns-main { flex: 4 1 620px; min-width: 0; }

/* Dritte Zeile des Flex-Behaelters: die Themenbeitraege ueber die volle
   Breite. flex-basis 100% zwingt sie in eine eigene Zeile, der row-gap von
   .ns-wrap liefert den Abstand nach oben. Die rechte Spalte endet oberhalb,
   der Platz daneben stand vorher leer. */
.ns-voll { flex: 1 1 100%; min-width: 0; }

.ns-side {
  flex: 1 1 300px;
  min-width: 280px;
  padding-top: 44px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 32px;
  align-items: start;
}


/* ───────────────────────────────────────────────────────────────────────────
   6) Aufmacher
   Quelle: README §4.
   ─────────────────────────────────────────────────────────────────────────── */
/* Der Aufmacher steht ohne eigene Flaeche auf dem Seitengrund und ist nur
   durch die 3px-Linie nach unten abgesetzt. Quelle: README §4.

   Zwischenzeitlich trug er eine Navy-Flaeche wie die Ausgabe-Karte. Das ist
   zurueckgenommen, die grosse Flaeche war zu dominant fuer den Seitenanfang.
   Von der Angleichung geblieben ist nur das Abzeichen, siehe
   .ns-label--solid. Wer die Flaeche je zurueckholt, braucht wieder helle
   Schrift an Titel, Standfirst und Fusszeile, einen Akzent statt Navy an der
   Oberkante der Kennzahlkarte und margin-top statt padding-top oben. */
.ns-lead {
  display: flex; gap: 40px; flex-wrap: wrap;
  padding: 44px 0 40px;
  border-bottom: 3px solid var(--ns-ink);
}

.ns-lead__text { flex: 1 1 420px; min-width: 0; }

.ns-lead__labels {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 16px; flex-wrap: wrap;
}
/* Das Abzeichen traegt --ns-navy, denselben Ton wie die Ausgabe-Karte in
   der Filterspalte und das Kapitelband weiter unten. Vorher war es
   --ns-ink (#11212e), also fast schwarz und damit ein vierter dunkler Ton
   neben den dreien. Weisse Schrift darauf, gemessen 11,89:1.

   Das ist der einzige Rest der Farbangleichung am Aufmacher. Die grosse
   Flaeche darunter bleibt hell. */
.ns-label--solid {
  background: var(--ns-navy); color: #ffffff;
  font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase;
  font-weight: 700; padding: 5px 9px;
}

.ns-rubrik {
  font-size: 13px; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ns-rubric); font-weight: 600;
}

.ns-lead__title {
  margin: 0;
  font-family: var(--ns-serif);
  font-size: clamp(32px, 3.4vw, 50px);
  line-height: 1.05; font-weight: 600; letter-spacing: -0.02em;
  color: var(--ns-ink);
  text-wrap: balance;
}
.ns-lead__title:hover { color: var(--ns-navy); }

.ns-lead__standfirst {
  margin: 22px 0 0;
  font-family: var(--ns-serif);
  font-size: 21px; line-height: 1.52; color: #33475a;
  text-wrap: pretty;
}

.ns-lead__foot {
  margin-top: 26px;
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  font-size: 15px; color: var(--ns-body-mid);
  background: none; border: 0; padding: 0; cursor: pointer; font-family: inherit;
}
.ns-lead__more  { font-weight: 600; color: var(--ns-navy); }
.ns-lead__foot:hover .ns-lead__more { text-decoration: underline; }
.ns-lead__rule  { width: 40px; height: 1px; background: #b9c6d0; }

/* Kennzahl-Karte: Papierton statt zweiter Navy-Flaeche. Quelle: README §4. */
.ns-stat {
  flex: 0 1 300px; min-width: 260px;
  background: var(--ns-paper);
  border: 1px solid #d8d3c6;
  border-top: 3px solid var(--ns-navy);
  color: var(--ns-ink);
  padding: 26px 26px 24px;
  display: flex; flex-direction: column;
}
/* 13px statt der 11px des Entwurfs. Die Karte steht neben dem Abzeichen
   "AUFMACHER" und der Ausgabe-Karte mit "AUSGABE", beide ebenfalls 11px,
   aber beide auf gefuellter Flaeche und damit optisch schwerer. Auf dem
   hellen Papierton wirkte dieselbe Groesse nebensaechlich.

   13px ist der groesste Grad, der bei unveraenderter Laufweite noch in
   eine Zeile passt: die Karte ist an jeder Fensterbreite gemessen 300px
   breit, innen also 248px, und "DIESE AUSGABE IM UEBERBLICK" braucht bei
   13px und 0,16em gemessen 229px. 14px kaemen auf 246px und haetten nur
   zwei Pixel Luft, das ist zu knapp. Die Laufweite bleibt bewusst bei
   0,16em, dieselbe wie an den beiden anderen Beschriftungen. */
.ns-stat__label {
  font-size: 13px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ns-navy); font-weight: 700;
}
.ns-stat__big {
  margin-top: 16px;
  display: flex; align-items: baseline; gap: 10px;
}
.ns-stat__num {
  font-family: var(--ns-serif);
  font-size: 62px; line-height: 0.9; letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.ns-stat__numlabel { font-size: 15px; line-height: 1.3; color: var(--ns-body-mid); }

.ns-stat__rows { margin-top: 20px; }

/* padding-right haelt in JEDER Zeile den Platz frei, den der Pfeil braucht,
   auch in den beiden ohne Pfeil. Sonst stuenden die Zahlen der klickbaren
   Zeilen um genau diese 17px weiter links als die der uebrigen, und die
   vier Zahlen haetten keine gemeinsame Flucht. 17px sind die 11px des
   Zeichens plus 6px Abstand davor.

   Die Trennlinie bleibt davon unberuehrt: padding verkleinert den
   Inhaltskasten, border-top laeuft weiter ueber die volle Elementbreite. */
.ns-stat__row {
  position: relative;
  display: flex; justify-content: space-between; gap: 12px;
  padding: 9px 17px 9px 0; border-top: 1px solid var(--ns-line-5);
  font-size: 15px;
}
.ns-stat__row-k { color: var(--ns-body-mid); }
.ns-stat__row-v { color: var(--ns-ink); font-weight: 600; font-variant-numeric: tabular-nums; }

/* Zwei der vier Zeilen sind Knoepfe und klappen eine Titelliste auf.

   Die Optik der Zeile bleibt dabei unangetastet: dieselbe Klasse
   .ns-stat__row, dieselben Abstaende, dieselbe Schrift, dieselben Farben.
   Der Block hier nimmt dem <button> nur seine eigenen Vorgaben weg, die
   der Browser mitbringt, und ergaenzt den Pfeil. Gemessen sind Zeilenhoehe
   und die Lage von Beschriftung und Zahl vor und nach dem Umbau gleich.

   border-left/right/bottom muessen einzeln auf 0: .ns-stat__row setzt nur
   border-top, die uebrigen drei Kanten behielten sonst den Vorgaberahmen
   des Knopfes. */
button.ns-stat__row {
  width: 100%;
  background: none;
  border-left: 0; border-right: 0; border-bottom: 0;
  font-family: inherit; font-size: 15px; line-height: inherit;
  text-align: left; cursor: pointer;
}
button.ns-stat__row:hover .ns-stat__row-k { color: var(--ns-navy); }

/* Der Pfeil steht ausserhalb des Textflusses am rechten Rand der Zeile, in
   dem Streifen, den das padding-right oben freihaelt. Nur so schiebt er die
   Zahl nicht nach links.

   Die Drehung muss das translateY der Zentrierung mitfuehren, sonst springt
   das Zeichen beim Aufklappen nach unten. */
.ns-stat__pfeil {
  position: absolute; right: 0; top: 50%;
  transform: translateY(-50%);
  color: var(--ns-meta);
  transition: transform 0.18s ease;
}
.ns-toc__section.is-open .ns-stat__pfeil { transform: translateY(-50%) rotate(180deg); }

/* Die Liste schwebt ueber dem uebrigen Karteninhalt, statt ihn nach unten
   zu schieben. Vorher wanderten beim Aufklappen die Zeilen darunter, die
   Gesellschaften, die Lesezeit und der PDF-Knopf mit.

   Dasselbe Rezept wie .nsx-tocpick__panel auf index_v2.html: absolut am
   Knopf verankert, eigener Grund, Rahmen, Schatten, gedeckelte Hoehe mit
   Rollbalken. Kein Radius, anders als dort: hier ist ausser Pillen und
   Tags alles kantig.

   Der Schatten ist hier die Ausnahme von der Regel "keine Box-Shadows" des
   Entwurfs, und zwar aus demselben Grund wie auf index_v2.html: ein
   schwebendes Panel braucht Tiefe, sonst liest es sich als Teil der Karte.
   Der Grund ist Weiss gegen den Papierton der Karte, der Unterschied allein
   traegt nicht.

   Verankert ist es an der EIGENEN Zeile, .ns-stat__group, und schliesst
   ohne Abstand an deren Unterkante an. Es traegt den Kartengrund und
   liegt links wie rechts genau auf den Kanten der Zeile, ist also so
   breit wie deren Trennlinie.

   Zwischenstand war eine schwebende weisse Box mit Rahmen, Schatten und
   12px Ueberhang, verankert am Behaelter um BEIDE Zeilen. Sie las sich als
   eigenstaendiges Element neben der Karte statt als Fortsetzung der Zeile.

   Preis dieser Loesung, bewusst in Kauf genommen: das offene Panel deckt
   die Zeilen darunter zu, bei offenen Kurzmeldungen also die Zeile
   "Themenbeitraege". Sie ist dann nicht anklickbar, bis das Panel zu ist.
   Das geht auf vier Wegen, siehe js/seite.js: zweiter Klick auf die
   Zeile, Escape, Klick daneben, Sprung. */
.ns-stat__klapp { position: static; }
.ns-stat__group { position: relative; }

/* Solange ein Panel offen ist, tritt alles darunter zurueck.

   Grund: das Panel ist nur so hoch wie seine Liste, alles Laengere
   darunter schaut unten heraus. Gemessen endete das Panel der
   Kurzmeldungen bei y=834, der PDF-Knopf reicht aber bis 840 und blitzte
   als blauer Streifen hervor. Beim Panel der Themenbeitraege waren es
   sogar 32px.

   visibility statt display: der Platz bleibt erhalten, die Karte behaelt
   ihre Hoehe, und nichts verschiebt sich. Genau darum ging es beim Umbau
   auf ein schwebendes Panel.

   :has() waehlt die Faelle sauber ab, dieselbe Technik wie
   .nsx-cols:has(.news-kurz-section) in css/news_v2.css. Der Nachlaeufer
   ~ trifft nur, was NACH dem offenen Abschnitt kommt: ist unten
   "Themenbeitraege" offen, bleibt "Kurzmeldungen" darueber sichtbar. */
.ns-stat__group.is-open ~ .ns-stat__group,
.ns-stat__klapp:has(.ns-toc__section.is-open) ~ .ns-stat__row,
.ns-stat:has(.ns-toc__section.is-open) .ns-stat__pdfwrap {
  visibility: hidden;
}

.ns-stat__list { list-style: none; margin: 0; padding: 0; display: none; }

.ns-toc__section.is-open .ns-stat__list {
  display: block;
  position: absolute;
  top: 100%; left: 0; right: 0;
  z-index: 30;
  max-height: 320px; overflow-y: auto;
  padding: 2px 0 9px;
  background: var(--ns-paper);
  border-bottom: 1px solid var(--ns-line-5);
}

.ns-stat__jump {
  width: 100%; display: flex; align-items: baseline;
  justify-content: space-between; gap: 10px;
  background: none; border: 0; padding: 5px 0 5px 14px;
  font-family: inherit; font-size: 13.5px; line-height: 1.4;
  color: var(--ns-body-mid); text-align: left; cursor: pointer;
  position: relative;
}
.ns-stat__jump::before {
  content: ''; position: absolute; left: 3px; top: 11px;
  width: 4px; height: 4px; background: var(--ns-line-3);
}
.ns-stat__jump:hover { color: var(--ns-navy); }
.ns-stat__jump:hover::before { background: var(--ns-navy); }
.ns-stat__jump-t { min-width: 0; }
.ns-stat__jump-z {
  flex: 0 0 auto; font-size: 12px; color: var(--ns-meta);
  font-variant-numeric: tabular-nums;
}

.ns-stat__pdfwrap {
  margin-top: 20px; border-top: 1px solid var(--ns-line-5); padding-top: 18px;
}
/* 38px hoch. Der Knopf war mit seinen urspruenglichen 46px die hoechste
   Flaeche der Karte und zog dadurch mehr Aufmerksamkeit auf sich als der
   Inhalt darueber. 38px ist der Wert, an dem er spuerbar zurueckttritt,
   ohne schwer bedienbar zu werden.

   Der Boden dafuer ist nicht Geschmack: WCAG 2.2, Erfolgskriterium 2.5.8
   Target Size (Minimum), verlangt auf Stufe AA mindestens 24x24 CSS-Pixel.
   38px lassen dazu 14px Luft. Die 44px, die Apple und WCAG 2.5.5 auf
   Stufe AAA nennen, unterschreitet der Knopf damit bewusst. Er ist
   246px breit, die Trefferflaeche ist also reichlich.

   Mitgezogen sind Symbol und Schrift, sonst wirkt die Flaeche gestopft:
   17px statt 18px und 14px statt 15px. Der Inhalt misst damit 20px, es
   bleiben 9px Luft nach oben und unten.

   Der Radius ist 8px. 12px waren bei 38px Hoehe 63 Prozent der halben
   Hoehe und naeherten sich damit der Kapselform, 6px lesen sich bei
   dieser Hoehe schon fast scharfkantig. 8px sind 42 Prozent, die Ecke
   bleibt deutlich weich, draengt sich aber nicht auf.

   Farbe und Schriftgewicht bleiben, wie sie sind: --ns-navy und 700.
   Bewusst KEIN Schatten. Das Seitenformat kennt an keiner einzigen
   Stelle einen box-shadow, die Flaechen stehen flach nebeneinander. */
.ns-pdfbtn {
  width: 100%;
  background: var(--ns-navy); color: #ffffff;
  min-height: 38px; border: 0; cursor: pointer;
  border-radius: 8px;
  display: flex; align-items: center; justify-content: center; gap: 9px;
  padding: 0 14px;
  font-family: inherit;
  /* Der Knopf ist ein <a download>, ohne das hier waere er unterstrichen. */
  text-decoration: none;
}
.ns-pdfbtn:hover { background: var(--ns-navy-dark); }
/* line-height 1.15 statt des geerbten Werts. Ohne das bringt die Zeile
   ihre eigene Hoehe mit und der Knopf waere hoeher als seine min-height. */
.ns-pdfbtn__label {
  font-size: 14px; font-weight: 700; letter-spacing: 0.01em; line-height: 1.15;
}
/* Das Symbol erbt seine Farbe ueber currentColor vom Knopf. Damit bleibt es
   bei einem Farbwechsel automatisch richtig, auch im Hover. */
.ns-pdfbtn__doc {
  width: 17px; height: 17px; flex: 0 0 auto;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}


/* ───────────────────────────────────────────────────────────────────────────
   7) Kurzmeldungen
   Quelle: README §5. Zwei typografische Ebenen erzeugen die Hierarchie, ohne
   dass es Karten-Container braucht.
   ─────────────────────────────────────────────────────────────────────────── */
.ns-sechead {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
  padding: 42px 0 8px;
}
.ns-sechead__h {
  margin: 0;
  font-family: var(--ns-serif);
  font-size: 32px; font-weight: 600; letter-spacing: -0.01em;
  color: var(--ns-ink);
}
.ns-sechead__meta {
  font-size: 13px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ns-meta); font-weight: 600;
}

.ns-briefs--lead {
  margin-top: 14px;
  padding: 22px 0 28px;
  border-top: 1px solid var(--ns-line-2);
  border-bottom: 1px solid var(--ns-line-2);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 34px 48px;
}

.ns-briefs--rest {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 0 48px;
}

/* Die ganze Meldung ist ein einziger Knopf, wie auf index.html und
   index_v2.html: toggleNewsArticle() bleibt unverändert die Bedienung.
   Die Klasse ns-schlag-item ist Pflicht, _newsInstallOutsideHandler() in
   js/actions.js prüft mit closest('.ns-schlag-item'), ob der Klick in einer
   offenen Meldung lag. */
.ns-brief { display: block; }
.ns-brief__btn {
  width: 100%; text-align: left;
  font: inherit; color: inherit; background: none; border: 0; padding: 0;
  cursor: pointer;
  display: flex; flex-direction: column;
}

.ns-brief--lead .ns-brief__btn { gap: 12px; }
.ns-brief--rest { padding: 22px 0; border-bottom: 1px solid var(--ns-line); }
.ns-brief--rest .ns-brief__btn { gap: 8px; }

.ns-brief__meta {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
}
/* Alle Kategorie-Marker tragen denselben Ton, siehe --ns-gold. Navy bleibt
   den strukturellen Flaechen vorbehalten, Karten, Baendern, Knoepfen. */
.ns-brief__marker { background: var(--ns-gold); flex: 0 0 auto; }
.ns-brief--lead .ns-brief__marker { width: 9px; height: 9px; }
.ns-brief--rest .ns-brief__marker { width: 6px; height: 6px; }
/* 12px statt der 11px des Exports. Versalien mit 0,16em Sperrung lesen
   sich bei 11px muehsam, gerade in dieser Farbe. Ein Punkt mehr reicht,
   die Zeile bleibt einzeilig und die Kachel unveraendert im Aufbau. */
.ns-brief__rubrik {
  font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ns-rubric); font-weight: 700;
}

.ns-brief__titlerow {
  display: flex; gap: 14px; align-items: flex-start;
  justify-content: space-between; width: 100%;
}

.ns-brief__title {
  margin: 0;
  font-family: var(--ns-serif);
  font-weight: 600; color: var(--ns-ink);
  text-wrap: pretty;
}
/* Alle Kurzmeldungs-Titel gleich gesetzt, 21px in Newsreader 600.

   Der Export arbeitete mit zwei Ebenen: die ersten beiden Meldungen auf
   29px, die uebrigen auf 21px, dazu unterschiedlich grosse Marker. Das
   sollte Hierarchie ohne Karten-Container erzeugen. In den echten Daten
   gibt es diese Hierarchie aber nicht: welche Meldung oben steht,
   entscheidet die Reihenfolge im Worddokument, nicht ihre Bedeutung.
   Zwei Groessen behaupteten also eine Gewichtung, die es nicht gibt. */
.ns-brief__title { font-size: 21px; line-height: 1.2; letter-spacing: 0; }

/* Ein Satz Werte fuer ALLE Anrisstexte: 16px, Zeilenhoehe 1.6, also
   gemessen 25,6px, in --ns-body-mid.

   Vorher trug die Ebene 1 des Exports 17px/1.58 in --ns-body-soft und die
   Ebene 2 15px/1.55 in --ns-body-mid, gemessen 26,86px gegen 23,25px
   Zeilenhoehe. Von diesen 3,6px Unterschied gehen nur 0,45px auf das
   Verhaeltnis zurueck, die restlichen 3,2px auf die Schriftgroesse. Wer
   nur die line-height angleicht, aendert also fast nichts am sichtbaren
   Zeilenabstand. Deshalb sind Groesse und Farbe mitgezogen.

   16px/1.6 ist kein neu erfundener Wert, sondern der der Anrisstexte in
   den Trefferlisten (.ns-result-snippet). Er liegt zwischen den beiden
   alten Staenden, staucht die ersten beiden Kacheln also nicht und blaeht
   die uebrigen nicht auf.

   Die zwei Ebenen des Exports sind damit auch im Text aufgehoben, wie
   zuvor schon bei den Titeln: welche Meldung oben steht, entscheidet die
   Reihenfolge im Worddokument und nicht ihre Bedeutung. */
.ns-brief__text {
  margin: 0; text-wrap: pretty; white-space: pre-line;
  font-size: 16px; line-height: 1.6; color: var(--ns-body-mid);
}

/* Eingeklappt: vier Zeilen Anriss. Aufgeklappt: voller Text. */
.ns-brief__text.is-clamped {
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Plus-Quadrat als Zustandsanzeige, kantig wie der Rest des Entwurfs.
   aria-hidden, der zugängliche Name der Meldung bleibt Titel und Text. */
.ns-brief__plus {
  width: 26px; height: 26px; flex: 0 0 auto;
  border: 1px solid var(--ns-line-3);
  background: var(--ns-surface);
  color: var(--ns-navy);
  display: flex; align-items: center; justify-content: center;
  font-size: 17px; line-height: 1;
  margin-top: 2px;
}
.ns-brief__btn:hover .ns-brief__plus { background: var(--ns-navy); color: #ffffff; border-color: var(--ns-navy); }
.ns-brief.is-open .ns-brief__plus  { background: var(--ns-navy); color: #ffffff; border-color: var(--ns-navy); }


/* ───────────────────────────────────────────────────────────────────────────
   8) Navy-Kapitelband: Vorschau der Themenbeiträge
   Quelle: README §6. Die Einträge sind Sprunganker auf die Volltexte
   darunter, es gibt keine Detailseiten.
   ─────────────────────────────────────────────────────────────────────────── */
/* Der Abstand nach oben kommt jetzt vom row-gap des Flex-Behaelters, das
   Band steht in einer eigenen Zeile. Der Innenabstand ist derselbe wie an
   den Artikelflaechen darunter, damit beide dieselbe linke Kante haben. */
/* Deutlich gedrungener als im Export. Der Kasten ist ein Verzeichnis und
   kein Kapitelaufschlag, viel Weissraum liess ihn bullig wirken. Aussen
   von 42px auf 26/28px, die Ueberschrift von 34px auf 26px, das Verzeichnis
   einspaltig mit engen Zeilen.

   Gemessene Bauhoehe des Bandes, vorher zweispaltig gegen jetzt:
     3 Eintraege  339px -> 232px  (-32%)
     4 Eintraege  364px -> 272px  (-25%)
     5 Eintraege  388px -> 312px  (-20%)
   Ein Eintrag ist 30px hoch, das Band waechst gleichmaessig um 40px je
   Eintrag statt in Spruengen von einer halben Zeile. */
.ns-chapters {
  background: var(--ns-navy); color: #ffffff;
  padding: 26px var(--ns-art-pad) 28px;
}
.ns-chapters__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
  padding-bottom: 14px;
  border-bottom: 1px solid rgba(255,255,255,0.18);
}
.ns-chapters__h {
  margin: 0; font-family: var(--ns-serif);
  font-size: 26px; font-weight: 600; color: #ffffff;
}
.ns-chapters__note {
  font-size: 13px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ns-accent); font-weight: 700;
}
/* Einspaltige Liste, ein Eintrag je Zeile.

   Das Verzeichnis hatte zwei Staende hinter sich: erst
   repeat(auto-fit, minmax(240px, 1fr)), wo sich die Spaltenzahl nach der
   Breite richtete und bei vier Beitraegen alle vier nebeneinander standen,
   dann ein festes zweispaltiges Raster. Beide liessen bei ungerader Anzahl
   eine halbe Zeile leer, und der Kasten wuchs mit jeder zweiten Zeile um
   die volle Zeilenhoehe.

   Einspaltig gibt es diesen Rest nicht mehr, und die Bauhoehe waechst
   gleichmaessig mit jedem Eintrag, egal ob zwei, drei, vier oder fuenf. */
.ns-chapters__grid {
  display: flex; flex-direction: column;
  gap: 10px;
  padding-top: 14px;
}
/* Nummer links, Titel daneben, Lesezeit und Rubrik rechtsbuendig am Ende
   derselben Zeile. Einspaltig steht die volle Bandbreite zur Verfuegung,
   die Meta-Angabe braucht dann keine eigene Zeile mehr. Erst wenn der Titel
   zu lang wird, bricht er um und die Meta rutscht mit. */
.ns-chapter {
  width: 100%;
  display: flex; gap: 14px; align-items: baseline;
  font: inherit; color: inherit; background: none; border: 0; padding: 0;
  cursor: pointer; text-align: left;
}
.ns-chapter > span:last-child {
  flex: 1; min-width: 0;
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 24px; flex-wrap: wrap;
}
.ns-chapter__num {
  font-family: var(--ns-serif); font-size: 20px; color: var(--ns-accent);
  flex: 0 0 auto; font-variant-numeric: tabular-nums;
}
/* Der alte Block hier setzte .ns-chapter > span:last-child auf display:
   block, damit die Lesezeit UNTER dem Titel stand. Seit die Liste
   einspaltig ist, steht sie rechts daneben, und die Regel dafuer steht
   weiter oben am selben Selektor. Zwei Regeln mit gleichem Selektor, und
   die spaetere gewinnt: die alte hier hat die neue ausgehebelt und die
   Eintraege gemessen 47px statt 24px hoch gemacht. Deshalb ist sie weg. */
.ns-chapter__title {
  display: block; min-width: 0;
  font-family: var(--ns-serif); font-size: 19px; line-height: 1.25; color: #ffffff;
}
.ns-chapter:hover .ns-chapter__title { text-decoration: underline; }
/* Aufgehellt von #8fa6b8 auf #9db4c6: der Grund ist von --ns-ink (#11212e)
   auf --ns-navy (#12395c) gewechselt und damit heller. Gemessen faellt der
   Kontrast dadurch von 6,35:1 auf 4,71:1, mit dem helleren Ton sind es
   wieder 5,54:1. */
.ns-chapter__meta {
  display: block; margin-top: 0; flex: 0 0 auto;
  font-size: 13px; color: #9db4c6;
}


/* ───────────────────────────────────────────────────────────────────────────
   9) Themenbeiträge im Volltext
   Quelle: README §6. Textspalte plus Randspalte mit Lesezeit, Zitat, Tags.
   ─────────────────────────────────────────────────────────────────────────── */
/* Ein Artikel besteht aus mehreren gestapelten Zeilen, je eine Textspalte
   und eine Randspalte. Der Schnitt liegt dort, wo ein Zitat sitzt: so steht
   jedes Zitat genau auf Hoehe seiner Textstelle, ohne dass irgendwo
   gemessen oder nachgerechnet werden muesste. Siehe _nsArtikelHTML() in
   js/seite.js.

   Weil alle Zeilen dieselbe Rasterdefinition tragen, stehen die Spalten
   exakt untereinander, und die Randlinien der Randspalten stossen ohne
   Luecke aneinander und ergeben eine durchgehende Linie. Deshalb hat der
   Artikel KEINEN row-gap. */
.ns-article {
  margin-top: 28px;
  background: var(--ns-surface);
  border: 1px solid var(--ns-line);
  padding: 44px var(--ns-art-pad) 40px;
  display: flex; flex-direction: column;
}

.ns-article__row {
  display: grid;
  grid-template-columns: minmax(0, var(--ns-art-text)) minmax(0, 1fr);
  column-gap: var(--ns-art-luft);
  align-items: stretch;
}

.ns-article__text { min-width: 0; }

/* Gemessener Versatz: das Zitat stand 20px ueber seinem Absatz. Grund ist
   der margin-top von .ns-article__body, der in der ersten Zeile den Abstand
   zum Titel setzt und in jeder weiteren Zeile den Abstand zum Absatz
   darueber, weil .ns-article__body p:last-child seinen margin-bottom
   verliert. Die Randspalte kannte diesen Versatz nicht.

   Die Verschiebung sitzt bewusst als padding-top am Randspaltenkasten und
   nicht als margin: padding liegt INNERHALB des Kastens, die Randlinie
   laeuft also weiter ueber die volle Zeilenhoehe. Ein margin risse dort
   eine 20px-Luecke in die Linie. */
.ns-article__row + .ns-article__row .ns-article__side { padding-top: 20px; }

.ns-article__labels {
  display: flex; align-items: center; gap: 10px; margin-bottom: 14px;
  flex-wrap: wrap;
}
.ns-article__marker { width: 8px; height: 8px; background: var(--ns-gold); flex: 0 0 auto; }

.ns-article__title {
  margin: 0;
  font-family: var(--ns-serif);
  font-size: clamp(26px, 2.4vw, 34px);
  line-height: 1.12; font-weight: 600; letter-spacing: -0.015em;
  color: var(--ns-ink);
  text-wrap: pretty;
  /* Derselbe Deckel wie an .ns-article__body p, und aus demselben Grund: er
     wirkt nur im gestapelten Zustand, wo die Gitterzelle nicht mehr 713px
     breit ist, sondern die volle Kastenbreite. Ohne ihn lief der Titel dort
     bis zu 348px weiter nach rechts als der Text darunter, gemessen bei
     1239px Fensterbreite, und sprang dabei von zwei Zeilen auf eine.
     Im Zweispalter greift der Deckel nicht, dort ist die Zelle ohnehin
     genau 713px breit. */
  max-width: var(--ns-art-text);
}

/* Die Zeilenlaenge steht an zwei Stellen, und beide werden gebraucht: die
   Spaltenbreite --ns-art-text im Raster, und derselbe Wert als max-width an
   den Absaetzen. Der Deckel wirkt nur im gestapelten Zustand, wo es keine
   Spalte mehr gibt. Ohne ihn lief der Absatz dort auf die volle
   Kastenbreite, gemessen 1102px und damit 116,6 Zeichen je Zeile.
   Der fruehere Wert 68ch (608px) ist ersetzt, er laege unter der
   Spaltenbreite und waere im Raster wirkungslos. */
.ns-article__body { margin-top: 20px; }
.ns-article__body p {
  margin: 0 0 18px;
  font-size: 18px; line-height: 1.72; color: var(--ns-body);
  max-width: var(--ns-art-text); text-wrap: pretty;
}
/* 1.72 statt der 1.65 des Entwurfs. Je laenger die Zeile, desto mehr
   Durchschuss braucht sie, damit das Auge beim Ruecksprung die naechste
   Zeile trifft. Der Entwurf rechnete mit 68ch, hier sind es gemessen rund
   81 Zeichen. Wer --ns-art-text weiter zurueckdreht, dreht auch diesen
   Wert zurueck. */
.ns-article__body p:last-child { margin-bottom: 0; }

/* Aufzählungen und Bilder liefert _newsBodyHTML() aus js/render.js, die
   Klassen stammen von dort und werden hier nur neu eingekleidet. */
.ns-article__body .ns-article-list {
  margin: 2px 0 18px 22px; padding: 0; list-style: disc;
  max-width: var(--ns-art-text);
}
.ns-article__body .ns-article-list li {
  font-size: 17px; line-height: 1.6; color: var(--ns-body); margin-bottom: 6px;
}
.ns-article__body .ns-article-img {
  margin: 28px 0 22px; padding: 0;
}
.ns-article__body .ns-article-img img {
  max-width: 100%; max-height: 420px; width: auto; height: auto;
  border: 1px solid var(--ns-line-3);
  display: block;
}

.ns-article__body .ns-interview-header {
  display: flex; align-items: flex-start; gap: 16px; margin: 26px 0 20px;
  padding-top: 22px; border-top: 1px solid var(--ns-line-4);
}
.ns-article__body .ns-interview-portrait {
  width: 84px; height: 84px; object-fit: cover; object-position: top;
  border: 1px solid var(--ns-line-3); flex-shrink: 0;
}
.ns-article__body .ns-interview-byline { display: flex; flex-direction: column; gap: 3px; padding-top: 4px; }
.ns-article__body .ns-interview-name { display: block; font-size: 15px; font-weight: 700; color: var(--ns-ink); }
.ns-article__body .ns-interview-role { display: block; font-size: 13.5px; color: var(--ns-meta); }
.ns-article__body .ns-interview-line {
  margin: 0 0 14px; font-size: 17px; line-height: 1.65; color: var(--ns-body);
  max-width: var(--ns-art-text);
}
.ns-article__body .ns-interview-speaker { font-weight: 700; color: var(--ns-ink); }

/* Die Linie sitzt an der linken Kante der Randspalte, also --ns-art-luft
   rechts vom Text, und derselbe Abstand noch einmal bis zum Randinhalt. */
.ns-article__side {
  min-width: 0;
  border-left: 1px solid var(--ns-line-4);
  padding-left: var(--ns-art-luft);
  display: flex; flex-direction: column; gap: 26px;
}

.ns-article__readtime {
  font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ns-ink); font-weight: 700;
}
.ns-article__edition { margin-top: 5px; font-size: 14px; color: var(--ns-meta); }
/* Das Anfuehrungszeichen ist eine kleine Marke am Rand des Zitats, kein
   Dekorationselement. 26px, also nur fuenf Pixel groesser als der Zitattext
   selbst. Es traegt die Farbe des Zitats und dessen Schrift und faellt
   damit nicht aus dem zurueckhaltenden Ton der Randspalte.

   Die Groesse hat zwei Staende hinter sich, damit niemand einen Kreis
   laeuft: der Export setzte 34px in einem blassen Warmgrau (#c4bfae), das
   ging neben dem Zitat unter. Danach standen 100px in der Zitatfarbe, das
   dominierte die Randspalte und wirkte altmodisch. 26px ist die Mitte:
   sichtbar, weil farbig und fett, aber ohne eigenen Auftritt.

   line-height 0.9 haelt den Kegel knapp, sonst stuende zwischen Zeichen und
   erster Zitatzeile eine halbe Leerzeile. margin-left haengt es zwei Pixel
   ueber den Textanfang hinaus, damit es als Marke VOR dem Zitat steht und
   nicht als erste Glyphe darin.

   Der Block ist ein Flex-Behaelter, und das ist funktional: ohne ihn
   kollabierten die Aussenabstaende des Zeichens mit dem Block, und der
   Block rutschte nach oben. Er ist aber genau auf Hoehe seines Absatzes
   ausgerichtet, siehe _nsArtikelHTML() in js/seite.js. */
.ns-article__quoteblock { align-self: start; display: flex; flex-direction: column; }

.ns-article__quotemark {
  font-family: var(--ns-serif);
  font-size: 26px; line-height: 0.9; font-weight: 700;
  margin-left: -0.08em;
  color: var(--ns-gold);
}

/* Groesser als im Export. Dort sass das Zitat in einer 190px schmalen
   Randspalte, hier in einer bis zu 440px breiten. Bei 18px las es sich dort
   wie eine zweite Textspalte statt wie ein Blickfang. Gemessen ergeben
   21px in 380px rund 39 Zeichen je Zeile, ein Zitat steht damit in sieben
   Zeilen. */
.ns-article__quote {
  margin: 0;
  font-family: var(--ns-serif); font-style: italic;
  font-size: 21px; line-height: 1.5; color: var(--ns-gold);
}
/* Die Tags stehen in der LETZTEN Zeile des Artikels und werden dort nach
   unten geschoben, sitzen also am Fuss der Randspalte. */
.ns-article__tags { margin-top: auto; display: flex; flex-wrap: wrap; gap: 7px; }
.ns-tag {
  border: 1px solid var(--ns-line-3); border-radius: 12px;
  padding: 5px 11px; font-size: 13px; color: var(--ns-ink);
  background: none; cursor: pointer; font-family: inherit;
}
.ns-tag:hover { border-color: var(--ns-navy); color: var(--ns-navy); }


/* ───────────────────────────────────────────────────────────────────────────
   10) Sidebar
   Quelle: README §7.
   ─────────────────────────────────────────────────────────────────────────── */

/* Ausgabe-Karte. Der Außenklick-Handler in js/actions.js prüft per
   composedPath() auf genau diese Klasse, sonst schließt ein Klick ins
   offene Menü dieses sofort wieder. Bis zur Vereinheitlichung der
   Klassenfamilien am 20.09.2026 trug der Wurzelknoten dafür eine zweite
   Klasse nsx-issue, die am selben Element saß und nichts Eigenes tat. */
.ns-issue {
  position: relative;
  background: var(--ns-navy); color: #ffffff;
  padding: 26px 24px;
}
.ns-issue__label {
  font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ns-tint-1); font-weight: 700;
}
.ns-issue__row {
  margin-top: 14px;
  display: flex; align-items: flex-end; justify-content: space-between; gap: 12px;
}
.ns-issue__value {
  font-family: var(--ns-serif); font-size: 38px; line-height: 1; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.ns-issue__month { margin-top: 6px; font-size: 15px; color: var(--ns-tint-2); }
.ns-issue__toggle {
  border: 1px solid rgba(255,255,255,0.3);
  width: 34px; height: 34px; flex: 0 0 auto;
  background: none; color: #ffffff; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; line-height: 1;
}
.ns-issue__toggle:hover { background: rgba(255,255,255,0.12); }
.ns-issue__toggle svg { transition: transform 0.18s ease; }
.ns-issue__toggle[aria-expanded="true"] svg { transform: rotate(180deg); }

/* Der Balken ist reine Anzeige und nichts zum Anfassen. pointer-events:
   none nimmt ihm jede Reaktion auf die Maus, also auch jeden Hover, den er
   sonst von einem Vorfahren erben koennte. Zusammen mit cursor: default und
   dem fehlenden Klickziel ist damit ausgeschlossen, dass er sich als
   Bedienelement anbietet. role="img" und aria-label setzt
   renderNewsIssueBar(). */
.ns-issue__progress {
  margin-top: 20px; display: flex; gap: 6px;
  cursor: default; pointer-events: none; user-select: none;
}
.ns-issue__seg { flex: 1; height: 3px; background: rgba(255,255,255,0.25); }
.ns-issue__seg.is-on { background: var(--ns-accent); }

.ns-issue__search {
  margin-top: 16px; padding-top: 16px; width: 100%;
  border: 0; border-top: 1px solid rgba(255,255,255,0.2);
  background: none; cursor: pointer; font-family: inherit; text-align: left;
  display: flex; align-items: center; gap: 10px;
}
.ns-issue__searchdot {
  width: 13px; height: 13px; flex: 0 0 auto;
  border: 2px solid var(--ns-tint-1); border-radius: 50%;
}
.ns-issue__searchtext { font-size: 15px; color: var(--ns-tint-2); }
.ns-issue__search:hover .ns-issue__searchtext { color: #ffffff; }

/* Ausgabenmenü: Markup unverändert aus _newsIssueMenuHTML() in
   js/render.js, hier nur im Ton dieser Seite eingekleidet. */
.ns-issue .ns-issue__menu {
  position: absolute; top: calc(100% + 2px); left: 0; right: 0;
  z-index: 40;
  background: var(--ns-surface);
  border: 1px solid var(--ns-line-3);
  max-height: 420px; overflow-y: auto;
  padding: 8px;
  color: var(--ns-ink);
}
.ns-issue .ns-issue__group + .ns-issue__group { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--ns-line-4); }
.ns-issue .ns-issue__grouplabel {
  font-size: 10.5px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ns-meta); font-weight: 700; padding: 6px 8px 8px;
}
.ns-issue .ns-issue__item,
.ns-issue .ns-issue__year,
.ns-issue .ns-issue__more {
  width: 100%; display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 8px 10px;
  background: none; border: 0; cursor: pointer; font-family: inherit;
  font-size: 14px; color: var(--ns-ink); text-align: left;
}
.ns-issue .ns-issue__item:hover,
.ns-issue .ns-issue__year:hover,
.ns-issue .ns-issue__more:hover { background: var(--ns-paper); }
.ns-issue .ns-issue__item.is-active { background: var(--ns-navy); color: #ffffff; }
.ns-issue .ns-issue__item.is-active .ns-issue__item-date { color: var(--ns-tint-2); }
.ns-issue .ns-issue__item-date { font-size: 13px; color: var(--ns-meta); font-variant-numeric: tabular-nums; }
.ns-issue .ns-issue__year { font-weight: 700; font-variant-numeric: tabular-nums; }
.ns-issue .ns-issue__more { color: var(--ns-navy); font-weight: 600; margin-top: 2px; }

/* Sidebar-Blöcke */
.ns-block__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; padding-bottom: 12px;
  border-bottom: 2px solid var(--ns-ink);
}
.ns-block__title {
  font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ns-ink); font-weight: 700;
}
.ns-block__title--soft { color: var(--ns-meta); }
.ns-block__count { font-size: 13px; color: var(--ns-meta); font-variant-numeric: tabular-nums; }

/* Suche */
.ns-search { position: relative; padding-top: 16px; }
.ns-search__icon {
  position: absolute; left: 12px; top: 50%; transform: translateY(calc(-50% + 8px));
  color: var(--ns-meta); pointer-events: none;
}
.ns-search__input {
  width: 100%; height: 42px;
  padding: 0 12px 0 36px;
  background: var(--ns-surface);
  border: 1px solid var(--ns-line-3);
  font-family: inherit; font-size: 15px; color: var(--ns-ink);
  border-radius: 0;
}
.ns-search__input::placeholder { color: var(--ns-meta); }
.ns-search__input:focus { outline: 2px solid var(--ns-navy); outline-offset: -2px; }

/* Aktiver Filter als Chip */
/* Deutlich kleiner als zuvor. Der Chip zeigt nur an, was gerade gefiltert
   ist, und ist der zweite Weg zum Zuruecksetzen: der erste ist ein zweiter
   Klick auf den aktiven Eintrag. Vorher stand er auf 13px mit
   7px/8px/7px/12px Innenabstand und einem 20px-Kreuz und war damit fast so
   schwer wie die Pillen daneben.

   Er sitzt jetzt im jeweiligen Block, siehe _nsAktiverFilterHTML() in
   js/seite.js, und der Abstand nach oben ist kleiner, weil er dort
   direkt unter der Blockkopfzeile steht. */
.ns-activefilter {
  margin-top: 10px;
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--ns-navy); color: #ffffff;
  padding: 3px 4px 3px 8px; font-size: 11.5px; line-height: 1.5;
  max-width: 100%;
}
.ns-activefilter strong { font-weight: 700; }
.ns-activefilter__x {
  background: rgba(255,255,255,0.18); border: 0; color: #ffffff;
  width: 15px; height: 15px; flex: 0 0 auto; cursor: pointer;
  font-size: 9px; line-height: 1; font-family: inherit;
  display: inline-flex; align-items: center; justify-content: center;
}
.ns-activefilter__x:hover { background: rgba(255,255,255,0.34); }

/* Themen als Pills. Alle identisch gefärbt, damit neue Themen beliebig
   ergänzt werden können. Quelle: README §7. */
.ns-pills {
  list-style: none; margin: 0; padding: 16px 0 0;
  display: flex; flex-wrap: wrap; gap: 7px;
}
.ns-pill {
  background: var(--ns-surface);
  border: 1px solid var(--ns-line-3);
  border-radius: 12px;
  min-height: 34px; padding: 0 15px;
  display: inline-flex; align-items: center; gap: 8px;
  cursor: pointer; font-family: inherit;
}
.ns-pill:hover { border-color: var(--ns-navy); }
.ns-pill__name  { font-size: 14px; font-weight: 500; color: var(--ns-ink); white-space: nowrap; line-height: 1; }
.ns-pill__count { font-size: 12px; color: var(--ns-meta); line-height: 1; font-variant-numeric: tabular-nums; }
.ns-pill.is-active { background: var(--ns-navy); border-color: var(--ns-navy); }
.ns-pill.is-active .ns-pill__name  { color: #ffffff; }
.ns-pill.is-active .ns-pill__count { color: var(--ns-tint-3); }

/* Gesellschaften als Liste */
.ns-companies { list-style: none; margin: 0; padding: 14px 0 0; }
.ns-company {
  width: 100%;
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid #dfdbd2;
  background: none; border-left: 0; border-right: 0; border-top: 0;
  cursor: pointer; font-family: inherit; text-align: left;
}
.ns-company__name  { font-size: 16px; color: var(--ns-ink); }
.ns-company__count { font-size: 13px; color: var(--ns-meta); font-variant-numeric: tabular-nums; }
.ns-company:hover .ns-company__name { color: var(--ns-navy); text-decoration: underline; }
.ns-company.is-active .ns-company__name { color: var(--ns-navy); font-weight: 700; }

/* "Mehr anzeigen" / "Weniger anzeigen", liefert _newsKurzliste() */
.ns-more {
  margin-top: 14px;
  display: inline-flex; align-items: center; gap: 7px;
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: inherit; font-size: 14px; font-weight: 600; color: var(--ns-navy);
}
.ns-more:hover { text-decoration: underline; }
.ns-more svg { transition: transform 0.18s ease; }
.ns-more.is-open svg { transform: rotate(180deg); }

/* Der angeheftete aktive Eintrag hinter der Kurzliste. */
.ns-pinned { margin-top: 7px; padding-top: 7px; border-top: 1px dashed var(--ns-line-3); width: 100%; }

/* Newsletter-CTA */
.ns-cta { background: var(--ns-accent); color: var(--ns-navy-dark); padding: 26px 24px; }
.ns-cta__title { font-family: var(--ns-serif); font-size: 25px; line-height: 1.2; font-weight: 600; }
.ns-cta__text  { margin: 12px 0 18px; font-size: 15px; line-height: 1.55; color: #123a24; }
.ns-cta__btn {
  width: 100%; background: var(--ns-navy-dark); color: #ffffff;
  text-align: center; padding: 13px 18px; font-size: 15px; font-weight: 600;
  border: 0; cursor: pointer; font-family: inherit;
}
.ns-cta__btn:hover { background: #08223a; }


/* ───────────────────────────────────────────────────────────────────────────
   11) Ergebnisansichten
   Das Markup liefern unverändert _newsSearchResultsHTML(),
   _newsTopicResultsHTML() und _newsGesellschaftResultsHTML() aus
   js/render.js. Hier steht nur die Einkleidung.
   ─────────────────────────────────────────────────────────────────────────── */
.ns-results-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
  padding: 44px 0 18px;
  border-bottom: 3px solid var(--ns-ink);
  font-size: 17px; color: var(--ns-ink);
}
.ns-results-head em { font-style: normal; font-weight: 700; }
.ns-results-head-right { margin-left: auto; }

/* Die Rückkehrzeile über dem Artikel, siehe js/urlzustand.js. Sie sitzt
   über dem Aufmacher und soll dort ein Wegweiser sein, kein zweiter
   Knopf: deshalb keine Fläche, nur Text mit Pfeil. */
.ns-rueckkehr { margin: 0 0 18px; }
.ns-rueckkehr__btn {
  background: none; border: 0; padding: 4px 0;
  font-family: inherit; font-size: 15px; color: var(--ns-navy);
  cursor: pointer; display: inline-flex; align-items: center; gap: 8px;
  border-bottom: 1px solid transparent;
}
.ns-rueckkehr__btn:hover { color: var(--ns-navy-dark); border-bottom-color: var(--ns-navy-dark); }
.ns-rueckkehr__pfeil { font-size: 17px; line-height: 1; }

.ns-filter-clear {
  background: none; border: 1px solid var(--ns-line-3);
  padding: 7px 14px; font-size: 14px; color: var(--ns-navy);
  cursor: pointer; font-family: inherit;
}
.ns-filter-clear:hover { border-color: var(--ns-navy); background: var(--ns-surface); }

.ns-year-filter { display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--ns-meta); }
.ns-year-select {
  font-family: inherit; font-size: 14px; color: var(--ns-ink);
  background: var(--ns-surface); border: 1px solid var(--ns-line-3);
  padding: 6px 10px;
}

.ns-result-card {
  background: var(--ns-surface);
  border: 1px solid var(--ns-line);
  padding: 22px 24px;
  margin-top: 18px;
}
.ns-result-meta {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-bottom: 10px;
}
.ns-result-pill {
  background: var(--ns-ink); color: #ffffff;
  font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase;
  font-weight: 700; padding: 4px 8px;
}
.ns-meta-date { font-size: 13px; color: var(--ns-meta); }
.ns-result-type {
  font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ns-rubric); font-weight: 700;
}
.ns-result-title {
  font-family: var(--ns-serif);
  font-size: 24px; line-height: 1.2; font-weight: 600; color: var(--ns-ink);
}
.ns-result-snippet {
  margin: 10px 0 16px;
  font-size: 16px; line-height: 1.6; color: var(--ns-body-mid);
  max-width: 72ch;
}
.ns-highlight { background: #f6e3a6; color: var(--ns-ink); padding: 0 2px; }

.ns-btn {
  font-family: inherit; cursor: pointer;
  background: var(--ns-navy); color: #ffffff; border: 1px solid var(--ns-navy);
  padding: 9px 16px; font-size: 14px; font-weight: 600;
}
.ns-btn:hover { background: var(--ns-navy-dark); border-color: var(--ns-navy-dark); }
.ns-btn--outline { background: none; color: var(--ns-navy); }
.ns-btn--outline:hover { background: var(--ns-navy); color: #ffffff; }

.ns-empty-state {
  padding: 40px 0; font-size: 16px; color: var(--ns-meta);
}


/* ───────────────────────────────────────────────────────────────────────────
   12) Blättern zwischen den Ausgaben
   Markup unverändert aus renderNewsIssueNav() in js/render.js.
   ─────────────────────────────────────────────────────────────────────────── */
.ns-issuenav {
  margin-top: 40px; padding-top: 28px;
  border-top: 1px solid var(--ns-line-2);
  display: flex; align-items: stretch; justify-content: space-between; gap: 20px;
  flex-wrap: wrap;
}
.ns-issuenav__link {
  display: flex; align-items: center; gap: 12px;
  background: var(--ns-surface); border: 1px solid var(--ns-line);
  padding: 14px 18px; cursor: pointer; font-family: inherit;
  color: var(--ns-ink); max-width: 100%;
}
.ns-issuenav__link:hover { border-color: var(--ns-navy); }
.ns-issuenav__text { display: flex; flex-direction: column; gap: 3px; text-align: left; }
.ns-issuenav__link--next .ns-issuenav__text { text-align: right; }
.ns-issuenav__label {
  font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ns-meta); font-weight: 700;
}
.ns-issuenav__name { font-family: var(--ns-serif); font-size: 19px; font-weight: 600; }
.ns-issuenav__arrow { color: var(--ns-navy); flex: 0 0 auto; }


/* ───────────────────────────────────────────────────────────────────────────
   13) Footer
   Nach dem Vorbild des frueheren zweiteiligen Footers, im Ton dieser Seite.
   ─────────────────────────────────────────────────────────────────────────── */
.ns-trust {
  margin-top: auto;
  background: var(--ns-ink); color: #ffffff;
}
.ns-trust__grid {
  max-width: var(--ns-maxw); margin: 0 auto; padding: 46px 32px;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 32px 40px;
}
.ns-trust__col { display: flex; align-items: flex-start; gap: 14px; }
.ns-trust__icon {
  width: 40px; height: 40px; flex: 0 0 auto;
  border: 1px solid rgba(255,255,255,0.24);
  display: flex; align-items: center; justify-content: center;
  color: var(--ns-accent);
}
.ns-trust__title { font-family: var(--ns-serif); font-size: 19px; font-weight: 600; }
.ns-trust__text  { margin-top: 5px; font-size: 14px; line-height: 1.55; color: #a9bccc; }

.ns-legal { background: var(--ns-navy-dark); color: #c4d9e8; }
.ns-legal__inner {
  max-width: var(--ns-maxw); margin: 0 auto; padding: 18px 32px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 18px; flex-wrap: wrap;
  font-size: 14px;
}
.ns-legal__links { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }
.ns-legal__links button {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: inherit; font-size: 14px; color: #c4d9e8;
  display: inline-flex; align-items: center; gap: 7px;
}
.ns-legal__links button:hover { color: #ffffff; text-decoration: underline; }


/* ───────────────────────────────────────────────────────────────────────────
   13b) Fixierte Sprungknoepfe
   Markup aus _nsSprungKnoepfe() in js/seite.js, angehaengt an document.body
   und damit ausserhalb von #app.

   z-index 60 ordnet sie in die vorhandene Staffelung ein: ueber dem Panel der
   Kennzahlkarte (30) und dem Ausgabenmenue (40), unter den Dialogen (9000)
   und dem Hinweis-Toast (9999). Ein Dialog darf nicht hinter zwei Knoepfen
   liegen.

   visibility statt nur opacity im versteckten Zustand: mit opacity: 0 allein
   blieben die Knoepfe anklickbar und mit der Tastatur erreichbar, obwohl sie
   niemand sieht.
   ─────────────────────────────────────────────────────────────────────────── */
.ns-sprung {
  position: fixed; right: 24px; bottom: 24px; z-index: 60;
  display: flex; flex-direction: column; gap: 1px;
  opacity: 0; visibility: hidden;
  transform: translateY(8px);
  transition: opacity 0.22s ease, transform 0.22s ease, visibility 0.22s;
}
.ns-sprung.is-sichtbar { opacity: 1; visibility: visible; transform: none; }

.ns-sprung__btn {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 34px; padding: 0 13px 0 11px;
  background: var(--ns-navy); color: #ffffff;
  border: 0; cursor: pointer;
  font-family: inherit; font-size: 12.5px; font-weight: 600;
  letter-spacing: 0.02em; white-space: nowrap;
}
.ns-sprung__btn:hover { background: var(--ns-navy-dark); color: var(--ns-accent); }
.ns-sprung__btn:focus-visible { outline: 2px solid var(--ns-accent); outline-offset: 2px; }

/* Auf Telefonbreiten nur die Zeichen, sonst nehmen die Knoepfe ein Viertel
   der Bildbreite ein. Die Beschriftung bleibt im Markup stehen und wird nur
   optisch ausgeblendet, nicht per display: none. Damit bleibt sie der
   zugaengliche Name des Knopfes, ein aria-label braucht es nicht. */
@media (max-width: 560px) {
  .ns-sprung { right: 14px; bottom: 14px; }
  .ns-sprung__btn { padding: 0; width: 34px; justify-content: center; gap: 0; }
  .ns-sprung__btn span { position: absolute; width: 1px; height: 1px; overflow: hidden;
                         clip-path: inset(50%); white-space: nowrap; }
}

@media (prefers-reduced-motion: reduce) {
  .ns-sprung { transition: none; transform: none; }
}


/* ───────────────────────────────────────────────────────────────────────────
   14) Flash-Highlight
   Übernommen aus dem früheren css/news.css, das diese Seite nie geladen hat.
   openNewsIssueAt() setzt .ns-flash-target. Der PDF-Toast, der hier
   danebenstand, ist mit dem Platzhalter entfallen.
   ─────────────────────────────────────────────────────────────────────────── */
@keyframes ns-flash-in {
  0%   { background-color: #fdf0c4; }
  55%  { background-color: #fdf0c4; }
  100% { background-color: transparent; }
}
.ns-flash-target { animation: ns-flash-in 1.8s ease-out forwards; }


/* ───────────────────────────────────────────────────────────────────────────
   15) Schmale Viewports
   Der Export arbeitet bewusst ohne Media Queries, alles bricht über
   auto-fit und flex-wrap um. Die wenigen Regeln hier fangen nur die
   Innenabstände ab, die bei 420px sonst zu groß stehen.
   ─────────────────────────────────────────────────────────────────────────── */
/* Zwischenstufe: die Randspalte steht noch als Spalte, ist aber schon
   schmal. Gerechnet bleiben dem Randinhalt (Fensterbreite - 961) Pixel,
   bei 1321px also 360, bei 1240px noch 279. Dort geraten 21px zu eng,
   gemessen laeuft das laengste Zitat der Ausgabe dann auf neun Zeilen.
   Die Grenzen sind mit der Textspalte gewandert: bei 770px Textspalte lag
   dieselbe Stufe zwischen 1280 und 1379px.
   Bewusst mit min-width abgegrenzt: unterhalb von 1240px ist gestapelt,
   dort hat das Zitat wieder die volle Kastenbreite und darf gross bleiben. */
@media (min-width: 1240px) and (max-width: 1320px) {
  .ns-article__quote     { font-size: 18px; }
  .ns-article__quotemark { font-size: 23px; }
}

/* Die Textspalte ist gesetzt, die Randspur nimmt den Rest. Damit schrumpft
   beim Verkleinern zuerst die Randspalte, und der Fliesstext bleibt bei
   seinen 713px. Ab hier bliebe dem Randinhalt weniger als rund 280px, und
   das ist zu wenig: bei 1200px Fensterbreite blieben ihm 237px, und das
   laengste Zitat der Ausgabe lief dort gemessen auf ELF Zeilen. Dann ist
   Stapeln besser als Quetschen, gestapelt steht dasselbe Zitat in fuenf
   Zeilen ueber die volle Kastenbreite.

   Der Punkt wandert mit der Textspalte: 620px Text -> 1080px, 770px Text
   -> 1280px, 713px Text -> 1240px. Wer --ns-art-text aendert, misst die
   Zeilenzahl des laengsten Zitats nach, statt die Grenze zu rechnen: sie
   haengt auch an der Zitatlaenge und an der Schriftgroesse der Stufe.

   Gestapelt stehen Lesezeit, Zitate und Tags jeweils unter ihrem
   Textabschnitt, die Zitate also weiterhin an ihrer Textstelle. Der Deckel
   an den Absaetzen haelt dort die Zeilenlaenge. */
@media (max-width: 1239px) {
  .ns-article__row  { grid-template-columns: minmax(0, 1fr); }
  .ns-article__row + .ns-article__row .ns-article__side { padding-top: 20px; }
  .ns-article__side {
    border-left: 0; padding-left: 0;
    border-top: 1px solid var(--ns-line-4);
    margin: 6px 0 26px; padding-top: 20px;
    flex-direction: row; flex-wrap: wrap; gap: 18px 32px;
    align-items: flex-start;
  }
  .ns-article__row:last-child .ns-article__side { margin-bottom: 0; }
  .ns-article__tags { margin-top: 0; }
  /* min-width:0 ist hier kein Beiwerk. Ein Flex-Element schrumpft per
     min-width:auto nie unter seine min-content-Breite, also nie unter sein
     laengstes Wort. Ein Zitat mit einem Link darin war so gemessen 371px
     breit in einem 274px breiten Kasten und schob die ganze Seite nach
     rechts. Der Umbruch aus der body-Regel half dort nicht: zu breit war
     der Kasten, nicht sein Text. */
  .ns-article__quoteblock { flex: 1 1 320px; min-width: 0; }
}

@media (max-width: 640px) {
  .ns-topbar__inner { padding: 10px 20px; }
  .ns-hero__inner   { padding: 28px 20px 26px; }
  .ns-hero__metainner { padding: 10px 20px; gap: 18px; }
  .ns-wrap          { padding: 0 20px 64px; gap: 36px; }
  .ns-chapters      { padding: 28px 22px; }
  .ns-article       { padding: 26px 22px 24px; }
  .ns-trust__grid   { padding: 34px 20px; }
  .ns-legal__inner  { padding: 16px 20px; }
  .ns-consent__inner { padding: 18px 20px; }
}


/* ───────────────────────────────────────────────────────────────────────────
   Cookie-Banner

   Sitzt unten am Fensterrand statt ueber der ganzen Seite. Gemessen wird
   hier nichts Heikles, und ein Vorhang ueber dem Inhalt nimmt dem Leser den
   Blick auf das, wofuer er gekommen ist. Die Seite bleibt bedienbar.

   Die beiden Knoepfe sind ABSICHTLICH gleich gestaltet: gleiche Groesse,
   gleiche Farbe, gleiche Schrift. Nur die Reihenfolge unterscheidet sie, und
   "Ablehnen" steht sogar zuerst. Ein dunkel gefuelltes "Akzeptieren" neben
   einem blassen "Ablehnen" waere die uebliche Schieflage.

   Markup steht in index.html, das Ein- und Ausblenden macht js/consent.js
   ueber das hidden-Attribut. Das [hidden]-Verhalten steht in css/base.css
   nicht drin, deshalb hier die eigene Regel: ohne sie zeigt display:flex
   das Banner trotz hidden.
   ─────────────────────────────────────────────────────────────────────────── */
.ns-consent {
  position: fixed; inset: auto 0 0 0;
  z-index: 60;
  background: var(--ns-ink);
  color: #ffffff;
  border-top: 3px solid var(--ns-accent);
  box-shadow: 0 -8px 30px rgba(7, 26, 44, 0.28);
}
.ns-consent[hidden] { display: none; }

.ns-consent__inner {
  max-width: var(--ns-maxw);
  margin: 0 auto;
  padding: 20px 32px;
  display: flex; align-items: center; gap: 28px; flex-wrap: wrap;
}
.ns-consent__text { flex: 1 1 380px; }
.ns-consent__titel {
  font-family: var(--ns-serif);
  font-size: 19px; font-weight: 600; letter-spacing: -0.01em;
  margin-bottom: 6px;
}
.ns-consent__text p {
  font-size: 14px; line-height: 1.55; color: var(--ns-tint-2);
  max-width: 78ch;
}
/* Der Verweis auf den Datenschutz ist ein Knopf und kein <a>, weil er
   keine Adresse ansteuert, sondern einen Dialog öffnet. Aussehen soll er
   trotzdem wie ein Link im Fließtext, deshalb wird die Knopfgestaltung
   hier vollständig zurückgenommen. Weiß statt --ns-tint-2, damit er sich
   vom umgebenden Text abhebt. */
.ns-consent__link {
  font: inherit;
  color: #ffffff;
  background: none;
  border: 0;
  padding: 0;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.ns-consent__link:hover { color: var(--ns-accent); }
.ns-consent__link:focus-visible { outline: 3px solid var(--ns-accent); outline-offset: 2px; }

.ns-consent__knoepfe {
  display: flex; gap: 12px; flex: 0 0 auto;
}
.ns-consent__knopf {
  min-width: 148px;
  padding: 11px 22px;
  font: inherit; font-size: 15px; font-weight: 600;
  color: var(--ns-ink);
  background: #ffffff;
  border: 1px solid #ffffff;
  cursor: pointer;
}
.ns-consent__knopf:hover { background: var(--ns-accent); border-color: var(--ns-accent); }
.ns-consent__knopf:focus-visible { outline: 3px solid var(--ns-accent); outline-offset: 2px; }

@media (max-width: 560px) {
  .ns-consent__knoepfe { width: 100%; }
  .ns-consent__knopf { flex: 1 1 0; min-width: 0; }
}

